172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 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 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Implementation of the Chrome Extensions Proxy Settings API. 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/extensions/extension_proxy_api.h" 8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/json/json_writer.h" 10bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/values.h" 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/extensions/extension_event_router_forwarder.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_proxy_api_constants.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_proxy_api_helpers.h" 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/proxy_config_dictionary.h" 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/net_errors.h" 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace helpers = extension_proxy_api_helpers; 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace keys = extension_proxy_api_constants; 20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 22dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenExtensionProxyEventRouter* ExtensionProxyEventRouter::GetInstance() { 23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return Singleton<ExtensionProxyEventRouter>::get(); 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 26dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenExtensionProxyEventRouter::ExtensionProxyEventRouter() { 27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 29dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenExtensionProxyEventRouter::~ExtensionProxyEventRouter() { 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ExtensionProxyEventRouter::OnProxyError( 33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ExtensionEventRouterForwarder* event_router, 34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ProfileId profile_id, 35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int error_code) { 36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ListValue args; 37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DictionaryValue* dict = new DictionaryValue(); 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetBoolean(keys::kProxyEventFatal, true); 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetString(keys::kProxyEventError, net::ErrorToString(error_code)); 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetString(keys::kProxyEventDetails, ""); 41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen args.Append(dict); 42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string json_args; 44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen base::JSONWriter::Write(&args, false, &json_args); 45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (profile_id != Profile::kInvalidProfileId) { 47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen event_router->DispatchEventToRenderers( 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen keys::kProxyEventOnProxyError, json_args, profile_id, true, GURL()); 49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen event_router->BroadcastEventToRenderers( 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen keys::kProxyEventOnProxyError, json_args, GURL()); 52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenProxyPrefTransformer::ProxyPrefTransformer() { 56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenProxyPrefTransformer::~ProxyPrefTransformer() { 5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenValue* ProxyPrefTransformer::ExtensionToBrowserPref(const Value* extension_pref, 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string* error) { 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // When ExtensionToBrowserPref is called, the format of |extension_pref| 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // has been verified already by the extension API to match the schema 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // defined in chrome/common/extensions/api/extension_api.json. 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(extension_pref->IsType(Value::TYPE_DICTIONARY)); 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const DictionaryValue* config = 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<const DictionaryValue*>(extension_pref); 6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Extract the various pieces of information passed to 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // chrome.experimental.proxy.settings.set(). Several of these strings will 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // remain blank no respective values have been passed to set(). 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If a values has been passed to set but could not be parsed, we bail 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // out and return NULL. 7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ProxyPrefs::ProxyMode mode_enum; 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string pac_url; 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string pac_data; 7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string proxy_rules_string; 7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string bypass_list; 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!helpers::GetProxyModeFromExtensionPref(config, &mode_enum, error) || 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !helpers::GetPacUrlFromExtensionPref(config, &pac_url, error) || 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !helpers::GetPacDataFromExtensionPref(config, &pac_data, error) || 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !helpers::GetProxyRulesStringFromExtensionPref( 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen config, &proxy_rules_string, error) || 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !helpers::GetBypassListFromExtensionPref(config, &bypass_list, error)) { 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return helpers::CreateProxyConfigDict( 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen mode_enum, pac_url, pac_data, proxy_rules_string, bypass_list, error); 9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenValue* ProxyPrefTransformer::BrowserToExtensionPref(const Value* browser_pref) { 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(browser_pref->IsType(Value::TYPE_DICTIONARY)); 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This is a dictionary wrapper that exposes the proxy configuration stored in 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the browser preferences. 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProxyConfigDictionary config( 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen static_cast<const DictionaryValue*>(browser_pref)); 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ProxyPrefs::ProxyMode mode; 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!config.GetMode(&mode)) { 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(ERROR) << "Cannot determine proxy mode."; 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Build a new ProxyConfig instance as defined in the extension API. 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<DictionaryValue> extension_pref(new DictionaryValue); 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen extension_pref->SetString(keys::kProxyConfigMode, 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProxyPrefs::ProxyModeToString(mode)); 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (mode) { 11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ProxyPrefs::MODE_DIRECT: 11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ProxyPrefs::MODE_AUTO_DETECT: 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ProxyPrefs::MODE_SYSTEM: 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // These modes have no further parameters. 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ProxyPrefs::MODE_PAC_SCRIPT: { 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // A PAC URL either point to a PAC script or contain a base64 encoded 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // PAC script. In either case we build a PacScript dictionary as defined 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // in the extension API. 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* pac_dict = helpers::CreatePacScriptDict(config); 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!pac_dict) 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen extension_pref->Set(keys::kProxyConfigPacScript, pac_dict); 12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ProxyPrefs::MODE_FIXED_SERVERS: { 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Build ProxyRules dictionary according to the extension API. 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* proxy_rules_dict = helpers::CreateProxyRulesDict(config); 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!proxy_rules_dict) 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen extension_pref->Set(keys::kProxyConfigRules, proxy_rules_dict); 13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ProxyPrefs::kModeCount: 13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return extension_pref.release(); 141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 142