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(
     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