Home | History | Annotate | Download | only in extensions
      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