1 // Copyright (c) 2011 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 // Implementation of the Chrome Extensions Proxy Settings API. 6 7 #include "chrome/browser/extensions/extension_proxy_api.h" 8 9 #include "base/json/json_writer.h" 10 #include "base/values.h" 11 #include "chrome/browser/extensions/extension_event_router_forwarder.h" 12 #include "chrome/browser/extensions/extension_proxy_api_constants.h" 13 #include "chrome/browser/extensions/extension_proxy_api_helpers.h" 14 #include "chrome/browser/extensions/extension_service.h" 15 #include "chrome/browser/prefs/proxy_config_dictionary.h" 16 #include "net/base/net_errors.h" 17 18 namespace helpers = extension_proxy_api_helpers; 19 namespace keys = extension_proxy_api_constants; 20 21 // static 22 ExtensionProxyEventRouter* ExtensionProxyEventRouter::GetInstance() { 23 return Singleton<ExtensionProxyEventRouter>::get(); 24 } 25 26 ExtensionProxyEventRouter::ExtensionProxyEventRouter() { 27 } 28 29 ExtensionProxyEventRouter::~ExtensionProxyEventRouter() { 30 } 31 32 void ExtensionProxyEventRouter::OnProxyError( 33 ExtensionEventRouterForwarder* event_router, 34 ProfileId profile_id, 35 int error_code) { 36 ListValue args; 37 DictionaryValue* dict = new DictionaryValue(); 38 dict->SetBoolean(keys::kProxyEventFatal, true); 39 dict->SetString(keys::kProxyEventError, net::ErrorToString(error_code)); 40 dict->SetString(keys::kProxyEventDetails, ""); 41 args.Append(dict); 42 43 std::string json_args; 44 base::JSONWriter::Write(&args, false, &json_args); 45 46 if (profile_id != Profile::kInvalidProfileId) { 47 event_router->DispatchEventToRenderers( 48 keys::kProxyEventOnProxyError, json_args, profile_id, true, GURL()); 49 } else { 50 event_router->BroadcastEventToRenderers( 51 keys::kProxyEventOnProxyError, json_args, GURL()); 52 } 53 } 54 55 ProxyPrefTransformer::ProxyPrefTransformer() { 56 } 57 58 ProxyPrefTransformer::~ProxyPrefTransformer() { 59 } 60 61 Value* ProxyPrefTransformer::ExtensionToBrowserPref(const Value* extension_pref, 62 std::string* error) { 63 // When ExtensionToBrowserPref is called, the format of |extension_pref| 64 // has been verified already by the extension API to match the schema 65 // defined in chrome/common/extensions/api/extension_api.json. 66 CHECK(extension_pref->IsType(Value::TYPE_DICTIONARY)); 67 const DictionaryValue* config = 68 static_cast<const DictionaryValue*>(extension_pref); 69 70 // Extract the various pieces of information passed to 71 // chrome.experimental.proxy.settings.set(). Several of these strings will 72 // remain blank no respective values have been passed to set(). 73 // If a values has been passed to set but could not be parsed, we bail 74 // out and return NULL. 75 ProxyPrefs::ProxyMode mode_enum; 76 std::string pac_url; 77 std::string pac_data; 78 std::string proxy_rules_string; 79 std::string bypass_list; 80 if (!helpers::GetProxyModeFromExtensionPref(config, &mode_enum, error) || 81 !helpers::GetPacUrlFromExtensionPref(config, &pac_url, error) || 82 !helpers::GetPacDataFromExtensionPref(config, &pac_data, error) || 83 !helpers::GetProxyRulesStringFromExtensionPref( 84 config, &proxy_rules_string, error) || 85 !helpers::GetBypassListFromExtensionPref(config, &bypass_list, error)) { 86 return NULL; 87 } 88 89 return helpers::CreateProxyConfigDict( 90 mode_enum, pac_url, pac_data, proxy_rules_string, bypass_list, error); 91 } 92 93 Value* ProxyPrefTransformer::BrowserToExtensionPref(const Value* browser_pref) { 94 CHECK(browser_pref->IsType(Value::TYPE_DICTIONARY)); 95 96 // This is a dictionary wrapper that exposes the proxy configuration stored in 97 // the browser preferences. 98 ProxyConfigDictionary config( 99 static_cast<const DictionaryValue*>(browser_pref)); 100 101 ProxyPrefs::ProxyMode mode; 102 if (!config.GetMode(&mode)) { 103 LOG(ERROR) << "Cannot determine proxy mode."; 104 return NULL; 105 } 106 107 // Build a new ProxyConfig instance as defined in the extension API. 108 scoped_ptr<DictionaryValue> extension_pref(new DictionaryValue); 109 110 extension_pref->SetString(keys::kProxyConfigMode, 111 ProxyPrefs::ProxyModeToString(mode)); 112 113 switch (mode) { 114 case ProxyPrefs::MODE_DIRECT: 115 case ProxyPrefs::MODE_AUTO_DETECT: 116 case ProxyPrefs::MODE_SYSTEM: 117 // These modes have no further parameters. 118 break; 119 case ProxyPrefs::MODE_PAC_SCRIPT: { 120 // A PAC URL either point to a PAC script or contain a base64 encoded 121 // PAC script. In either case we build a PacScript dictionary as defined 122 // in the extension API. 123 DictionaryValue* pac_dict = helpers::CreatePacScriptDict(config); 124 if (!pac_dict) 125 return NULL; 126 extension_pref->Set(keys::kProxyConfigPacScript, pac_dict); 127 break; 128 } 129 case ProxyPrefs::MODE_FIXED_SERVERS: { 130 // Build ProxyRules dictionary according to the extension API. 131 DictionaryValue* proxy_rules_dict = helpers::CreateProxyRulesDict(config); 132 if (!proxy_rules_dict) 133 return NULL; 134 extension_pref->Set(keys::kProxyConfigRules, proxy_rules_dict); 135 break; 136 } 137 case ProxyPrefs::kModeCount: 138 NOTREACHED(); 139 } 140 return extension_pref.release(); 141 } 142