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.
5 // Implementation of the Chrome Extensions Proxy Settings API.
7 #include "chrome/browser/extensions/api/proxy/proxy_api.h"
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 "components/proxy_config/proxy_config_dictionary.h"
18 #include "net/base/net_errors.h"
20 namespace extensions
{
22 namespace helpers
= proxy_api_helpers
;
23 namespace keys
= proxy_api_constants
;
26 ProxyEventRouter
* ProxyEventRouter::GetInstance() {
27 return base::Singleton
<ProxyEventRouter
>::get();
30 ProxyEventRouter::ProxyEventRouter() {
33 ProxyEventRouter::~ProxyEventRouter() {
36 void ProxyEventRouter::OnProxyError(
37 EventRouterForwarder
* event_router
,
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());
48 event_router
->DispatchEventToRenderers(events::PROXY_ON_PROXY_ERROR
,
49 keys::kProxyEventOnProxyError
,
50 args
.Pass(), profile
, true, GURL());
52 event_router
->BroadcastEventToRenderers(events::PROXY_ON_PROXY_ERROR
,
53 keys::kProxyEventOnProxyError
,
58 void ProxyEventRouter::OnPACScriptError(
59 EventRouterForwarder
* event_router
,
62 const base::string16
& error
) {
63 scoped_ptr
<base::ListValue
> args(new base::ListValue());
64 base::DictionaryValue
* dict
= new base::DictionaryValue();
65 dict
->SetBoolean(keys::kProxyEventFatal
, false);
66 dict
->SetString(keys::kProxyEventError
,
67 net::ErrorToString(net::ERR_PAC_SCRIPT_FAILED
));
68 std::string error_msg
;
69 if (line_number
!= -1) {
70 base::SStringPrintf(&error_msg
,
72 line_number
, base::UTF16ToUTF8(error
).c_str());
74 error_msg
= base::UTF16ToUTF8(error
);
76 dict
->SetString(keys::kProxyEventDetails
, error_msg
);
80 event_router
->DispatchEventToRenderers(events::PROXY_ON_PROXY_ERROR
,
81 keys::kProxyEventOnProxyError
,
82 args
.Pass(), profile
, true, GURL());
84 event_router
->BroadcastEventToRenderers(events::PROXY_ON_PROXY_ERROR
,
85 keys::kProxyEventOnProxyError
,
90 ProxyPrefTransformer::ProxyPrefTransformer() {
93 ProxyPrefTransformer::~ProxyPrefTransformer() {
96 base::Value
* ProxyPrefTransformer::ExtensionToBrowserPref(
97 const base::Value
* extension_pref
,
100 // When ExtensionToBrowserPref is called, the format of |extension_pref|
101 // has been verified already by the extension API to match the schema
102 // defined in the extension API JSON.
103 CHECK(extension_pref
->IsType(base::Value::TYPE_DICTIONARY
));
104 const base::DictionaryValue
* config
=
105 static_cast<const base::DictionaryValue
*>(extension_pref
);
107 // Extract the various pieces of information passed to
108 // chrome.proxy.settings.set(). Several of these strings will
109 // remain blank no respective values have been passed to set().
110 // If a values has been passed to set but could not be parsed, we bail
111 // out and return NULL.
112 ProxyPrefs::ProxyMode mode_enum
;
115 std::string pac_data
;
116 std::string proxy_rules_string
;
117 std::string bypass_list
;
118 if (!helpers::GetProxyModeFromExtensionPref(
119 config
, &mode_enum
, error
, bad_message
) ||
120 !helpers::GetPacMandatoryFromExtensionPref(
121 config
, &pac_mandatory
, error
, bad_message
) ||
122 !helpers::GetPacUrlFromExtensionPref(
123 config
, &pac_url
, error
, bad_message
) ||
124 !helpers::GetPacDataFromExtensionPref(
125 config
, &pac_data
, error
, bad_message
) ||
126 !helpers::GetProxyRulesStringFromExtensionPref(
127 config
, &proxy_rules_string
, error
, bad_message
) ||
128 !helpers::GetBypassListFromExtensionPref(
129 config
, &bypass_list
, error
, bad_message
)) {
133 return helpers::CreateProxyConfigDict(
134 mode_enum
, pac_mandatory
, pac_url
, pac_data
, proxy_rules_string
,
138 base::Value
* ProxyPrefTransformer::BrowserToExtensionPref(
139 const base::Value
* browser_pref
) {
140 CHECK(browser_pref
->IsType(base::Value::TYPE_DICTIONARY
));
142 // This is a dictionary wrapper that exposes the proxy configuration stored in
143 // the browser preferences.
144 ProxyConfigDictionary
config(
145 static_cast<const base::DictionaryValue
*>(browser_pref
));
147 ProxyPrefs::ProxyMode mode
;
148 if (!config
.GetMode(&mode
)) {
149 LOG(ERROR
) << "Cannot determine proxy mode.";
153 // Build a new ProxyConfig instance as defined in the extension API.
154 scoped_ptr
<base::DictionaryValue
> extension_pref(new base::DictionaryValue
);
156 extension_pref
->SetString(keys::kProxyConfigMode
,
157 ProxyPrefs::ProxyModeToString(mode
));
160 case ProxyPrefs::MODE_DIRECT
:
161 case ProxyPrefs::MODE_AUTO_DETECT
:
162 case ProxyPrefs::MODE_SYSTEM
:
163 // These modes have no further parameters.
165 case ProxyPrefs::MODE_PAC_SCRIPT
: {
166 // A PAC URL either point to a PAC script or contain a base64 encoded
167 // PAC script. In either case we build a PacScript dictionary as defined
168 // in the extension API.
169 base::DictionaryValue
* pac_dict
= helpers::CreatePacScriptDict(config
);
172 extension_pref
->Set(keys::kProxyConfigPacScript
, pac_dict
);
175 case ProxyPrefs::MODE_FIXED_SERVERS
: {
176 // Build ProxyRules dictionary according to the extension API.
177 base::DictionaryValue
* proxy_rules_dict
=
178 helpers::CreateProxyRulesDict(config
);
179 if (!proxy_rules_dict
)
181 extension_pref
->Set(keys::kProxyConfigRules
, proxy_rules_dict
);
184 case ProxyPrefs::kModeCount
:
187 return extension_pref
.release();
190 } // namespace extensions