Popular sites on the NTP: re-download popular suggestions once per Chrome run
[chromium-blink-merge.git] / chrome / browser / net / proxy_policy_handler.cc
blob591fc2a0f43d134fad85b05b4656627d639ca439
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"
20 namespace {
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;
29 bool pac_url_allowed;
30 bool bypass_list_allowed;
31 bool server_allowed;
32 int error_message_id;
35 // List of entries determining which proxy policies can be specified, depending
36 // on the ProxyMode.
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 },
50 } // namespace
52 namespace policy {
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,
76 key::kProxyMode,
77 IDS_POLICY_NOT_SPECIFIED_ERROR);
78 return false;
81 std::string mode_value;
82 if (!CheckProxyModeAndServerMode(policies, errors, &mode_value))
83 return false;
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())
88 return true;
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)
94 continue;
96 is_valid_mode = true;
98 if (!entry.pac_url_allowed && pac_url) {
99 errors->AddError(key::kProxySettings,
100 key::kProxyPacUrl,
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,
110 key::kProxyServer,
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)) {
117 return false;
121 if (!is_valid_mode) {
122 errors->AddError(key::kProxySettings,
123 mode ? key::kProxyMode : key::kProxyServerMode,
124 IDS_POLICY_OUT_OF_RANGE_ERROR,
125 mode_value);
126 return false;
128 return true;
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;
142 if (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) {
147 int int_mode = 0;
148 CHECK(server_mode->GetAsInteger(&int_mode));
150 switch (int_mode) {
151 case PROXY_SERVER_MODE:
152 proxy_mode = ProxyPrefs::MODE_DIRECT;
153 break;
154 case PROXY_AUTO_DETECT_PROXY_SERVER_MODE:
155 proxy_mode = ProxyPrefs::MODE_AUTO_DETECT;
156 break;
157 case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE:
158 proxy_mode = ProxyPrefs::MODE_FIXED_SERVERS;
159 if (pac_url)
160 proxy_mode = ProxyPrefs::MODE_PAC_SCRIPT;
161 break;
162 case PROXY_USE_SYSTEM_PROXY_SERVER_MODE:
163 proxy_mode = ProxyPrefs::MODE_SYSTEM;
164 break;
165 default:
166 proxy_mode = ProxyPrefs::MODE_DIRECT;
167 NOTREACHED();
169 } else {
170 return;
173 switch (proxy_mode) {
174 case ProxyPrefs::MODE_DIRECT:
175 prefs->SetValue(proxy_config::prefs::kProxy,
176 make_scoped_ptr(ProxyConfigDictionary::CreateDirect()));
177 break;
178 case ProxyPrefs::MODE_AUTO_DETECT:
179 prefs->SetValue(
180 proxy_config::prefs::kProxy,
181 make_scoped_ptr(ProxyConfigDictionary::CreateAutoDetect()));
182 break;
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)));
189 } else {
190 NOTREACHED();
192 break;
194 case ProxyPrefs::MODE_FIXED_SERVERS: {
195 std::string proxy_server;
196 std::string bypass_list_string;
197 if (server->GetAsString(&proxy_server)) {
198 if (bypass_list)
199 bypass_list->GetAsString(&bypass_list_string);
200 prefs->SetValue(
201 proxy_config::prefs::kProxy,
202 make_scoped_ptr(ProxyConfigDictionary::CreateFixedServers(
203 proxy_server, bypass_list_string)));
205 break;
207 case ProxyPrefs::MODE_SYSTEM:
208 prefs->SetValue(proxy_config::prefs::kProxy,
209 make_scoped_ptr(ProxyConfigDictionary::CreateSystem()));
210 break;
211 case ProxyPrefs::kModeCount:
212 NOTREACHED();
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))
222 return NULL;
224 const base::Value* policy_value = NULL;
225 std::string tmp;
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) &&
230 tmp.empty())) {
231 return NULL;
233 return policy_value;
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.
247 if (mode) {
248 if (server_mode) {
249 errors->AddError(key::kProxySettings,
250 key::kProxyServerMode,
251 IDS_POLICY_OVERRIDDEN,
252 key::kProxyMode);
254 if (!mode->GetAsString(mode_value)) {
255 errors->AddError(key::kProxySettings,
256 key::kProxyMode,
257 IDS_POLICY_TYPE_ERROR,
258 ValueTypeToString(base::Value::TYPE_BOOLEAN));
259 return false;
262 ProxyPrefs::ProxyMode mode;
263 if (!ProxyPrefs::StringToProxyMode(*mode_value, &mode)) {
264 errors->AddError(key::kProxySettings,
265 key::kProxyMode,
266 IDS_POLICY_INVALID_PROXY_MODE_ERROR);
267 return false;
270 if (mode == ProxyPrefs::MODE_PAC_SCRIPT && !pac_url) {
271 errors->AddError(key::kProxySettings,
272 key::kProxyPacUrl,
273 IDS_POLICY_NOT_SPECIFIED_ERROR);
274 return false;
275 } else if (mode == ProxyPrefs::MODE_FIXED_SERVERS && !server) {
276 errors->AddError(key::kProxySettings,
277 key::kProxyServer,
278 IDS_POLICY_NOT_SPECIFIED_ERROR);
279 return false;
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));
288 return false;
291 switch (server_mode_value) {
292 case PROXY_SERVER_MODE:
293 *mode_value = ProxyPrefs::kDirectProxyModeName;
294 break;
295 case PROXY_AUTO_DETECT_PROXY_SERVER_MODE:
296 *mode_value = ProxyPrefs::kAutoDetectProxyModeName;
297 break;
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,
302 key::kProxyServer,
303 message_id);
304 errors->AddError(key::kProxySettings,
305 key::kProxyPacUrl,
306 message_id);
307 return false;
309 if (!server && !pac_url) {
310 int message_id = IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR;
311 errors->AddError(key::kProxySettings,
312 key::kProxyServer,
313 message_id);
314 errors->AddError(key::kProxySettings,
315 key::kProxyPacUrl,
316 message_id);
317 return false;
319 if (pac_url)
320 *mode_value = ProxyPrefs::kPacScriptProxyModeName;
321 else
322 *mode_value = ProxyPrefs::kFixedServersProxyModeName;
323 break;
324 case PROXY_USE_SYSTEM_PROXY_SERVER_MODE:
325 *mode_value = ProxyPrefs::kSystemProxyModeName;
326 break;
327 default:
328 errors->AddError(key::kProxySettings,
329 key::kProxyServerMode,
330 IDS_POLICY_OUT_OF_RANGE_ERROR,
331 base::IntToString(server_mode_value));
332 return false;
335 return true;
338 } // namespace policy