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