18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file.
48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/net/proxy_policy_handler.h"
68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/logging.h"
88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/prefs/pref_value_map.h"
98bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/values.h"
118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/prefs/proxy_config_dictionary.h"
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/prefs/proxy_prefs.h"
138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/common/pref_names.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/browser/configuration_policy_handler.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/browser/policy_error_map.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/policy_map.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "grit/components_strings.h"
188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "policy/policy_constants.h"
198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace {
218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// This is used to check whether for a given ProxyMode value, the ProxyPacUrl,
238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// the ProxyBypassList and the ProxyServer policies are allowed to be specified.
248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// |error_message_id| is the message id of the localized error message to show
258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// when the policies are not specified as allowed. Each value of ProxyMode
268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// has a ProxyModeValidationEntry in the |kProxyModeValidationMap| below.
278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)struct ProxyModeValidationEntry {
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const char* mode_value;
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool pac_url_allowed;
308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool bypass_list_allowed;
318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool server_allowed;
328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int error_message_id;
338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)};
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// List of entries determining which proxy policies can be specified, depending
368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// on the ProxyMode.
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const ProxyModeValidationEntry kProxyModeValidationMap[] = {
388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  { ProxyPrefs::kDirectProxyModeName,
398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    false, false, false, IDS_POLICY_PROXY_MODE_DISABLED_ERROR },
408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  { ProxyPrefs::kAutoDetectProxyModeName,
418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    false, false, false, IDS_POLICY_PROXY_MODE_AUTO_DETECT_ERROR },
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  { ProxyPrefs::kPacScriptProxyModeName,
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    true, false, false, IDS_POLICY_PROXY_MODE_PAC_URL_ERROR },
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  { ProxyPrefs::kFixedServersProxyModeName,
458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    false, true, true, IDS_POLICY_PROXY_MODE_FIXED_SERVERS_ERROR },
468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  { ProxyPrefs::kSystemProxyModeName,
478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    false, false, false, IDS_POLICY_PROXY_MODE_SYSTEM_ERROR },
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)};
498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace policy {
538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// The proxy policies have the peculiarity that they are loaded from individual
558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// policies, but the providers then expose them through a unified
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// DictionaryValue. Once Dictionary policies are fully supported, the individual
578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// proxy policies will be deprecated. http://crbug.com/108996
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ProxyPolicyHandler::ProxyPolicyHandler() {}
608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ProxyPolicyHandler::~ProxyPolicyHandler() {
628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ProxyPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                             PolicyErrorMap* errors) {
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode);
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer);
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* server_mode =
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      GetProxyPolicyValue(policies, key::kProxyServerMode);
708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl);
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* bypass_list =
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      GetProxyPolicyValue(policies, key::kProxyBypassList);
738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if ((server || pac_url || bypass_list) && !(mode || server_mode)) {
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    errors->AddError(key::kProxySettings,
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                     key::kProxyMode,
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                     IDS_POLICY_NOT_SPECIFIED_ERROR);
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string mode_value;
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!CheckProxyModeAndServerMode(policies, errors, &mode_value))
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be
868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // empty and the proxy shouldn't be configured at all.
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (mode_value.empty())
888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return true;
898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool is_valid_mode = false;
918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (size_t i = 0; i != arraysize(kProxyModeValidationMap); ++i) {
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const ProxyModeValidationEntry& entry = kProxyModeValidationMap[i];
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (entry.mode_value != mode_value)
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      continue;
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    is_valid_mode = true;
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!entry.pac_url_allowed && pac_url) {
998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      errors->AddError(key::kProxySettings,
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyPacUrl,
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       entry.error_message_id);
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!entry.bypass_list_allowed && bypass_list) {
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      errors->AddError(key::kProxySettings,
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyBypassList,
1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       entry.error_message_id);
1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
1088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!entry.server_allowed && server) {
1098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      errors->AddError(key::kProxySettings,
1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyServer,
1118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       entry.error_message_id);
1128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if ((!entry.pac_url_allowed && pac_url) ||
1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        (!entry.bypass_list_allowed && bypass_list) ||
1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        (!entry.server_allowed && server)) {
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!is_valid_mode) {
1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    errors->AddError(key::kProxySettings,
1238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                     mode ? key::kProxyMode : key::kProxyServerMode,
1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                     IDS_POLICY_OUT_OF_RANGE_ERROR,
1258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                     mode_value);
1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return true;
1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ProxyPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
1328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                             PrefValueMap* prefs) {
1338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode);
1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer);
1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* server_mode =
1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      GetProxyPolicyValue(policies, key::kProxyServerMode);
1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl);
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* bypass_list =
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      GetProxyPolicyValue(policies, key::kProxyBypassList);
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ProxyPrefs::ProxyMode proxy_mode;
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (mode) {
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    std::string string_mode;
1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    CHECK(mode->GetAsString(&string_mode));
1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    CHECK(ProxyPrefs::StringToProxyMode(string_mode, &proxy_mode));
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  } else if (server_mode) {
1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int int_mode = 0;
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    CHECK(server_mode->GetAsInteger(&int_mode));
1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    switch (int_mode) {
1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      case PROXY_SERVER_MODE:
1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        proxy_mode = ProxyPrefs::MODE_DIRECT;
1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      case PROXY_AUTO_DETECT_PROXY_SERVER_MODE:
1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        proxy_mode = ProxyPrefs::MODE_AUTO_DETECT;
1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
1578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE:
1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        proxy_mode = ProxyPrefs::MODE_FIXED_SERVERS;
1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (pac_url)
1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          proxy_mode = ProxyPrefs::MODE_PAC_SCRIPT;
1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      case PROXY_USE_SYSTEM_PROXY_SERVER_MODE:
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        proxy_mode = ProxyPrefs::MODE_SYSTEM;
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      default:
1668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        proxy_mode = ProxyPrefs::MODE_DIRECT;
1678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        NOTREACHED();
1688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  } else {
1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
1718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  switch (proxy_mode) {
1748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case ProxyPrefs::MODE_DIRECT:
1758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateDirect());
1768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
1778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case ProxyPrefs::MODE_AUTO_DETECT:
1788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect());
1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
1808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case ProxyPrefs::MODE_PAC_SCRIPT: {
1818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      std::string pac_url_string;
1828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      if (pac_url && pac_url->GetAsString(&pac_url_string)) {
1838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        prefs->SetValue(
1848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            prefs::kProxy,
1858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            ProxyConfigDictionary::CreatePacScript(pac_url_string, false));
1868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      } else {
1878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        NOTREACHED();
1888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
1898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
1908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case ProxyPrefs::MODE_FIXED_SERVERS: {
1928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      std::string proxy_server;
1938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      std::string bypass_list_string;
1948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      if (server->GetAsString(&proxy_server)) {
1958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (bypass_list)
1968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          bypass_list->GetAsString(&bypass_list_string);
1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        prefs->SetValue(prefs::kProxy,
1988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                        ProxyConfigDictionary::CreateFixedServers(
1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            proxy_server, bypass_list_string));
2008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
2018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
2028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case ProxyPrefs::MODE_SYSTEM:
2048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateSystem());
2058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
2068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case ProxyPrefs::kModeCount:
2078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      NOTREACHED();
2088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
2098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const base::Value* ProxyPolicyHandler::GetProxyPolicyValue(
2128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const PolicyMap& policies, const char* policy_name) {
2138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // See note on the ProxyPolicyHandler implementation above.
2148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* value = policies.GetValue(key::kProxySettings);
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* settings;
2168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!value || !value->GetAsDictionary(&settings))
2178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return NULL;
2188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* policy_value = NULL;
2208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::string tmp;
2218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!settings->Get(policy_name, &policy_value) ||
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      policy_value->IsType(base::Value::TYPE_NULL) ||
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (policy_value->IsType(base::Value::TYPE_STRING) &&
2248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       policy_value->GetAsString(&tmp) &&
2258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       tmp.empty())) {
2268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return NULL;
2278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
2288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return policy_value;
2298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ProxyPolicyHandler::CheckProxyModeAndServerMode(const PolicyMap& policies,
2328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                     PolicyErrorMap* errors,
2338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                                     std::string* mode_value) {
2348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode);
2358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer);
2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* server_mode =
2378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      GetProxyPolicyValue(policies, key::kProxyServerMode);
2388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl);
2398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // If there's a server mode, convert it into a mode.
2418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // When both are specified, the mode takes precedence.
2428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (mode) {
2438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (server_mode) {
2448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      errors->AddError(key::kProxySettings,
2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyServerMode,
2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       IDS_POLICY_OVERRIDDEN,
2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyMode);
2488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!mode->GetAsString(mode_value)) {
2508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      errors->AddError(key::kProxySettings,
2518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyMode,
2528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       IDS_POLICY_TYPE_ERROR,
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       ValueTypeToString(base::Value::TYPE_BOOLEAN));
2548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
2558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ProxyPrefs::ProxyMode mode;
2588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!ProxyPrefs::StringToProxyMode(*mode_value, &mode)) {
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      errors->AddError(key::kProxySettings,
2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyMode,
2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       IDS_POLICY_INVALID_PROXY_MODE_ERROR);
2628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
2638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (mode == ProxyPrefs::MODE_PAC_SCRIPT && !pac_url) {
2668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      errors->AddError(key::kProxySettings,
2678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyPacUrl,
2688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       IDS_POLICY_NOT_SPECIFIED_ERROR);
2698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
2708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    } else if (mode == ProxyPrefs::MODE_FIXED_SERVERS && !server) {
2718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      errors->AddError(key::kProxySettings,
2728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyServer,
2738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       IDS_POLICY_NOT_SPECIFIED_ERROR);
2748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
2758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  } else if (server_mode) {
2778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int server_mode_value;
2788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!server_mode->GetAsInteger(&server_mode_value)) {
2798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      errors->AddError(key::kProxySettings,
2808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       key::kProxyServerMode,
2818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       IDS_POLICY_TYPE_ERROR,
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       ValueTypeToString(base::Value::TYPE_INTEGER));
2838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
2848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    switch (server_mode_value) {
2878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      case PROXY_SERVER_MODE:
2888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        *mode_value = ProxyPrefs::kDirectProxyModeName;
2898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
2908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      case PROXY_AUTO_DETECT_PROXY_SERVER_MODE:
2918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        *mode_value = ProxyPrefs::kAutoDetectProxyModeName;
2928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
2938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE:
2948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (server && pac_url) {
2958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          int message_id = IDS_POLICY_PROXY_BOTH_SPECIFIED_ERROR;
2968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          errors->AddError(key::kProxySettings,
2978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                           key::kProxyServer,
2988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                           message_id);
2998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          errors->AddError(key::kProxySettings,
3008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                           key::kProxyPacUrl,
3018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                           message_id);
3028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          return false;
3038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
3048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (!server && !pac_url) {
3058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          int message_id = IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR;
3068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          errors->AddError(key::kProxySettings,
3078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                           key::kProxyServer,
3088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                           message_id);
3098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          errors->AddError(key::kProxySettings,
3108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                           key::kProxyPacUrl,
3118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                           message_id);
3128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          return false;
3138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
3148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (pac_url)
3158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          *mode_value = ProxyPrefs::kPacScriptProxyModeName;
3168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        else
3178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          *mode_value = ProxyPrefs::kFixedServersProxyModeName;
3188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
3198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      case PROXY_USE_SYSTEM_PROXY_SERVER_MODE:
3208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        *mode_value = ProxyPrefs::kSystemProxyModeName;
3218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
3228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      default:
3238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        errors->AddError(key::kProxySettings,
3248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         key::kProxyServerMode,
3258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         IDS_POLICY_OUT_OF_RANGE_ERROR,
3268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         base::IntToString(server_mode_value));
3278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return false;
3288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return true;
3318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace policy
334