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