1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/ui_proxy_config_service.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/values.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/net/proxy_config_handler.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/chromeos/proxy_config_service_impl.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/network/network_state.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/network/network_state_handler.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "grit/generated_resources.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/proxy/proxy_config.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace chromeos {
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char* ModeToString(UIProxyConfig::Mode mode) {
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  switch (mode) {
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case UIProxyConfig::MODE_DIRECT:
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return "direct";
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case UIProxyConfig::MODE_AUTO_DETECT:
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return "auto-detect";
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case UIProxyConfig::MODE_PAC_SCRIPT:
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return "pacurl";
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case UIProxyConfig::MODE_SINGLE_PROXY:
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return "single-proxy";
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case UIProxyConfig::MODE_PROXY_PER_SCHEME:
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return "proxy-per-scheme";
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NOTREACHED() << "Unrecognized mode type";
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return "";
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Writes the proxy config of |network| to |proxy_config|.  Sets |onc_source| to
39ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the source of this configuration. Returns false if no proxy was configured
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// for this network.
41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool GetProxyConfig(const PrefService* profile_prefs,
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    const PrefService* local_state_prefs,
43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    const NetworkState& network,
44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    net::ProxyConfig* proxy_config,
45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    onc::ONCSource* onc_source) {
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<ProxyConfigDictionary> proxy_dict =
47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      proxy_config::GetProxyConfigForNetwork(
48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          profile_prefs, local_state_prefs, network, onc_source);
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!proxy_dict)
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return PrefProxyConfigTrackerImpl::PrefConfigToNetConfig(*proxy_dict,
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                           proxy_config);
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Returns true if proxy settings from |onc_source| are editable.
56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool IsNetworkProxySettingsEditable(const onc::ONCSource onc_source) {
57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return onc_source != onc::ONC_SOURCE_DEVICE_POLICY &&
58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch         onc_source != onc::ONC_SOURCE_USER_POLICY;
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochUIProxyConfigService::UIProxyConfigService()
64ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    : profile_prefs_(NULL), local_state_prefs_(NULL) {
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)UIProxyConfigService::~UIProxyConfigService() {
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
70ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid UIProxyConfigService::SetPrefs(PrefService* profile_prefs,
71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                    PrefService* local_state_prefs) {
72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  profile_prefs_ = profile_prefs;
73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  local_state_prefs_ = local_state_prefs;
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UIProxyConfigService::SetCurrentNetwork(
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& current_network) {
78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  current_ui_network_ = current_network;
79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid UIProxyConfigService::UpdateFromPrefs() {
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const NetworkState* network = NULL;
83ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!current_ui_network_.empty()) {
84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    network = NetworkHandler::Get()->network_state_handler()
85ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        ->GetNetworkState(current_ui_network_);
86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG_IF(ERROR, !network) << "Can't find requested network "
87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                            << current_ui_network_;
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!network) {
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    current_ui_network_.clear();
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    current_ui_config_ = UIProxyConfig();
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DetermineEffectiveConfig(*network);
96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  VLOG(1) << "Current ui network: " << network->name() << ", "
97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          << ModeToString(current_ui_config_.mode) << ", "
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          << ProxyPrefs::ConfigStateToDebugString(current_ui_config_.state)
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          << ", modifiable:" << current_ui_config_.user_modifiable;
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UIProxyConfigService::GetProxyConfig(UIProxyConfig* config) const {
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *config = current_ui_config_;
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UIProxyConfigService::SetProxyConfig(const UIProxyConfig& config) {
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  current_ui_config_ = config;
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (current_ui_network_.empty())
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const NetworkState* network =
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      NetworkHandler::Get()->network_state_handler()->
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GetNetworkState(current_ui_network_);
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!network) {
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LOG(ERROR) << "Can't find requested network " << current_ui_network_;
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Store config for this network.
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> proxy_config_value(
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      config.ToPrefProxyConfig());
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProxyConfigDictionary proxy_config_dict(proxy_config_value.get());
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  VLOG(1) << "Set proxy for " << current_ui_network_
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          << " to " << *proxy_config_value;
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  proxy_config::SetProxyConfigForNetwork(proxy_config_dict, *network);
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  current_ui_config_.state = ProxyPrefs::CONFIG_SYSTEM;
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UIProxyConfigService::DetermineEffectiveConfig(
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const NetworkState& network) {
133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(local_state_prefs_);
134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // The pref service to read proxy settings that apply to all networks.
136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Settings from the profile overrule local state.
137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PrefService* top_pref_service =
138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      profile_prefs_ ? profile_prefs_ : local_state_prefs_;
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Get prefs proxy config if available.
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  net::ProxyConfig pref_config;
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProxyPrefs::ConfigState pref_state = ProxyConfigServiceImpl::ReadPrefConfig(
143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      top_pref_service, &pref_config);
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Get network proxy config if available.
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  net::ProxyConfig network_config;
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  net::ProxyConfigService::ConfigAvailability network_availability =
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      net::ProxyConfigService::CONFIG_UNSET;
149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (chromeos::GetProxyConfig(profile_prefs_,
151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               local_state_prefs_,
152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               network,
153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               &network_config,
154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               &onc_source)) {
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Network is private or shared with user using shared proxies.
156ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    VLOG(1) << this << ": using proxy of network: " << network.path();
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    network_availability = net::ProxyConfigService::CONFIG_VALID;
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Determine effective proxy config, either from prefs or network.
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProxyPrefs::ConfigState effective_config_state;
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  net::ProxyConfig effective_config;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProxyConfigServiceImpl::GetEffectiveProxyConfig(
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pref_state, pref_config,
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      network_availability, network_config, false,
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &effective_config_state, &effective_config);
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Store effective proxy into |current_ui_config_|.
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  current_ui_config_.FromNetProxyConfig(effective_config);
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  current_ui_config_.state = effective_config_state;
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ProxyConfigServiceImpl::PrefPrecedes(effective_config_state)) {
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    current_ui_config_.user_modifiable = false;
173ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else if (!IsNetworkProxySettingsEditable(onc_source)) {
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    current_ui_config_.state = ProxyPrefs::CONFIG_POLICY;
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    current_ui_config_.user_modifiable = false;
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    current_ui_config_.user_modifiable = !ProxyConfigServiceImpl::IgnoreProxy(
178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        profile_prefs_, network.profile_path(), onc_source);
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace chromeos
183