• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
GetInstance()26 ProxyEventRouter* ProxyEventRouter::GetInstance() {
27   return Singleton<ProxyEventRouter>::get();
28 }
29 
ProxyEventRouter()30 ProxyEventRouter::ProxyEventRouter() {
31 }
32 
~ProxyEventRouter()33 ProxyEventRouter::~ProxyEventRouter() {
34 }
35 
OnProxyError(EventRouterForwarder * event_router,void * profile,int error_code)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 
OnPACScriptError(EventRouterForwarder * event_router,void * profile,int line_number,const base::string16 & error)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 
ProxyPrefTransformer()86 ProxyPrefTransformer::ProxyPrefTransformer() {
87 }
88 
~ProxyPrefTransformer()89 ProxyPrefTransformer::~ProxyPrefTransformer() {
90 }
91 
ExtensionToBrowserPref(const base::Value * extension_pref,std::string * error,bool * bad_message)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 
BrowserToExtensionPref(const base::Value * browser_pref)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