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( 69 &error_msg, "line: %d: %s", line_number, UTF16ToUTF8(error).c_str()); 70 } else { 71 error_msg = UTF16ToUTF8(error); 72 } 73 dict->SetString(keys::kProxyEventDetails, error_msg); 74 args->Append(dict); 75 76 if (profile) { 77 event_router->DispatchEventToRenderers( 78 keys::kProxyEventOnProxyError, args.Pass(), profile, true, GURL()); 79 } else { 80 event_router->BroadcastEventToRenderers( 81 keys::kProxyEventOnProxyError, args.Pass(), GURL()); 82 } 83 } 84 85 ProxyPrefTransformer::ProxyPrefTransformer() { 86 } 87 88 ProxyPrefTransformer::~ProxyPrefTransformer() { 89 } 90 91 Value* ProxyPrefTransformer::ExtensionToBrowserPref(const Value* extension_pref, 92 std::string* error, 93 bool* bad_message) { 94 // When ExtensionToBrowserPref is called, the format of |extension_pref| 95 // has been verified already by the extension API to match the schema 96 // defined in the extension API JSON. 97 CHECK(extension_pref->IsType(Value::TYPE_DICTIONARY)); 98 const base::DictionaryValue* config = 99 static_cast<const base::DictionaryValue*>(extension_pref); 100 101 // Extract the various pieces of information passed to 102 // chrome.proxy.settings.set(). Several of these strings will 103 // remain blank no respective values have been passed to set(). 104 // If a values has been passed to set but could not be parsed, we bail 105 // out and return NULL. 106 ProxyPrefs::ProxyMode mode_enum; 107 bool pac_mandatory; 108 std::string pac_url; 109 std::string pac_data; 110 std::string proxy_rules_string; 111 std::string bypass_list; 112 if (!helpers::GetProxyModeFromExtensionPref( 113 config, &mode_enum, error, bad_message) || 114 !helpers::GetPacMandatoryFromExtensionPref( 115 config, &pac_mandatory, error, bad_message) || 116 !helpers::GetPacUrlFromExtensionPref( 117 config, &pac_url, error, bad_message) || 118 !helpers::GetPacDataFromExtensionPref( 119 config, &pac_data, error, bad_message) || 120 !helpers::GetProxyRulesStringFromExtensionPref( 121 config, &proxy_rules_string, error, bad_message) || 122 !helpers::GetBypassListFromExtensionPref( 123 config, &bypass_list, error, bad_message)) { 124 return NULL; 125 } 126 127 return helpers::CreateProxyConfigDict( 128 mode_enum, pac_mandatory, pac_url, pac_data, proxy_rules_string, 129 bypass_list, error); 130 } 131 132 Value* ProxyPrefTransformer::BrowserToExtensionPref(const Value* browser_pref) { 133 CHECK(browser_pref->IsType(Value::TYPE_DICTIONARY)); 134 135 // This is a dictionary wrapper that exposes the proxy configuration stored in 136 // the browser preferences. 137 ProxyConfigDictionary config( 138 static_cast<const base::DictionaryValue*>(browser_pref)); 139 140 ProxyPrefs::ProxyMode mode; 141 if (!config.GetMode(&mode)) { 142 LOG(ERROR) << "Cannot determine proxy mode."; 143 return NULL; 144 } 145 146 // Build a new ProxyConfig instance as defined in the extension API. 147 scoped_ptr<base::DictionaryValue> extension_pref(new base::DictionaryValue); 148 149 extension_pref->SetString(keys::kProxyConfigMode, 150 ProxyPrefs::ProxyModeToString(mode)); 151 152 switch (mode) { 153 case ProxyPrefs::MODE_DIRECT: 154 case ProxyPrefs::MODE_AUTO_DETECT: 155 case ProxyPrefs::MODE_SYSTEM: 156 // These modes have no further parameters. 157 break; 158 case ProxyPrefs::MODE_PAC_SCRIPT: { 159 // A PAC URL either point to a PAC script or contain a base64 encoded 160 // PAC script. In either case we build a PacScript dictionary as defined 161 // in the extension API. 162 base::DictionaryValue* pac_dict = helpers::CreatePacScriptDict(config); 163 if (!pac_dict) 164 return NULL; 165 extension_pref->Set(keys::kProxyConfigPacScript, pac_dict); 166 break; 167 } 168 case ProxyPrefs::MODE_FIXED_SERVERS: { 169 // Build ProxyRules dictionary according to the extension API. 170 base::DictionaryValue* proxy_rules_dict = 171 helpers::CreateProxyRulesDict(config); 172 if (!proxy_rules_dict) 173 return NULL; 174 extension_pref->Set(keys::kProxyConfigRules, proxy_rules_dict); 175 break; 176 } 177 case ProxyPrefs::kModeCount: 178 NOTREACHED(); 179 } 180 return extension_pref.release(); 181 } 182 183 } // namespace extensions 184