1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file.
4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/proxy_config_service_impl.h"
6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <ostream>
8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/logging.h"
10bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_util.h"
11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/task.h"
12bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/cros/cros_library.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/cros_settings_names.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/proxy_prefs.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
17bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace em = enterprise_management;
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
20bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace chromeos {
21bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
22bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace {
23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char* SourceToString(ProxyConfigServiceImpl::ProxyConfig::Source source) {
25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  switch (source) {
26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case ProxyConfigServiceImpl::ProxyConfig::SOURCE_NONE:
27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return "SOURCE_NONE";
28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case ProxyConfigServiceImpl::ProxyConfig::SOURCE_POLICY:
29bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return "SOURCE_POLICY";
30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case ProxyConfigServiceImpl::ProxyConfig::SOURCE_OWNER:
31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return "SOURCE_OWNER";
32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  NOTREACHED() << "Unrecognized source type";
34bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return "";
35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
36bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
37bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstd::ostream& operator<<(std::ostream& out,
38bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) {
39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  out << "  " << SourceToString(proxy.source) << "\n"
40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      << "  server: " << (proxy.server.is_valid() ? proxy.server.ToURI() : "")
41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      << "\n";
42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return out;
43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
44bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
45bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstd::ostream& operator<<(std::ostream& out,
46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const ProxyConfigServiceImpl::ProxyConfig& config) {
47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  switch (config.mode) {
48bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT:
49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      out << "Direct connection:\n  "
50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          << SourceToString(config.automatic_proxy.source) << "\n";
51bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
52bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT:
53bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      out << "Auto detection:\n  "
54bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          << SourceToString(config.automatic_proxy.source) << "\n";
55bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
56bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT:
57bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      out << "Custom PAC script:\n  "
58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          << SourceToString(config.automatic_proxy.source)
59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          << "\n  PAC: " << config.automatic_proxy.pac_url << "\n";
60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY:
62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      out << "Single proxy:\n" << config.single_proxy;
63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME:
65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      out << "HTTP proxy: " << config.http_proxy;
66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      out << "HTTPS proxy: " << config.https_proxy;
67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      out << "FTP proxy: " << config.ftp_proxy;
68bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      out << "SOCKS proxy: " << config.socks_proxy;
69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    default:
71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NOTREACHED() << "Unrecognized proxy config mode";
72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
73bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (config.mode == ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY ||
75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      config.mode ==
76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME) {
77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    out << "Bypass list: ";
78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (config.bypass_rules.rules().empty()) {
79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      out << "[None]";
80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else {
81bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      const net::ProxyBypassRules& bypass_rules = config.bypass_rules;
82bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net::ProxyBypassRules::RuleList::const_iterator it;
83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      for (it = bypass_rules.rules().begin();
84bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen           it != bypass_rules.rules().end(); ++it) {
85bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        out << "\n    " << (*it)->ToString();
86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
88bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
89bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return out;
90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstd::string ProxyConfigToString(
93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const ProxyConfigServiceImpl::ProxyConfig& proxy_config) {
94bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::ostringstream stream;
95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  stream << proxy_config;
96bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return stream.str();
97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
98bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}  // namespace
100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//---------- ProxyConfigServiceImpl::ProxyConfig::Setting methods --------------
102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool ProxyConfigServiceImpl::ProxyConfig::Setting::CanBeWrittenByUser(
104bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    bool user_is_owner) {
105bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Setting can only be written by user if user is owner and setting is not
106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // from policy.
107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return user_is_owner && source != ProxyConfig::SOURCE_POLICY;
108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
110bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//----------- ProxyConfigServiceImpl::ProxyConfig: public methods --------------
111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
112bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid ProxyConfigServiceImpl::ProxyConfig::ToNetProxyConfig(
113bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    net::ProxyConfig* net_config) {
114bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  switch (mode) {
115bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case MODE_DIRECT:
116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      *net_config = net::ProxyConfig::CreateDirect();
117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case MODE_AUTO_DETECT:
119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      *net_config = net::ProxyConfig::CreateAutoDetect();
120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case MODE_PAC_SCRIPT:
122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      *net_config = net::ProxyConfig::CreateFromCustomPacURL(
123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          automatic_proxy.pac_url);
124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case MODE_SINGLE_PROXY:
126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      *net_config = net::ProxyConfig();
127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net_config->proxy_rules().type =
128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen             net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net_config->proxy_rules().single_proxy = single_proxy.server;
130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net_config->proxy_rules().bypass_rules = bypass_rules;
131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    case MODE_PROXY_PER_SCHEME:
133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      *net_config = net::ProxyConfig();
134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net_config->proxy_rules().type =
135bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net_config->proxy_rules().proxy_for_http = http_proxy.server;
137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net_config->proxy_rules().proxy_for_https = https_proxy.server;
138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net_config->proxy_rules().proxy_for_ftp = ftp_proxy.server;
139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net_config->proxy_rules().fallback_proxy = socks_proxy.server;
140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      net_config->proxy_rules().bypass_rules = bypass_rules;
141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    default:
143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NOTREACHED() << "Unrecognized proxy config mode";
144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
145bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
146bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ProxyConfigServiceImpl::ProxyConfig::CanBeWrittenByUser(
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    bool user_is_owner, const std::string& scheme) {
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Setting can only be written by user if user is owner and setting is not
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // from policy.
15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Setting* setting = NULL;
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  switch (mode) {
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case MODE_DIRECT:
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case MODE_AUTO_DETECT:
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case MODE_PAC_SCRIPT:
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      setting = &automatic_proxy;
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case MODE_SINGLE_PROXY:
16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      setting = &single_proxy;
16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case MODE_PROXY_PER_SCHEME:
16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      setting = MapSchemeToProxy(scheme);
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    default:
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!setting) {
16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED() << "Unrecognized proxy config mode";
17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return setting->CanBeWrittenByUser(user_is_owner);
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenProxyConfigServiceImpl::ProxyConfig::ManualProxy*
17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ProxyConfigServiceImpl::ProxyConfig::MapSchemeToProxy(
17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        const std::string& scheme) {
17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (scheme == "http")
17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return &http_proxy;
18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (scheme == "https")
18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return &https_proxy;
18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (scheme == "ftp")
18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return &ftp_proxy;
18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (scheme == "socks")
18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return &socks_proxy;
18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  NOTREACHED() << "Invalid scheme: " << scheme;
18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return NULL;
18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
190bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool ProxyConfigServiceImpl::ProxyConfig::Serialize(std::string* output) {
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  em::DeviceProxySettingsProto proxy_proto;
192bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  switch (mode) {
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case MODE_DIRECT: {
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      proxy_proto.set_proxy_mode(ProxyPrefs::kDirectProxyModeName);
195bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case MODE_AUTO_DETECT: {
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      proxy_proto.set_proxy_mode(ProxyPrefs::kAutoDetectProxyModeName);
199bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case MODE_PAC_SCRIPT: {
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      proxy_proto.set_proxy_mode(ProxyPrefs::kPacScriptProxyModeName);
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!automatic_proxy.pac_url.is_empty())
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        proxy_proto.set_proxy_pac_url(automatic_proxy.pac_url.spec());
205bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case MODE_SINGLE_PROXY: {
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      proxy_proto.set_proxy_mode(ProxyPrefs::kFixedServersProxyModeName);
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (single_proxy.server.is_valid())
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        proxy_proto.set_proxy_server(single_proxy.server.ToURI());
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case MODE_PROXY_PER_SCHEME: {
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      proxy_proto.set_proxy_mode(ProxyPrefs::kFixedServersProxyModeName);
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      std::string spec;
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EncodeAndAppendProxyServer("http", http_proxy.server, &spec);
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EncodeAndAppendProxyServer("https", https_proxy.server, &spec);
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EncodeAndAppendProxyServer("ftp", ftp_proxy.server, &spec);
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      EncodeAndAppendProxyServer("socks", socks_proxy.server, &spec);
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!spec.empty())
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        proxy_proto.set_proxy_server(spec);
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    default: {
225bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NOTREACHED() << "Unrecognized proxy config mode";
226bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      break;
227bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
228bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  proxy_proto.set_proxy_bypass_list(bypass_rules.ToString());
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return proxy_proto.SerializeToString(output);
231bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
232bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
233bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool ProxyConfigServiceImpl::ProxyConfig::Deserialize(
234bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const std::string& input) {
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  em::DeviceProxySettingsProto proxy_proto;
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!proxy_proto.ParseFromString(input))
237bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const std::string& mode_string(proxy_proto.proxy_mode());
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (mode_string == ProxyPrefs::kDirectProxyModeName) {
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    mode = MODE_DIRECT;
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (mode_string == ProxyPrefs::kAutoDetectProxyModeName) {
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    mode = MODE_AUTO_DETECT;
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (mode_string == ProxyPrefs::kPacScriptProxyModeName) {
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    mode = MODE_PAC_SCRIPT;
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (proxy_proto.has_proxy_pac_url())
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      automatic_proxy.pac_url = GURL(proxy_proto.proxy_pac_url());
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (mode_string == ProxyPrefs::kFixedServersProxyModeName) {
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    net::ProxyConfig::ProxyRules rules;
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    rules.ParseFromString(proxy_proto.proxy_server());
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    switch (rules.type) {
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case net::ProxyConfig::ProxyRules::TYPE_NO_RULES:
253bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        return false;
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY:
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (!rules.single_proxy.is_valid())
256bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen          return false;
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        mode = MODE_SINGLE_PROXY;
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        single_proxy.server = rules.single_proxy;
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME:
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // Make sure we have valid server for at least one of the protocols.
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (!rules.proxy_for_http.is_valid() &&
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            !rules.proxy_for_https.is_valid() &&
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            !rules.proxy_for_ftp.is_valid() &&
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            !rules.fallback_proxy.is_valid()) {
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          return false;
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        }
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        mode = MODE_PROXY_PER_SCHEME;
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (rules.proxy_for_http.is_valid())
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          http_proxy.server = rules.proxy_for_http;
271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (rules.proxy_for_https.is_valid())
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          https_proxy.server = rules.proxy_for_https;
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (rules.proxy_for_ftp.is_valid())
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          ftp_proxy.server = rules.proxy_for_ftp;
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (rules.fallback_proxy.is_valid())
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          socks_proxy.server = rules.fallback_proxy;
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
278bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED() << "Unrecognized proxy config mode";
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
282bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (proxy_proto.has_proxy_bypass_list())
285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bypass_rules.ParseFromString(proxy_proto.proxy_bypass_list());
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
287bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
288bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
289bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
290bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstd::string ProxyConfigServiceImpl::ProxyConfig::ToString() const {
291bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return ProxyConfigToString(*this);
292bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
293bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
294bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//----------- ProxyConfigServiceImpl::ProxyConfig: private methods -------------
295bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer(
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& scheme,
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const net::ProxyServer& server,
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string* spec) {
301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!server.is_valid())
302bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return;
303bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!spec->empty())
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *spec += ';';
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!scheme.empty()) {
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *spec += scheme;
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *spec += "=";
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  *spec += server.ToURI();
312bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
313bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
314bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//------------------- ProxyConfigServiceImpl: public methods -------------------
315bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
316bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenProxyConfigServiceImpl::ProxyConfigServiceImpl()
317bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    : can_post_task_(false),
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      config_availability_(net::ProxyConfigService::CONFIG_PENDING),
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      persist_to_device_(true),
320bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      persist_to_device_pending_(false) {
321bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Start async fetch of proxy config from settings persisted on device.
322bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // TODO(kuan): retrieve config from policy and owner and merge them
323bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  bool use_default = true;
324bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (CrosLibrary::Get()->EnsureLoaded()) {
325bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    retrieve_property_op_ = SignedSettings::CreateRetrievePropertyOp(
326bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        kSettingProxyEverywhere, this);
32721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (retrieve_property_op_) {
32821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      retrieve_property_op_->Execute();
329513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      VLOG(1) << "Start retrieving proxy setting from device";
330bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      use_default = false;
331bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else {
332513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      VLOG(1) << "Fail to retrieve proxy setting from device";
333bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
334bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
335bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (use_default)
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    config_availability_ = net::ProxyConfigService::CONFIG_UNSET;
337bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  can_post_task_ = true;
338bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
339bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
340bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenProxyConfigServiceImpl::ProxyConfigServiceImpl(const ProxyConfig& init_config)
341bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    : can_post_task_(true),
342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      config_availability_(net::ProxyConfigService::CONFIG_VALID),
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      persist_to_device_(false),
344bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      persist_to_device_pending_(false) {
345bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  reference_config_ = init_config;
346bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Update the IO-accessible copy in |cached_config_| as well.
347bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  cached_config_ = reference_config_;
348bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
349bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
350bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenProxyConfigServiceImpl::~ProxyConfigServiceImpl() {
351bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
352bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
353bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid ProxyConfigServiceImpl::UIGetProxyConfig(ProxyConfig* config) {
354bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from UI thread.
355bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnUIThread();
356bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Simply returns the copy on the UI thread.
357bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  *config = reference_config_;
358bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
359bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
360bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool ProxyConfigServiceImpl::UISetProxyConfigToDirect() {
361bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from UI thread.
362bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnUIThread();
363bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  reference_config_.mode = ProxyConfig::MODE_DIRECT;
364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  OnUISetProxyConfig(persist_to_device_);
365bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
366bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
367bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
368bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool ProxyConfigServiceImpl::UISetProxyConfigToAutoDetect() {
369bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from UI thread.
370bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnUIThread();
371bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  reference_config_.mode = ProxyConfig::MODE_AUTO_DETECT;
372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  OnUISetProxyConfig(persist_to_device_);
373bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
374bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
375bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
376bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool ProxyConfigServiceImpl::UISetProxyConfigToPACScript(const GURL& pac_url) {
377bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from UI thread.
378bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnUIThread();
379bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  reference_config_.mode = ProxyConfig::MODE_PAC_SCRIPT;
380bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  reference_config_.automatic_proxy.pac_url = pac_url;
381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  OnUISetProxyConfig(persist_to_device_);
382513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return true;
383bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
384bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
385bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool ProxyConfigServiceImpl::UISetProxyConfigToSingleProxy(
386bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const net::ProxyServer& server) {
387bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from UI thread.
388bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnUIThread();
389bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  reference_config_.mode = ProxyConfig::MODE_SINGLE_PROXY;
390bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  reference_config_.single_proxy.server = server;
391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  OnUISetProxyConfig(persist_to_device_);
392513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return true;
393bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
394bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
395bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool ProxyConfigServiceImpl::UISetProxyConfigToProxyPerScheme(
396bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const std::string& scheme, const net::ProxyServer& server) {
397bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from UI thread.
398bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnUIThread();
39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ProxyConfig::ManualProxy* proxy = reference_config_.MapSchemeToProxy(scheme);
400bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!proxy) {
401bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    NOTREACHED() << "Cannot set proxy: invalid scheme [" << scheme << "]";
402bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
403bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
404bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  reference_config_.mode = ProxyConfig::MODE_PROXY_PER_SCHEME;
405bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  proxy->server = server;
406dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  OnUISetProxyConfig(persist_to_device_);
407513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return true;
408bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
409bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
410bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool ProxyConfigServiceImpl::UISetProxyConfigBypassRules(
411bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const net::ProxyBypassRules& bypass_rules) {
412bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from UI thread.
413bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnUIThread();
414bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DCHECK(reference_config_.mode == ProxyConfig::MODE_SINGLE_PROXY ||
415bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen         reference_config_.mode == ProxyConfig::MODE_PROXY_PER_SCHEME);
416bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (reference_config_.mode != ProxyConfig::MODE_SINGLE_PROXY &&
417bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      reference_config_.mode != ProxyConfig::MODE_PROXY_PER_SCHEME) {
418513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    VLOG(1) << "Cannot set bypass rules for proxy mode ["
419513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch             << reference_config_.mode << "]";
420bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
421bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
422bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  reference_config_.bypass_rules = bypass_rules;
423dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  OnUISetProxyConfig(persist_to_device_);
424bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
425bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
426bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
427bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid ProxyConfigServiceImpl::AddObserver(
428bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    net::ProxyConfigService::Observer* observer) {
429bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from IO thread.
430bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnIOThread();
431bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  observers_.AddObserver(observer);
432bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
433bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
434bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid ProxyConfigServiceImpl::RemoveObserver(
435bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    net::ProxyConfigService::Observer* observer) {
436bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from IO thread.
437bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnIOThread();
438bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  observers_.RemoveObserver(observer);
439bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
440bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennet::ProxyConfigService::ConfigAvailability
442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ProxyConfigServiceImpl::IOGetProxyConfig(net::ProxyConfig* net_config) {
443bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Should be called from IO thread.
444bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  CheckCurrentlyOnIOThread();
445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (config_availability_ == net::ProxyConfigService::CONFIG_VALID)
446bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    cached_config_.ToNetProxyConfig(net_config);
447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return config_availability_;
449bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
450bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
45121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ProxyConfigServiceImpl::OnSettingsOpCompleted(
45221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    SignedSettings::ReturnCode code,
45321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bool value) {
45421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (SignedSettings::SUCCESS == code)
45521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    VLOG(1) << "Stored proxy setting to device";
45621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  else
45721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(WARNING) << "Error storing proxy setting to device";
458bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  store_property_op_ = NULL;
459bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (persist_to_device_pending_)
460bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    PersistConfigToDevice();
461bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
462bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
46321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ProxyConfigServiceImpl::OnSettingsOpCompleted(
46421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    SignedSettings::ReturnCode code,
46521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    std::string value) {
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  retrieve_property_op_ = NULL;
46721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (SignedSettings::SUCCESS == code) {
46821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    VLOG(1) << "Retrieved proxy setting from device, value=[" << value << "]";
46921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (reference_config_.Deserialize(value)) {
470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      IOSetProxyConfig(reference_config_,
471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       net::ProxyConfigService::CONFIG_VALID);
472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
47321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    } else {
47421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      LOG(WARNING) << "Error deserializing device's proxy setting";
47521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
476bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  } else {
477bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    LOG(WARNING) << "Error retrieving proxy setting from device";
478bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Update the configuration state on the IO thread.
481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IOSetProxyConfig(reference_config_, net::ProxyConfigService::CONFIG_UNSET);
482bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
483bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
484bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen//------------------ ProxyConfigServiceImpl: private methods -------------------
485bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
486bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid ProxyConfigServiceImpl::PersistConfigToDevice() {
487bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DCHECK(!store_property_op_);
488bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  persist_to_device_pending_ = false;
489bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::string value;
490bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!reference_config_.Serialize(&value)) {
49121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(WARNING) << "Error serializing proxy config";
492bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return;
493bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
494bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  store_property_op_ = SignedSettings::CreateStorePropertyOp(
495bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      kSettingProxyEverywhere, value, this);
49621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  store_property_op_->Execute();
49721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  VLOG(1) << "Start storing proxy setting to device, value=" << value;
498bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
499bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
500bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid ProxyConfigServiceImpl::OnUISetProxyConfig(bool persist_to_device) {
501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IOSetProxyConfig(reference_config_, net::ProxyConfigService::CONFIG_VALID);
502bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (persist_to_device && CrosLibrary::Get()->EnsureLoaded()) {
503bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (store_property_op_) {
504bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      persist_to_device_pending_ = true;
505513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      VLOG(1) << "Pending persisting proxy setting to device";
506bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else {
507bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      PersistConfigToDevice();
508bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
509bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
510bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
511bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProxyConfigServiceImpl::IOSetProxyConfig(
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const ProxyConfig& new_config,
514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    net::ProxyConfigService::ConfigAvailability new_availability) {
515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!BrowserThread::CurrentlyOn(BrowserThread::IO) && can_post_task_) {
516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Posts a task to IO thread with the new config, so it can update
517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // |cached_config_|.
518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Task* task = NewRunnableMethod(this,
519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   &ProxyConfigServiceImpl::IOSetProxyConfig,
520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   new_config,
521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   new_availability);
522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task))
523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      VLOG(1) << "Couldn't post task to IO thread to set new proxy config";
524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
526bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Now guaranteed to be on the correct thread.
528513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  VLOG(1) << "Proxy configuration changed";
529bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  cached_config_ = new_config;
530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  config_availability_ = new_availability;
531bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Notify observers of new proxy config.
532bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  net::ProxyConfig net_config;
533bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  cached_config_.ToNetProxyConfig(&net_config);
534bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                    OnProxyConfigChanged(net_config, config_availability_));
536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProxyConfigServiceImpl::CheckCurrentlyOnIOThread() {
539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProxyConfigServiceImpl::CheckCurrentlyOnUIThread() {
543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
544bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
545bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
546bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}  // namespace chromeos
547