1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/net/proxy_policy_handler.h"
7 #include "base/logging.h"
8 #include "base/prefs/pref_value_map.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/values.h"
11 #include "chrome/common/pref_names.h"
12 #include "components/policy/core/browser/configuration_policy_handler.h"
13 #include "components/policy/core/browser/policy_error_map.h"
14 #include "components/policy/core/common/policy_map.h"
15 #include "components/proxy_config/proxy_config_dictionary.h"
16 #include "components/proxy_config/proxy_config_pref_names.h"
17 #include "grit/components_strings.h"
18 #include "policy/policy_constants.h"
22 // This is used to check whether for a given ProxyMode value, the ProxyPacUrl,
23 // the ProxyBypassList and the ProxyServer policies are allowed to be specified.
24 // |error_message_id| is the message id of the localized error message to show
25 // when the policies are not specified as allowed. Each value of ProxyMode
26 // has a ProxyModeValidationEntry in the |kProxyModeValidationMap| below.
27 struct ProxyModeValidationEntry
{
28 const char* mode_value
;
30 bool bypass_list_allowed
;
35 // List of entries determining which proxy policies can be specified, depending
37 const ProxyModeValidationEntry kProxyModeValidationMap
[] = {
38 { ProxyPrefs::kDirectProxyModeName
,
39 false, false, false, IDS_POLICY_PROXY_MODE_DISABLED_ERROR
},
40 { ProxyPrefs::kAutoDetectProxyModeName
,
41 false, false, false, IDS_POLICY_PROXY_MODE_AUTO_DETECT_ERROR
},
42 { ProxyPrefs::kPacScriptProxyModeName
,
43 true, false, false, IDS_POLICY_PROXY_MODE_PAC_URL_ERROR
},
44 { ProxyPrefs::kFixedServersProxyModeName
,
45 false, true, true, IDS_POLICY_PROXY_MODE_FIXED_SERVERS_ERROR
},
46 { ProxyPrefs::kSystemProxyModeName
,
47 false, false, false, IDS_POLICY_PROXY_MODE_SYSTEM_ERROR
},
54 // The proxy policies have the peculiarity that they are loaded from individual
55 // policies, but the providers then expose them through a unified
56 // DictionaryValue. Once Dictionary policies are fully supported, the individual
57 // proxy policies will be deprecated. http://crbug.com/108996
59 ProxyPolicyHandler::ProxyPolicyHandler() {}
61 ProxyPolicyHandler::~ProxyPolicyHandler() {
64 bool ProxyPolicyHandler::CheckPolicySettings(const PolicyMap
& policies
,
65 PolicyErrorMap
* errors
) {
66 const base::Value
* mode
= GetProxyPolicyValue(policies
, key::kProxyMode
);
67 const base::Value
* server
= GetProxyPolicyValue(policies
, key::kProxyServer
);
68 const base::Value
* server_mode
=
69 GetProxyPolicyValue(policies
, key::kProxyServerMode
);
70 const base::Value
* pac_url
= GetProxyPolicyValue(policies
, key::kProxyPacUrl
);
71 const base::Value
* bypass_list
=
72 GetProxyPolicyValue(policies
, key::kProxyBypassList
);
74 if ((server
|| pac_url
|| bypass_list
) && !(mode
|| server_mode
)) {
75 errors
->AddError(key::kProxySettings
,
77 IDS_POLICY_NOT_SPECIFIED_ERROR
);
81 std::string mode_value
;
82 if (!CheckProxyModeAndServerMode(policies
, errors
, &mode_value
))
85 // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be
86 // empty and the proxy shouldn't be configured at all.
87 if (mode_value
.empty())
90 bool is_valid_mode
= false;
91 for (size_t i
= 0; i
!= arraysize(kProxyModeValidationMap
); ++i
) {
92 const ProxyModeValidationEntry
& entry
= kProxyModeValidationMap
[i
];
93 if (entry
.mode_value
!= mode_value
)
98 if (!entry
.pac_url_allowed
&& pac_url
) {
99 errors
->AddError(key::kProxySettings
,
101 entry
.error_message_id
);
103 if (!entry
.bypass_list_allowed
&& bypass_list
) {
104 errors
->AddError(key::kProxySettings
,
105 key::kProxyBypassList
,
106 entry
.error_message_id
);
108 if (!entry
.server_allowed
&& server
) {
109 errors
->AddError(key::kProxySettings
,
111 entry
.error_message_id
);
114 if ((!entry
.pac_url_allowed
&& pac_url
) ||
115 (!entry
.bypass_list_allowed
&& bypass_list
) ||
116 (!entry
.server_allowed
&& server
)) {
121 if (!is_valid_mode
) {
122 errors
->AddError(key::kProxySettings
,
123 mode
? key::kProxyMode
: key::kProxyServerMode
,
124 IDS_POLICY_OUT_OF_RANGE_ERROR
,
131 void ProxyPolicyHandler::ApplyPolicySettings(const PolicyMap
& policies
,
132 PrefValueMap
* prefs
) {
133 const base::Value
* mode
= GetProxyPolicyValue(policies
, key::kProxyMode
);
134 const base::Value
* server
= GetProxyPolicyValue(policies
, key::kProxyServer
);
135 const base::Value
* server_mode
=
136 GetProxyPolicyValue(policies
, key::kProxyServerMode
);
137 const base::Value
* pac_url
= GetProxyPolicyValue(policies
, key::kProxyPacUrl
);
138 const base::Value
* bypass_list
=
139 GetProxyPolicyValue(policies
, key::kProxyBypassList
);
141 ProxyPrefs::ProxyMode proxy_mode
;
143 std::string string_mode
;
144 CHECK(mode
->GetAsString(&string_mode
));
145 CHECK(ProxyPrefs::StringToProxyMode(string_mode
, &proxy_mode
));
146 } else if (server_mode
) {
148 CHECK(server_mode
->GetAsInteger(&int_mode
));
151 case PROXY_SERVER_MODE
:
152 proxy_mode
= ProxyPrefs::MODE_DIRECT
;
154 case PROXY_AUTO_DETECT_PROXY_SERVER_MODE
:
155 proxy_mode
= ProxyPrefs::MODE_AUTO_DETECT
;
157 case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE
:
158 proxy_mode
= ProxyPrefs::MODE_FIXED_SERVERS
;
160 proxy_mode
= ProxyPrefs::MODE_PAC_SCRIPT
;
162 case PROXY_USE_SYSTEM_PROXY_SERVER_MODE
:
163 proxy_mode
= ProxyPrefs::MODE_SYSTEM
;
166 proxy_mode
= ProxyPrefs::MODE_DIRECT
;
173 switch (proxy_mode
) {
174 case ProxyPrefs::MODE_DIRECT
:
175 prefs
->SetValue(proxy_config::prefs::kProxy
,
176 make_scoped_ptr(ProxyConfigDictionary::CreateDirect()));
178 case ProxyPrefs::MODE_AUTO_DETECT
:
180 proxy_config::prefs::kProxy
,
181 make_scoped_ptr(ProxyConfigDictionary::CreateAutoDetect()));
183 case ProxyPrefs::MODE_PAC_SCRIPT
: {
184 std::string pac_url_string
;
185 if (pac_url
&& pac_url
->GetAsString(&pac_url_string
)) {
186 prefs
->SetValue(proxy_config::prefs::kProxy
,
187 make_scoped_ptr(ProxyConfigDictionary::CreatePacScript(
188 pac_url_string
, false)));
194 case ProxyPrefs::MODE_FIXED_SERVERS
: {
195 std::string proxy_server
;
196 std::string bypass_list_string
;
197 if (server
->GetAsString(&proxy_server
)) {
199 bypass_list
->GetAsString(&bypass_list_string
);
201 proxy_config::prefs::kProxy
,
202 make_scoped_ptr(ProxyConfigDictionary::CreateFixedServers(
203 proxy_server
, bypass_list_string
)));
207 case ProxyPrefs::MODE_SYSTEM
:
208 prefs
->SetValue(proxy_config::prefs::kProxy
,
209 make_scoped_ptr(ProxyConfigDictionary::CreateSystem()));
211 case ProxyPrefs::kModeCount
:
216 const base::Value
* ProxyPolicyHandler::GetProxyPolicyValue(
217 const PolicyMap
& policies
, const char* policy_name
) {
218 // See note on the ProxyPolicyHandler implementation above.
219 const base::Value
* value
= policies
.GetValue(key::kProxySettings
);
220 const base::DictionaryValue
* settings
;
221 if (!value
|| !value
->GetAsDictionary(&settings
))
224 const base::Value
* policy_value
= NULL
;
226 if (!settings
->Get(policy_name
, &policy_value
) ||
227 policy_value
->IsType(base::Value::TYPE_NULL
) ||
228 (policy_value
->IsType(base::Value::TYPE_STRING
) &&
229 policy_value
->GetAsString(&tmp
) &&
236 bool ProxyPolicyHandler::CheckProxyModeAndServerMode(const PolicyMap
& policies
,
237 PolicyErrorMap
* errors
,
238 std::string
* mode_value
) {
239 const base::Value
* mode
= GetProxyPolicyValue(policies
, key::kProxyMode
);
240 const base::Value
* server
= GetProxyPolicyValue(policies
, key::kProxyServer
);
241 const base::Value
* server_mode
=
242 GetProxyPolicyValue(policies
, key::kProxyServerMode
);
243 const base::Value
* pac_url
= GetProxyPolicyValue(policies
, key::kProxyPacUrl
);
245 // If there's a server mode, convert it into a mode.
246 // When both are specified, the mode takes precedence.
249 errors
->AddError(key::kProxySettings
,
250 key::kProxyServerMode
,
251 IDS_POLICY_OVERRIDDEN
,
254 if (!mode
->GetAsString(mode_value
)) {
255 errors
->AddError(key::kProxySettings
,
257 IDS_POLICY_TYPE_ERROR
,
258 ValueTypeToString(base::Value::TYPE_BOOLEAN
));
262 ProxyPrefs::ProxyMode mode
;
263 if (!ProxyPrefs::StringToProxyMode(*mode_value
, &mode
)) {
264 errors
->AddError(key::kProxySettings
,
266 IDS_POLICY_INVALID_PROXY_MODE_ERROR
);
270 if (mode
== ProxyPrefs::MODE_PAC_SCRIPT
&& !pac_url
) {
271 errors
->AddError(key::kProxySettings
,
273 IDS_POLICY_NOT_SPECIFIED_ERROR
);
275 } else if (mode
== ProxyPrefs::MODE_FIXED_SERVERS
&& !server
) {
276 errors
->AddError(key::kProxySettings
,
278 IDS_POLICY_NOT_SPECIFIED_ERROR
);
281 } else if (server_mode
) {
282 int server_mode_value
;
283 if (!server_mode
->GetAsInteger(&server_mode_value
)) {
284 errors
->AddError(key::kProxySettings
,
285 key::kProxyServerMode
,
286 IDS_POLICY_TYPE_ERROR
,
287 ValueTypeToString(base::Value::TYPE_INTEGER
));
291 switch (server_mode_value
) {
292 case PROXY_SERVER_MODE
:
293 *mode_value
= ProxyPrefs::kDirectProxyModeName
;
295 case PROXY_AUTO_DETECT_PROXY_SERVER_MODE
:
296 *mode_value
= ProxyPrefs::kAutoDetectProxyModeName
;
298 case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE
:
299 if (server
&& pac_url
) {
300 int message_id
= IDS_POLICY_PROXY_BOTH_SPECIFIED_ERROR
;
301 errors
->AddError(key::kProxySettings
,
304 errors
->AddError(key::kProxySettings
,
309 if (!server
&& !pac_url
) {
310 int message_id
= IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR
;
311 errors
->AddError(key::kProxySettings
,
314 errors
->AddError(key::kProxySettings
,
320 *mode_value
= ProxyPrefs::kPacScriptProxyModeName
;
322 *mode_value
= ProxyPrefs::kFixedServersProxyModeName
;
324 case PROXY_USE_SYSTEM_PROXY_SERVER_MODE
:
325 *mode_value
= ProxyPrefs::kSystemProxyModeName
;
328 errors
->AddError(key::kProxySettings
,
329 key::kProxyServerMode
,
330 IDS_POLICY_OUT_OF_RANGE_ERROR
,
331 base::IntToString(server_mode_value
));
338 } // namespace policy