ui_proxy_config_service.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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.
4
5#include "chrome/browser/chromeos/ui_proxy_config_service.h"
6
7#include "base/logging.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/values.h"
10#include "chrome/browser/chromeos/net/proxy_config_handler.h"
11#include "chrome/browser/chromeos/proxy_config_service_impl.h"
12#include "chromeos/network/network_state.h"
13#include "chromeos/network/network_state_handler.h"
14#include "net/proxy/proxy_config.h"
15
16namespace chromeos {
17
18namespace {
19
20const char* ModeToString(UIProxyConfig::Mode mode) {
21  switch (mode) {
22    case UIProxyConfig::MODE_DIRECT:
23      return "direct";
24    case UIProxyConfig::MODE_AUTO_DETECT:
25      return "auto-detect";
26    case UIProxyConfig::MODE_PAC_SCRIPT:
27      return "pacurl";
28    case UIProxyConfig::MODE_SINGLE_PROXY:
29      return "single-proxy";
30    case UIProxyConfig::MODE_PROXY_PER_SCHEME:
31      return "proxy-per-scheme";
32  }
33  NOTREACHED() << "Unrecognized mode type";
34  return "";
35}
36
37// Writes the proxy config of |network| to |proxy_config|.  Sets |onc_source| to
38// the source of this configuration. Returns false if no proxy was configured
39// for this network.
40bool GetProxyConfig(const PrefService* profile_prefs,
41                    const PrefService* local_state_prefs,
42                    const NetworkState& network,
43                    net::ProxyConfig* proxy_config,
44                    onc::ONCSource* onc_source) {
45  scoped_ptr<ProxyConfigDictionary> proxy_dict =
46      proxy_config::GetProxyConfigForNetwork(
47          profile_prefs, local_state_prefs, network, onc_source);
48  if (!proxy_dict)
49    return false;
50  return PrefProxyConfigTrackerImpl::PrefConfigToNetConfig(*proxy_dict,
51                                                           proxy_config);
52}
53
54// Returns true if proxy settings from |onc_source| are editable.
55bool IsNetworkProxySettingsEditable(const onc::ONCSource onc_source) {
56  return onc_source != onc::ONC_SOURCE_DEVICE_POLICY &&
57         onc_source != onc::ONC_SOURCE_USER_POLICY;
58}
59
60}  // namespace
61
62UIProxyConfigService::UIProxyConfigService()
63    : profile_prefs_(NULL), local_state_prefs_(NULL) {
64}
65
66UIProxyConfigService::~UIProxyConfigService() {
67}
68
69void UIProxyConfigService::SetPrefs(PrefService* profile_prefs,
70                                    PrefService* local_state_prefs) {
71  profile_prefs_ = profile_prefs;
72  local_state_prefs_ = local_state_prefs;
73}
74
75void UIProxyConfigService::SetCurrentNetwork(
76    const std::string& current_network) {
77  current_ui_network_ = current_network;
78}
79
80void UIProxyConfigService::UpdateFromPrefs() {
81  const NetworkState* network = NULL;
82  if (!current_ui_network_.empty()) {
83    network = NetworkHandler::Get()
84                  ->network_state_handler()
85                  ->GetNetworkStateFromServicePath(current_ui_network_,
86                                                   true /* configured_only */);
87    LOG_IF(ERROR, !network) << "Couldn't find NetworkState for network "
88                            << current_ui_network_;
89  }
90  if (!network) {
91    current_ui_network_.clear();
92    current_ui_config_ = UIProxyConfig();
93    return;
94  }
95
96  DetermineEffectiveConfig(*network);
97  VLOG(1) << "Current ui network: " << network->name() << ", "
98          << ModeToString(current_ui_config_.mode) << ", "
99          << ProxyPrefs::ConfigStateToDebugString(current_ui_config_.state)
100          << ", modifiable:" << current_ui_config_.user_modifiable;
101}
102
103void UIProxyConfigService::GetProxyConfig(UIProxyConfig* config) const {
104  *config = current_ui_config_;
105}
106
107void UIProxyConfigService::SetProxyConfig(const UIProxyConfig& config) {
108  current_ui_config_ = config;
109  if (current_ui_network_.empty())
110    return;
111
112  const NetworkState* network =
113      NetworkHandler::Get()
114          ->network_state_handler()
115          ->GetNetworkStateFromServicePath(current_ui_network_,
116                                           true /* configured_only */);
117  if (!network) {
118    LOG(ERROR) << "Couldn't find NetworkState for network "
119               << current_ui_network_;
120    return;
121  }
122
123  // Store config for this network.
124  scoped_ptr<base::DictionaryValue> proxy_config_value(
125      config.ToPrefProxyConfig());
126  ProxyConfigDictionary proxy_config_dict(proxy_config_value.get());
127
128  VLOG(1) << "Set proxy for " << current_ui_network_
129          << " to " << *proxy_config_value;
130
131  proxy_config::SetProxyConfigForNetwork(proxy_config_dict, *network);
132  current_ui_config_.state = ProxyPrefs::CONFIG_SYSTEM;
133}
134
135void UIProxyConfigService::DetermineEffectiveConfig(
136    const NetworkState& network) {
137  DCHECK(local_state_prefs_);
138
139  // The pref service to read proxy settings that apply to all networks.
140  // Settings from the profile overrule local state.
141  PrefService* top_pref_service =
142      profile_prefs_ ? profile_prefs_ : local_state_prefs_;
143
144  // Get prefs proxy config if available.
145  net::ProxyConfig pref_config;
146  ProxyPrefs::ConfigState pref_state = ProxyConfigServiceImpl::ReadPrefConfig(
147      top_pref_service, &pref_config);
148
149  // Get network proxy config if available.
150  net::ProxyConfig network_config;
151  net::ProxyConfigService::ConfigAvailability network_availability =
152      net::ProxyConfigService::CONFIG_UNSET;
153  onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
154  if (chromeos::GetProxyConfig(profile_prefs_,
155                               local_state_prefs_,
156                               network,
157                               &network_config,
158                               &onc_source)) {
159    // Network is private or shared with user using shared proxies.
160    VLOG(1) << this << ": using proxy of network: " << network.path();
161    network_availability = net::ProxyConfigService::CONFIG_VALID;
162  }
163
164  // Determine effective proxy config, either from prefs or network.
165  ProxyPrefs::ConfigState effective_config_state;
166  net::ProxyConfig effective_config;
167  ProxyConfigServiceImpl::GetEffectiveProxyConfig(
168      pref_state, pref_config,
169      network_availability, network_config, false,
170      &effective_config_state, &effective_config);
171
172  // Store effective proxy into |current_ui_config_|.
173  current_ui_config_.FromNetProxyConfig(effective_config);
174  current_ui_config_.state = effective_config_state;
175  if (ProxyConfigServiceImpl::PrefPrecedes(effective_config_state)) {
176    current_ui_config_.user_modifiable = false;
177  } else if (!IsNetworkProxySettingsEditable(onc_source)) {
178    current_ui_config_.state = ProxyPrefs::CONFIG_POLICY;
179    current_ui_config_.user_modifiable = false;
180  } else {
181    current_ui_config_.user_modifiable = !ProxyConfigServiceImpl::IgnoreProxy(
182        profile_prefs_, network.profile_path(), onc_source);
183  }
184}
185
186}  // namespace chromeos
187