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/browser/prefs/proxy_config_dictionary.h"
12 #include "chrome/browser/prefs/proxy_prefs.h"
13 #include "chrome/common/pref_names.h"
14 #include "components/policy/core/browser/configuration_policy_handler.h"
15 #include "components/policy/core/browser/policy_error_map.h"
16 #include "components/policy/core/common/policy_map.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(prefs::kProxy
, ProxyConfigDictionary::CreateDirect());
177 case ProxyPrefs::MODE_AUTO_DETECT
:
178 prefs
->SetValue(prefs::kProxy
, ProxyConfigDictionary::CreateAutoDetect());
180 case ProxyPrefs::MODE_PAC_SCRIPT
: {
181 std::string pac_url_string
;
182 if (pac_url
&& pac_url
->GetAsString(&pac_url_string
)) {
185 ProxyConfigDictionary::CreatePacScript(pac_url_string
, false));
191 case ProxyPrefs::MODE_FIXED_SERVERS
: {
192 std::string proxy_server
;
193 std::string bypass_list_string
;
194 if (server
->GetAsString(&proxy_server
)) {
196 bypass_list
->GetAsString(&bypass_list_string
);
197 prefs
->SetValue(prefs::kProxy
,
198 ProxyConfigDictionary::CreateFixedServers(
199 proxy_server
, bypass_list_string
));
203 case ProxyPrefs::MODE_SYSTEM
:
204 prefs
->SetValue(prefs::kProxy
, ProxyConfigDictionary::CreateSystem());
206 case ProxyPrefs::kModeCount
:
211 const base::Value
* ProxyPolicyHandler::GetProxyPolicyValue(
212 const PolicyMap
& policies
, const char* policy_name
) {
213 // See note on the ProxyPolicyHandler implementation above.
214 const base::Value
* value
= policies
.GetValue(key::kProxySettings
);
215 const base::DictionaryValue
* settings
;
216 if (!value
|| !value
->GetAsDictionary(&settings
))
219 const base::Value
* policy_value
= NULL
;
221 if (!settings
->Get(policy_name
, &policy_value
) ||
222 policy_value
->IsType(base::Value::TYPE_NULL
) ||
223 (policy_value
->IsType(base::Value::TYPE_STRING
) &&
224 policy_value
->GetAsString(&tmp
) &&
231 bool ProxyPolicyHandler::CheckProxyModeAndServerMode(const PolicyMap
& policies
,
232 PolicyErrorMap
* errors
,
233 std::string
* mode_value
) {
234 const base::Value
* mode
= GetProxyPolicyValue(policies
, key::kProxyMode
);
235 const base::Value
* server
= GetProxyPolicyValue(policies
, key::kProxyServer
);
236 const base::Value
* server_mode
=
237 GetProxyPolicyValue(policies
, key::kProxyServerMode
);
238 const base::Value
* pac_url
= GetProxyPolicyValue(policies
, key::kProxyPacUrl
);
240 // If there's a server mode, convert it into a mode.
241 // When both are specified, the mode takes precedence.
244 errors
->AddError(key::kProxySettings
,
245 key::kProxyServerMode
,
246 IDS_POLICY_OVERRIDDEN
,
249 if (!mode
->GetAsString(mode_value
)) {
250 errors
->AddError(key::kProxySettings
,
252 IDS_POLICY_TYPE_ERROR
,
253 ValueTypeToString(base::Value::TYPE_BOOLEAN
));
257 ProxyPrefs::ProxyMode mode
;
258 if (!ProxyPrefs::StringToProxyMode(*mode_value
, &mode
)) {
259 errors
->AddError(key::kProxySettings
,
261 IDS_POLICY_INVALID_PROXY_MODE_ERROR
);
265 if (mode
== ProxyPrefs::MODE_PAC_SCRIPT
&& !pac_url
) {
266 errors
->AddError(key::kProxySettings
,
268 IDS_POLICY_NOT_SPECIFIED_ERROR
);
270 } else if (mode
== ProxyPrefs::MODE_FIXED_SERVERS
&& !server
) {
271 errors
->AddError(key::kProxySettings
,
273 IDS_POLICY_NOT_SPECIFIED_ERROR
);
276 } else if (server_mode
) {
277 int server_mode_value
;
278 if (!server_mode
->GetAsInteger(&server_mode_value
)) {
279 errors
->AddError(key::kProxySettings
,
280 key::kProxyServerMode
,
281 IDS_POLICY_TYPE_ERROR
,
282 ValueTypeToString(base::Value::TYPE_INTEGER
));
286 switch (server_mode_value
) {
287 case PROXY_SERVER_MODE
:
288 *mode_value
= ProxyPrefs::kDirectProxyModeName
;
290 case PROXY_AUTO_DETECT_PROXY_SERVER_MODE
:
291 *mode_value
= ProxyPrefs::kAutoDetectProxyModeName
;
293 case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE
:
294 if (server
&& pac_url
) {
295 int message_id
= IDS_POLICY_PROXY_BOTH_SPECIFIED_ERROR
;
296 errors
->AddError(key::kProxySettings
,
299 errors
->AddError(key::kProxySettings
,
304 if (!server
&& !pac_url
) {
305 int message_id
= IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR
;
306 errors
->AddError(key::kProxySettings
,
309 errors
->AddError(key::kProxySettings
,
315 *mode_value
= ProxyPrefs::kPacScriptProxyModeName
;
317 *mode_value
= ProxyPrefs::kFixedServersProxyModeName
;
319 case PROXY_USE_SYSTEM_PROXY_SERVER_MODE
:
320 *mode_value
= ProxyPrefs::kSystemProxyModeName
;
323 errors
->AddError(key::kProxySettings
,
324 key::kProxyServerMode
,
325 IDS_POLICY_OUT_OF_RANGE_ERROR
,
326 base::IntToString(server_mode_value
));
333 } // namespace policy