1 // Copyright (c) 2012 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/api/proxy/proxy_api.h" 8 9 #include "base/json/json_writer.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "base/values.h" 13 #include "chrome/browser/extensions/api/proxy/proxy_api_constants.h" 14 #include "chrome/browser/extensions/api/proxy/proxy_api_helpers.h" 15 #include "chrome/browser/extensions/event_router_forwarder.h" 16 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/prefs/proxy_config_dictionary.h" 18 #include "net/base/net_errors.h" 19 20 namespace extensions { 21 22 namespace helpers = proxy_api_helpers; 23 namespace keys = proxy_api_constants; 24 25 // static 26 ProxyEventRouter* ProxyEventRouter::GetInstance() { 27 return Singleton<ProxyEventRouter>::get(); 28 } 29 30 ProxyEventRouter::ProxyEventRouter() { 31 } 32 33 ProxyEventRouter::~ProxyEventRouter() { 34 } 35 36 void ProxyEventRouter::OnProxyError( 37 EventRouterForwarder* event_router, 38 void* profile, 39 int error_code) { 40 scoped_ptr<base::ListValue> args(new base::ListValue()); 41 base::DictionaryValue* dict = new base::DictionaryValue(); 42 dict->SetBoolean(keys::kProxyEventFatal, true); 43 dict->SetString(keys::kProxyEventError, net::ErrorToString(error_code)); 44 dict->SetString(keys::kProxyEventDetails, std::string()); 45 args->Append(dict); 46 47 if (profile) { 48 event_router->DispatchEventToRenderers( 49 keys::kProxyEventOnProxyError, args.Pass(), profile, true, GURL()); 50 } else { 51 event_router->BroadcastEventToRenderers( 52 keys::kProxyEventOnProxyError, args.Pass(), GURL()); 53 } 54 } 55 56 void ProxyEventRouter::OnPACScriptError( 57 EventRouterForwarder* event_router, 58 void* profile, 59 int line_number, 60 const base::string16& error) { 61 scoped_ptr<base::ListValue> args(new base::ListValue()); 62 base::DictionaryValue* dict = new base::DictionaryValue(); 63 dict->SetBoolean(keys::kProxyEventFatal, false); 64 dict->SetString(keys::kProxyEventError, 65 net::ErrorToString(net::ERR_PAC_SCRIPT_FAILED)); 66 std::string error_msg; 67 if (line_number != -1) { 68 base::SStringPrintf(&error_msg, 69 "line: %d: %s", 70 line_number, base::UTF16ToUTF8(error).c_str()); 71 } else { 72 error_msg = base::UTF16ToUTF8(error); 73 } 74 dict->SetString(keys::kProxyEventDetails, error_msg); 75 args->Append(dict); 76 77 if (profile) { 78 event_router->DispatchEventToRenderers( 79 keys::kProxyEventOnProxyError, args.Pass(), profile, true, GURL()); 80 } else { 81 event_router->BroadcastEventToRenderers( 82 keys::kProxyEventOnProxyError, args.Pass(), GURL()); 83 } 84 } 85 86 ProxyPrefTransformer::ProxyPrefTransformer() { 87 } 88 89 ProxyPrefTransformer::~ProxyPrefTransformer() { 90 } 91 92 base::Value* ProxyPrefTransformer::ExtensionToBrowserPref( 93 const base::Value* extension_pref, 94 std::string* error, 95 bool* bad_message) { 96 // When ExtensionToBrowserPref is called, the format of |extension_pref| 97 // has been verified already by the extension API to match the schema 98 // defined in the extension API JSON. 99 CHECK(extension_pref->IsType(base::Value::TYPE_DICTIONARY)); 100 const base::DictionaryValue* config = 101 static_cast<const base::DictionaryValue*>(extension_pref); 102 103 // Extract the various pieces of information passed to 104 // chrome.proxy.settings.set(). Several of these strings will 105 // remain blank no respective values have been passed to set(). 106 // If a values has been passed to set but could not be parsed, we bail 107 // out and return NULL. 108 ProxyPrefs::ProxyMode mode_enum; 109 bool pac_mandatory; 110 std::string pac_url; 111 std::string pac_data; 112 std::string proxy_rules_string; 113 std::string bypass_list; 114 if (!helpers::GetProxyModeFromExtensionPref( 115 config, &mode_enum, error, bad_message) || 116 !helpers::GetPacMandatoryFromExtensionPref( 117 config, &pac_mandatory, error, bad_message) || 118 !helpers::GetPacUrlFromExtensionPref( 119 config, &pac_url, error, bad_message) || 120 !helpers::GetPacDataFromExtensionPref( 121 config, &pac_data, error, bad_message) || 122 !helpers::GetProxyRulesStringFromExtensionPref( 123 config, &proxy_rules_string, error, bad_message) || 124 !helpers::GetBypassListFromExtensionPref( 125 config, &bypass_list, error, bad_message)) { 126 return NULL; 127 } 128 129 return helpers::CreateProxyConfigDict( 130 mode_enum, pac_mandatory, pac_url, pac_data, proxy_rules_string, 131 bypass_list, error); 132 } 133 134 base::Value* ProxyPrefTransformer::BrowserToExtensionPref( 135 const base::Value* browser_pref) { 136 CHECK(browser_pref->IsType(base::Value::TYPE_DICTIONARY)); 137 138 // This is a dictionary wrapper that exposes the proxy configuration stored in 139 // the browser preferences. 140 ProxyConfigDictionary config( 141 static_cast<const base::DictionaryValue*>(browser_pref)); 142 143 ProxyPrefs::ProxyMode mode; 144 if (!config.GetMode(&mode)) { 145 LOG(ERROR) << "Cannot determine proxy mode."; 146 return NULL; 147 } 148 149 // Build a new ProxyConfig instance as defined in the extension API. 150 scoped_ptr<base::DictionaryValue> extension_pref(new base::DictionaryValue); 151 152 extension_pref->SetString(keys::kProxyConfigMode, 153 ProxyPrefs::ProxyModeToString(mode)); 154 155 switch (mode) { 156 case ProxyPrefs::MODE_DIRECT: 157 case ProxyPrefs::MODE_AUTO_DETECT: 158 case ProxyPrefs::MODE_SYSTEM: 159 // These modes have no further parameters. 160 break; 161 case ProxyPrefs::MODE_PAC_SCRIPT: { 162 // A PAC URL either point to a PAC script or contain a base64 encoded 163 // PAC script. In either case we build a PacScript dictionary as defined 164 // in the extension API. 165 base::DictionaryValue* pac_dict = helpers::CreatePacScriptDict(config); 166 if (!pac_dict) 167 return NULL; 168 extension_pref->Set(keys::kProxyConfigPacScript, pac_dict); 169 break; 170 } 171 case ProxyPrefs::MODE_FIXED_SERVERS: { 172 // Build ProxyRules dictionary according to the extension API. 173 base::DictionaryValue* proxy_rules_dict = 174 helpers::CreateProxyRulesDict(config); 175 if (!proxy_rules_dict) 176 return NULL; 177 extension_pref->Set(keys::kProxyConfigRules, proxy_rules_dict); 178 break; 179 } 180 case ProxyPrefs::kModeCount: 181 NOTREACHED(); 182 } 183 return extension_pref.release(); 184 } 185 186 } // namespace extensions 187