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 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) {
69 &error_msg, "line: %d: %s", line_number, UTF16ToUTF8(error).c_str());
71 error_msg = UTF16ToUTF8(error);
73 dict->SetString(keys::kProxyEventDetails, error_msg);
77 event_router->DispatchEventToRenderers(
78 keys::kProxyEventOnProxyError, args.Pass(), profile, true, GURL());
80 event_router->BroadcastEventToRenderers(
81 keys::kProxyEventOnProxyError, args.Pass(), GURL());
85 ProxyPrefTransformer::ProxyPrefTransformer() {
88 ProxyPrefTransformer::~ProxyPrefTransformer() {
91 Value* ProxyPrefTransformer::ExtensionToBrowserPref(const Value* extension_pref,
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);
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;
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)) {
127 return helpers::CreateProxyConfigDict(
128 mode_enum, pac_mandatory, pac_url, pac_data, proxy_rules_string,
132 Value* ProxyPrefTransformer::BrowserToExtensionPref(const Value* browser_pref) {
133 CHECK(browser_pref->IsType(Value::TYPE_DICTIONARY));
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));
140 ProxyPrefs::ProxyMode mode;
141 if (!config.GetMode(&mode)) {
142 LOG(ERROR) << "Cannot determine proxy mode.";
146 // Build a new ProxyConfig instance as defined in the extension API.
147 scoped_ptr<base::DictionaryValue> extension_pref(new base::DictionaryValue);
149 extension_pref->SetString(keys::kProxyConfigMode,
150 ProxyPrefs::ProxyModeToString(mode));
153 case ProxyPrefs::MODE_DIRECT:
154 case ProxyPrefs::MODE_AUTO_DETECT:
155 case ProxyPrefs::MODE_SYSTEM:
156 // These modes have no further parameters.
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);
165 extension_pref->Set(keys::kProxyConfigPacScript, pac_dict);
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)
174 extension_pref->Set(keys::kProxyConfigRules, proxy_rules_dict);
177 case ProxyPrefs::kModeCount:
180 return extension_pref.release();
183 } // namespace extensions