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 "chrome/browser/prefs/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 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(
49 keys::kProxyEventOnProxyError
, args
.Pass(), profile
, true, GURL());
51 event_router
->BroadcastEventToRenderers(
52 keys::kProxyEventOnProxyError
, args
.Pass(), GURL());
56 void ProxyEventRouter::OnPACScriptError(
57 EventRouterForwarder
* event_router
,
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
,
70 line_number
, base::UTF16ToUTF8(error
).c_str());
72 error_msg
= base::UTF16ToUTF8(error
);
74 dict
->SetString(keys::kProxyEventDetails
, error_msg
);
78 event_router
->DispatchEventToRenderers(
79 keys::kProxyEventOnProxyError
, args
.Pass(), profile
, true, GURL());
81 event_router
->BroadcastEventToRenderers(
82 keys::kProxyEventOnProxyError
, args
.Pass(), GURL());
86 ProxyPrefTransformer::ProxyPrefTransformer() {
89 ProxyPrefTransformer::~ProxyPrefTransformer() {
92 base::Value
* ProxyPrefTransformer::ExtensionToBrowserPref(
93 const base::Value
* extension_pref
,
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
);
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
;
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
)) {
129 return helpers::CreateProxyConfigDict(
130 mode_enum
, pac_mandatory
, pac_url
, pac_data
, proxy_rules_string
,
134 base::Value
* ProxyPrefTransformer::BrowserToExtensionPref(
135 const base::Value
* browser_pref
) {
136 CHECK(browser_pref
->IsType(base::Value::TYPE_DICTIONARY
));
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
));
143 ProxyPrefs::ProxyMode mode
;
144 if (!config
.GetMode(&mode
)) {
145 LOG(ERROR
) << "Cannot determine proxy mode.";
149 // Build a new ProxyConfig instance as defined in the extension API.
150 scoped_ptr
<base::DictionaryValue
> extension_pref(new base::DictionaryValue
);
152 extension_pref
->SetString(keys::kProxyConfigMode
,
153 ProxyPrefs::ProxyModeToString(mode
));
156 case ProxyPrefs::MODE_DIRECT
:
157 case ProxyPrefs::MODE_AUTO_DETECT
:
158 case ProxyPrefs::MODE_SYSTEM
:
159 // These modes have no further parameters.
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
);
168 extension_pref
->Set(keys::kProxyConfigPacScript
, pac_dict
);
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
)
177 extension_pref
->Set(keys::kProxyConfigRules
, proxy_rules_dict
);
180 case ProxyPrefs::kModeCount
:
183 return extension_pref
.release();
186 } // namespace extensions