xref: /aosp_15_r20/external/cronet/base/environment.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/environment.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <array>
8*6777b538SAndroid Build Coastguard Worker #include <string_view>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
13*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
16*6777b538SAndroid Build Coastguard Worker #include <windows.h>
17*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
18*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
19*6777b538SAndroid Build Coastguard Worker #endif
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker namespace base {
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker namespace {
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker class EnvironmentImpl : public Environment {
26*6777b538SAndroid Build Coastguard Worker  public:
GetVar(std::string_view variable_name,std::string * result)27*6777b538SAndroid Build Coastguard Worker   bool GetVar(std::string_view variable_name, std::string* result) override {
28*6777b538SAndroid Build Coastguard Worker     if (GetVarImpl(variable_name, result))
29*6777b538SAndroid Build Coastguard Worker       return true;
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker     // Some commonly used variable names are uppercase while others
32*6777b538SAndroid Build Coastguard Worker     // are lowercase, which is inconsistent. Let's try to be helpful
33*6777b538SAndroid Build Coastguard Worker     // and look for a variable name with the reverse case.
34*6777b538SAndroid Build Coastguard Worker     // I.e. HTTP_PROXY may be http_proxy for some users/systems.
35*6777b538SAndroid Build Coastguard Worker     char first_char = variable_name[0];
36*6777b538SAndroid Build Coastguard Worker     std::string alternate_case_var;
37*6777b538SAndroid Build Coastguard Worker     if (IsAsciiLower(first_char))
38*6777b538SAndroid Build Coastguard Worker       alternate_case_var = ToUpperASCII(variable_name);
39*6777b538SAndroid Build Coastguard Worker     else if (IsAsciiUpper(first_char))
40*6777b538SAndroid Build Coastguard Worker       alternate_case_var = ToLowerASCII(variable_name);
41*6777b538SAndroid Build Coastguard Worker     else
42*6777b538SAndroid Build Coastguard Worker       return false;
43*6777b538SAndroid Build Coastguard Worker     return GetVarImpl(alternate_case_var, result);
44*6777b538SAndroid Build Coastguard Worker   }
45*6777b538SAndroid Build Coastguard Worker 
SetVar(std::string_view variable_name,const std::string & new_value)46*6777b538SAndroid Build Coastguard Worker   bool SetVar(std::string_view variable_name,
47*6777b538SAndroid Build Coastguard Worker               const std::string& new_value) override {
48*6777b538SAndroid Build Coastguard Worker     return SetVarImpl(variable_name, new_value);
49*6777b538SAndroid Build Coastguard Worker   }
50*6777b538SAndroid Build Coastguard Worker 
UnSetVar(std::string_view variable_name)51*6777b538SAndroid Build Coastguard Worker   bool UnSetVar(std::string_view variable_name) override {
52*6777b538SAndroid Build Coastguard Worker     return UnSetVarImpl(variable_name);
53*6777b538SAndroid Build Coastguard Worker   }
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker  private:
GetVarImpl(std::string_view variable_name,std::string * result)56*6777b538SAndroid Build Coastguard Worker   bool GetVarImpl(std::string_view variable_name, std::string* result) {
57*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
58*6777b538SAndroid Build Coastguard Worker     std::wstring wide_name = UTF8ToWide(variable_name);
59*6777b538SAndroid Build Coastguard Worker     if (!result) {
60*6777b538SAndroid Build Coastguard Worker       return ::GetEnvironmentVariable(wide_name.c_str(), nullptr, 0) != 0;
61*6777b538SAndroid Build Coastguard Worker     }
62*6777b538SAndroid Build Coastguard Worker     // Documented to be the maximum environment variable size.
63*6777b538SAndroid Build Coastguard Worker     std::array<wchar_t, 32767> value;
64*6777b538SAndroid Build Coastguard Worker     DWORD value_length =
65*6777b538SAndroid Build Coastguard Worker         ::GetEnvironmentVariable(wide_name.c_str(), value.data(), value.size());
66*6777b538SAndroid Build Coastguard Worker     if (value_length == 0) {
67*6777b538SAndroid Build Coastguard Worker       return false;
68*6777b538SAndroid Build Coastguard Worker     }
69*6777b538SAndroid Build Coastguard Worker     CHECK_LE(value_length, value.size() - 1)
70*6777b538SAndroid Build Coastguard Worker         << "value should fit in the buffer (including the null terminator)";
71*6777b538SAndroid Build Coastguard Worker     WideToUTF8(value.data(), value_length, result);
72*6777b538SAndroid Build Coastguard Worker     return true;
73*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
74*6777b538SAndroid Build Coastguard Worker     const char* env_value = getenv(std::string(variable_name).c_str());
75*6777b538SAndroid Build Coastguard Worker     if (!env_value)
76*6777b538SAndroid Build Coastguard Worker       return false;
77*6777b538SAndroid Build Coastguard Worker     // Note that the variable may be defined but empty.
78*6777b538SAndroid Build Coastguard Worker     if (result)
79*6777b538SAndroid Build Coastguard Worker       *result = env_value;
80*6777b538SAndroid Build Coastguard Worker     return true;
81*6777b538SAndroid Build Coastguard Worker #endif
82*6777b538SAndroid Build Coastguard Worker   }
83*6777b538SAndroid Build Coastguard Worker 
SetVarImpl(std::string_view variable_name,const std::string & new_value)84*6777b538SAndroid Build Coastguard Worker   bool SetVarImpl(std::string_view variable_name,
85*6777b538SAndroid Build Coastguard Worker                   const std::string& new_value) {
86*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
87*6777b538SAndroid Build Coastguard Worker     // On success, a nonzero value is returned.
88*6777b538SAndroid Build Coastguard Worker     return !!SetEnvironmentVariable(UTF8ToWide(variable_name).c_str(),
89*6777b538SAndroid Build Coastguard Worker                                     UTF8ToWide(new_value).c_str());
90*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
91*6777b538SAndroid Build Coastguard Worker     // On success, zero is returned.
92*6777b538SAndroid Build Coastguard Worker     return !setenv(variable_name.data(), new_value.c_str(), 1);
93*6777b538SAndroid Build Coastguard Worker #endif
94*6777b538SAndroid Build Coastguard Worker   }
95*6777b538SAndroid Build Coastguard Worker 
UnSetVarImpl(std::string_view variable_name)96*6777b538SAndroid Build Coastguard Worker   bool UnSetVarImpl(std::string_view variable_name) {
97*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
98*6777b538SAndroid Build Coastguard Worker     // On success, a nonzero value is returned.
99*6777b538SAndroid Build Coastguard Worker     return !!SetEnvironmentVariable(UTF8ToWide(variable_name).c_str(), nullptr);
100*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
101*6777b538SAndroid Build Coastguard Worker     // On success, zero is returned.
102*6777b538SAndroid Build Coastguard Worker     return !unsetenv(variable_name.data());
103*6777b538SAndroid Build Coastguard Worker #endif
104*6777b538SAndroid Build Coastguard Worker   }
105*6777b538SAndroid Build Coastguard Worker };
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker }  // namespace
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker namespace env_vars {
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
112*6777b538SAndroid Build Coastguard Worker // On Posix systems, this variable contains the location of the user's home
113*6777b538SAndroid Build Coastguard Worker // directory. (e.g, /home/username/).
114*6777b538SAndroid Build Coastguard Worker const char kHome[] = "HOME";
115*6777b538SAndroid Build Coastguard Worker #endif
116*6777b538SAndroid Build Coastguard Worker 
117*6777b538SAndroid Build Coastguard Worker }  // namespace env_vars
118*6777b538SAndroid Build Coastguard Worker 
119*6777b538SAndroid Build Coastguard Worker Environment::~Environment() = default;
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker // static
Create()122*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Environment> Environment::Create() {
123*6777b538SAndroid Build Coastguard Worker   return std::make_unique<EnvironmentImpl>();
124*6777b538SAndroid Build Coastguard Worker }
125*6777b538SAndroid Build Coastguard Worker 
HasVar(std::string_view variable_name)126*6777b538SAndroid Build Coastguard Worker bool Environment::HasVar(std::string_view variable_name) {
127*6777b538SAndroid Build Coastguard Worker   return GetVar(variable_name, nullptr);
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker 
130*6777b538SAndroid Build Coastguard Worker }  // namespace base
131