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