extension_proxy_api.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Copyright (c) 2010 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/extensions/extension_proxy_api.h"
6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_util.h"
8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/stringprintf.h"
9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/values.h"
1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/prefs/proxy_prefs.h"
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h"
13bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/pref_names.h"
14bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
15bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace {
16bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
17bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// The scheme for which to use a manually specified proxy, not of the proxy URI
18bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// itself.
19bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenenum {
20bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  SCHEME_ALL = 0,
21bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  SCHEME_HTTP,
22bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  SCHEME_HTTPS,
23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  SCHEME_FTP,
24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  SCHEME_SOCKS,
25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  SCHEME_MAX = SCHEME_SOCKS  // Keep this value up to date.
26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// The names of the JavaScript properties to extract from the proxy_rules.
29bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// These must be kept in sync with the SCHEME_* constants.
30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char* field_name[] = { "singleProxy",
31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                             "proxyForHttp",
32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                             "proxyForHttps",
33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                             "proxyForFtp",
34bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                             "socksProxy" };
35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
36bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// The names of the schemes to be used to build the preference value string
37bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// for manual proxy settings.  These must be kept in sync with the SCHEME_*
38bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// constants.
39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst char* scheme_name[] = { "*error*",
40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                              "http",
41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                              "https",
42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                              "ftp",
43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                              "socks" };
44bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
45bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}  // namespace
46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenCOMPILE_ASSERT(SCHEME_MAX == SCHEME_SOCKS, SCHEME_MAX_must_equal_SCHEME_SOCKS);
48bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenCOMPILE_ASSERT(arraysize(field_name) == SCHEME_MAX + 1,
49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen               field_name_array_is_wrong_size);
50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenCOMPILE_ASSERT(arraysize(scheme_name) == SCHEME_MAX + 1,
51bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen               scheme_name_array_is_wrong_size);
52bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
53bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool UseCustomProxySettingsFunction::RunImpl() {
54bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DictionaryValue* proxy_config;
55bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &proxy_config));
56bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string proxy_mode;
5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  proxy_config->GetString("mode", &proxy_mode);
59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DictionaryValue* pac_dict = NULL;
61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  proxy_config->GetDictionary("pacScript", &pac_dict);
62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DictionaryValue* proxy_rules = NULL;
64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  proxy_config->GetDictionary("rules", &proxy_rules);
65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // TODO(battre,gfeher): Make sure all the preferences get always
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // overwritten.
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return ApplyMode(proxy_mode) &&
69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      ApplyPacScript(pac_dict) &&
70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      ApplyProxyRules(proxy_rules);
71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
73bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool UseCustomProxySettingsFunction::GetProxyServer(
74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const DictionaryValue* dict, ProxyServer* proxy_server) {
75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  dict->GetString("scheme", &proxy_server->scheme);
76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXTENSION_FUNCTION_VALIDATE(dict->GetString("host", &proxy_server->host));
77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  dict->GetInteger("port", &proxy_server->port);
78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool UseCustomProxySettingsFunction::ApplyMode(const std::string& mode) {
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // We take control of the mode preference even if none was specified, so that
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // all proxy preferences are controlled by the same extension (if not by a
8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // higher-priority source).
8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool result = true;
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ProxyPrefs::ProxyMode mode_enum;
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!ProxyPrefs::StringToProxyMode(mode, &mode_enum)) {
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    mode_enum = ProxyPrefs::MODE_SYSTEM;
8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(WARNING) << "Invalid mode for proxy settings: " << mode;
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    result = false;
9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ApplyPreference(prefs::kProxyMode, Value::CreateIntegerValue(mode_enum));
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return result;
94bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
96bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool UseCustomProxySettingsFunction::ApplyPacScript(DictionaryValue* pac_dict) {
97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::string pac_url;
98bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (pac_dict)
99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    pac_dict->GetString("url", &pac_url);
100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // We take control of the PAC preference even if none was specified, so that
102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // all proxy preferences are controlled by the same extension (if not by a
103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // higher-priority source).
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ApplyPreference(prefs::kProxyPacUrl, Value::CreateStringValue(pac_url));
105bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool UseCustomProxySettingsFunction::ApplyProxyRules(
109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    DictionaryValue* proxy_rules) {
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!proxy_rules) {
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    ApplyPreference(prefs::kProxyServer, Value::CreateStringValue(""));
112bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return true;
11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
114bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
115bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Local data into which the parameters will be parsed. has_proxy describes
116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // whether a setting was found for the scheme; proxy_dict holds the
117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // DictionaryValues which in turn contain proxy server descriptions, and
118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // proxy_server holds ProxyServer structs containing those descriptions.
119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  bool has_proxy[SCHEME_MAX + 1];
120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DictionaryValue* proxy_dict[SCHEME_MAX + 1];
121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ProxyServer proxy_server[SCHEME_MAX + 1];
122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Looking for all possible proxy types is inefficient if we have a
124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // singleProxy that will supersede per-URL proxies, but it's worth it to keep
125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // the code simple and extensible.
126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (size_t i = 0; i <= SCHEME_MAX; ++i) {
127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    has_proxy[i] = proxy_rules->GetDictionary(field_name[i], &proxy_dict[i]);
128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (has_proxy[i]) {
129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (!GetProxyServer(proxy_dict[i], &proxy_server[i]))
130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        return false;
131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // A single proxy supersedes individual HTTP, HTTPS, and FTP proxies.
135bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (has_proxy[SCHEME_ALL]) {
136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    proxy_server[SCHEME_HTTP] = proxy_server[SCHEME_ALL];
137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    proxy_server[SCHEME_HTTPS] = proxy_server[SCHEME_ALL];
138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    proxy_server[SCHEME_FTP] = proxy_server[SCHEME_ALL];
139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    has_proxy[SCHEME_HTTP] = true;
140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    has_proxy[SCHEME_HTTPS] = true;
141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    has_proxy[SCHEME_FTP] = true;
142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    has_proxy[SCHEME_ALL] = false;
143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
145bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // TODO(pamg): Ensure that if a value is empty, that means "don't use a proxy
146bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // for this scheme".
147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
148bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Build the proxy preference string.
149bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::string proxy_pref;
150bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  for (size_t i = 0; i <= SCHEME_MAX; ++i) {
151bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (has_proxy[i]) {
152bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      // http=foopy:4010;ftp=socks://foopy2:80
153bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (!proxy_pref.empty())
154bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        proxy_pref.append(";");
155bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      proxy_pref.append(scheme_name[i]);
156bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      proxy_pref.append("=");
157bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      proxy_pref.append(proxy_server[i].scheme);
158bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      proxy_pref.append("://");
159bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      proxy_pref.append(proxy_server[i].host);
160bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      if (proxy_server[i].port != ProxyServer::INVALID_PORT) {
161bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        proxy_pref.append(":");
162bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen        proxy_pref.append(base::StringPrintf("%d", proxy_server[i].port));
163bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      }
164bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
165bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
166bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ApplyPreference(prefs::kProxyServer, Value::CreateStringValue(proxy_pref));
168bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
169bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
170bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid UseCustomProxySettingsFunction::ApplyPreference(const char* pref_path,
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                                     Value* pref_value) {
17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  profile()->GetExtensionService()->extension_prefs()
17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      ->SetExtensionControlledPref(extension_id(), pref_path, pref_value);
175bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
176