diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-22 13:23:47 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-22 13:23:47 +0000 |
commit | 8339da46719b5876723b1182b5ca60e9e07c2d81 (patch) | |
tree | 56ea3e3e2d4a4603e0e6d76ac3123dd4fc5ae7aa | |
parent | 8210f52f74e5e62bcd366119197a7f5aa51020ef (diff) | |
download | chromium_src-8339da46719b5876723b1182b5ca60e9e07c2d81.zip chromium_src-8339da46719b5876723b1182b5ca60e9e07c2d81.tar.gz chromium_src-8339da46719b5876723b1182b5ca60e9e07c2d81.tar.bz2 |
Extension half of the proxy error event
BUG=71067
TEST=test is still disabled, pending network side changes
Review URL: http://codereview.chromium.org/6549015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75585 0039d316-1c4b-4281-b951-d872f2087c98
10 files changed, 444 insertions, 16 deletions
diff --git a/chrome/browser/extensions/extension_io_event_router.cc b/chrome/browser/extensions/extension_io_event_router.cc index 5beb4b8..2c9f234 100644 --- a/chrome/browser/extensions/extension_io_event_router.cc +++ b/chrome/browser/extensions/extension_io_event_router.cc @@ -27,6 +27,17 @@ void ExtensionIOEventRouter::DispatchEventToExtension( extension_id, event_name, event_args)); } +void ExtensionIOEventRouter::DispatchEventToRenderers( + const std::string& event_name, + const std::string& event_args, + const GURL& event_url) const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, + &ExtensionIOEventRouter::DispatchEventToRenderersOnUIThread, + event_name, event_args, event_url)); +} + void ExtensionIOEventRouter::DispatchEventOnUIThread( const std::string& extension_id, const std::string& event_name, @@ -41,3 +52,18 @@ void ExtensionIOEventRouter::DispatchEventOnUIThread( profile_->GetExtensionEventRouter()->DispatchEventToExtension( extension_id, event_name, event_args, profile_, GURL()); } + +void ExtensionIOEventRouter::DispatchEventToRenderersOnUIThread( + const std::string& event_name, + const std::string& event_args, + const GURL& event_url) const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // If the profile has gone away, we're shutting down. If there's no event + // router, the extension system hasn't been initialized. + if (!profile_ || !profile_->GetExtensionEventRouter()) + return; + + profile_->GetExtensionEventRouter()->DispatchEventToRenderers( + event_name, event_args, profile_, event_url); +} diff --git a/chrome/browser/extensions/extension_io_event_router.h b/chrome/browser/extensions/extension_io_event_router.h index eae207b..765b04d 100644 --- a/chrome/browser/extensions/extension_io_event_router.h +++ b/chrome/browser/extensions/extension_io_event_router.h @@ -10,6 +10,7 @@ #include "base/ref_counted.h" +class GURL; class Profile; // For now, this just forwards events from the IO thread to the @@ -29,11 +30,22 @@ class ExtensionIOEventRouter const std::string& event_name, const std::string& event_args) const; + // Same as above, except the event is sent to all extensions that have + // sufficient permissions. + void DispatchEventToRenderers(const std::string& event_name, + const std::string& event_args, + const GURL& event_url) const; + private: void DispatchEventOnUIThread(const std::string& extension_id, const std::string& event_name, const std::string& event_args) const; + void DispatchEventToRenderersOnUIThread( + const std::string& event_name, + const std::string& event_args, + const GURL& event_url) const; + Profile* profile_; DISALLOW_COPY_AND_ASSIGN(ExtensionIOEventRouter); diff --git a/chrome/browser/extensions/extension_proxy_api.cc b/chrome/browser/extensions/extension_proxy_api.cc index 8f40ac4..5416af3 100644 --- a/chrome/browser/extensions/extension_proxy_api.cc +++ b/chrome/browser/extensions/extension_proxy_api.cc @@ -5,15 +5,18 @@ #include "chrome/browser/extensions/extension_proxy_api.h" #include "base/base64.h" +#include "base/json/json_writer.h" #include "base/string_util.h" #include "base/string_tokenizer.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/prefs/proxy_config_dictionary.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/extensions/extension_io_event_router.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/common/extensions/extension_error_utils.h" #include "chrome/common/pref_names.h" +#include "net/base/net_errors.h" #include "net/proxy/proxy_config.h" namespace { @@ -57,6 +60,12 @@ const char kProxyCfgRulePort[] = "port"; const char kProxyCfgBypassList[] = "bypassList"; const char kProxyCfgScheme[] = "scheme"; +const char kProxyEventFatal[] = "fatal"; +const char kProxyEventError[] = "error"; +const char kProxyEventDetails[] = "details"; +const char kProxyEventOnProxyError[] = "experimental.proxy.onProxyError"; + + const char kPACDataUrlPrefix[] = "data:application/x-ns-proxy-autoconfig;base64,"; @@ -101,6 +110,33 @@ bool CreatePACScriptFromDataURL( } // namespace +// static +ExtensionProxyEventRouter* ExtensionProxyEventRouter::GetInstance() { + return Singleton<ExtensionProxyEventRouter>::get(); +} + +ExtensionProxyEventRouter::ExtensionProxyEventRouter() { +} + +ExtensionProxyEventRouter::~ExtensionProxyEventRouter() { +} + +void ExtensionProxyEventRouter::OnProxyError( + const ExtensionIOEventRouter* event_router, + int error_code) { + ListValue args; + DictionaryValue* dict = new DictionaryValue(); + dict->SetBoolean(kProxyEventFatal, true); + dict->SetString(kProxyEventError, net::ErrorToString(error_code)); + dict->SetString(kProxyEventDetails, ""); + args.Append(dict); + + std::string json_args; + base::JSONWriter::Write(&args, false, &json_args); + event_router->DispatchEventToRenderers( + kProxyEventOnProxyError, json_args, GURL()); +} + bool UseCustomProxySettingsFunction::GetProxyServer( const DictionaryValue* dict, net::ProxyServer::Scheme default_scheme, diff --git a/chrome/browser/extensions/extension_proxy_api.h b/chrome/browser/extensions/extension_proxy_api.h index aa408b2..dd5ae97 100644 --- a/chrome/browser/extensions/extension_proxy_api.h +++ b/chrome/browser/extensions/extension_proxy_api.h @@ -7,10 +7,31 @@ #include <string> +#include "base/singleton.h" #include "chrome/browser/extensions/extension_function.h" #include "net/proxy/proxy_config.h" class DictionaryValue; +class ExtensionIOEventRouter; + +// This class observes proxy error events and routes them to the appropriate +// extensions listening to those events. All methods must be called on the IO +// thread unless otherwise specified. +class ExtensionProxyEventRouter { + public: + static ExtensionProxyEventRouter* GetInstance(); + + void OnProxyError(const ExtensionIOEventRouter* event_router, + int error_code); + + private: + friend struct DefaultSingletonTraits<ExtensionProxyEventRouter>; + + ExtensionProxyEventRouter(); + ~ExtensionProxyEventRouter(); + + DISALLOW_COPY_AND_ASSIGN(ExtensionProxyEventRouter); +}; class ProxySettingsFunction : public SyncExtensionFunction { public: diff --git a/chrome/browser/extensions/extension_proxy_apitest.cc b/chrome/browser/extensions/extension_proxy_apitest.cc index 439d915..ad77ed4 100644 --- a/chrome/browser/extensions/extension_proxy_apitest.cc +++ b/chrome/browser/extensions/extension_proxy_apitest.cc @@ -283,3 +283,11 @@ IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, kNoPac, pref_service); } + +// TODO(jochen): enable once network side has landed. Tests error events. +IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, DISABLED_ProxyEvents) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + + ASSERT_TRUE(RunExtensionTest("proxy/events")) << message_; +} diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json index a8ef0e1..05c53a3 100644 --- a/chrome/common/extensions/api/extension_api.json +++ b/chrome/common/extensions/api/extension_api.json @@ -3808,6 +3808,33 @@ } ] } + ], + "events": [ + { + "name": "onProxyError", + "type": "function", + "description": "Notifies about proxy errors.", + "parameters": [ + { + "type": "object", + "name": "details", + "properties": { + "fatal": { + "type": "boolean", + "description": "If true, the error was fatal and the network transaction was aborted. Otherwise, a direct connection is used instead." + }, + "error": { + "type": "string", + "description": "The error description." + }, + "details": { + "type": "string", + "description": "Additional details about the error such as a JavaScript runtime error." + } + } + } + ] + } ] }, { diff --git a/chrome/common/extensions/docs/experimental.proxy.html b/chrome/common/extensions/docs/experimental.proxy.html index fc2a95e..9711b84 100644 --- a/chrome/common/extensions/docs/experimental.proxy.html +++ b/chrome/common/extensions/docs/experimental.proxy.html @@ -315,11 +315,11 @@ </li> </ol> </li> - <li style="display: none; "> - <a>Events</a> + <li> + <a href="#global-events">Events</a> <ol> <li> - <a href="#event-anchor">eventName</a> + <a href="#event-onProxyError">onProxyError</a> </li> </ol> </li> @@ -454,8 +454,7 @@ A proxy server is configured in a <a href="#type-ProxyServer"><code>ProxyServer</code></a> object. The connection to the proxy server (defined by the <code>host</code> attribute) uses the protocol defined in the <code>scheme</code> attribute. If no <code>scheme</code> -is specified, the proxy connection usually defaults to <code>http</code>. Only -the <code>fallbackProxy</code> defaults to <code>socks5</code>. +is specified, the proxy connection defaults to <code>http</code>. </p> <p> @@ -586,7 +585,7 @@ The following code sets a custom pac script. } }; var incognito = false; -chrome.experimental.proxy.useCurrentProxySettings(config, incognito); +chrome.experimental.proxy.useCustomProxySettings(config, incognito); </pre> <p> @@ -1239,24 +1238,22 @@ a <code>rules.httpProxy.port</code> element. </div> <!-- /apiGroup --> <!-- EVENTS --> - <div id="eventsTemplate" class="apiGroup" style="display: none; "> - <a></a> + <div id="eventsTemplate" class="apiGroup"> + <a name="global-events"></a> <h3>Events</h3> <!-- iterates over all events --> <div class="apiItem"> - <a></a> - <h4>event name</h4> + <a name="event-onProxyError"></a> + <h4>onProxyError</h4> <div class="summary"> <!-- Note: intentionally longer 80 columns --> - <span class="subdued">chrome.bookmarks</span><span>onEvent</span><span class="subdued">.addListener</span>(function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>); + <span class="subdued">chrome.experimental.proxy.</span><span>onProxyError</span><span class="subdued">.addListener</span>(function(<span>object details</span>) <span class="subdued">{...}</span>); </div> <div class="description"> - <p class="todo">Undocumented.</p> - <p> - A description from the json schema def of the event goes here. - </p> + <p class="todo" style="display: none; ">Undocumented.</p> + <p>Notifies about proxy errors.</p> <!-- PARAMETERS --> <div> @@ -1264,7 +1261,275 @@ a <code>rules.httpProxy.port</code> element. <dl> <div> <div> - </div> + <dt> + <var>details</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>object</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd> + <dl> + <div> + <div> + <dt> + <var>fatal</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>boolean</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>If true, the error was fatal and the network transaction was aborted. Otherwise, a direct connection is used instead.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>error</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>The error description.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div><div> + <div> + <dt> + <var>details</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span class="enum" style="display: none; ">enumerated</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + <span style="display: none; "></span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>Additional details about the error such as a JavaScript runtime error.</dd> + <dd style="display: none; "> + This parameter was added in version + <b><span></span></b>. + You must omit this parameter in earlier versions, + and you may omit it in any version. If you require this + parameter, the manifest key + <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a> + can ensure that your extension won't be run in an earlier browser version. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> + </div> + </dl> + </dd> + + <!-- OBJECT METHODS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- OBJECT EVENT FIELDS --> + <dd style="display: none; "> + <div></div> + </dd> + + <!-- FUNCTION PARAMETERS --> + <dd style="display: none; "> + <div></div> + </dd> + + </div> </div> </dl> </div> diff --git a/chrome/test/data/extensions/api_test/proxy/events/manifest.json b/chrome/test/data/extensions/api_test/proxy/events/manifest.json new file mode 100644 index 0000000..f763c13 --- /dev/null +++ b/chrome/test/data/extensions/api_test/proxy/events/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "chrome.proxy", + "version": "0.1", + "description": "end-to-end browser test for chrome.proxy API", + "background_page": "test.html", + "permissions": ["experimental", "proxy", "http://127.0.0.1/"] +} diff --git a/chrome/test/data/extensions/api_test/proxy/events/test.html b/chrome/test/data/extensions/api_test/proxy/events/test.html new file mode 100644 index 0000000..46f4d74 --- /dev/null +++ b/chrome/test/data/extensions/api_test/proxy/events/test.html @@ -0,0 +1 @@ +<script src="test.js"></script> diff --git a/chrome/test/data/extensions/api_test/proxy/events/test.js b/chrome/test/data/extensions/api_test/proxy/events/test.js new file mode 100644 index 0000000..2a55c81 --- /dev/null +++ b/chrome/test/data/extensions/api_test/proxy/events/test.js @@ -0,0 +1,25 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// proxy api test +// browser_tests.exe --gtest_filter=ExtensionApiTest.ProxyEvents + +chrome.experimental.proxy.onProxyError.addListener(function (error) { + chrome.test.assertTrue(error.fatal); + chrome.test.assertEq("net::ERR_PROXY_CONNECTION_FAILED", error.error); + chrome.test.assertEq("", error.details); + chrome.test.notifyPass(); +}); + +var rules = { + singleProxy: { host: "does.not.exist" } +}; + +var config = { rules: rules, mode: "fixed_servers" }; +chrome.experimental.proxy.useCustomProxySettings(config); + +var req = new XMLHttpRequest(); +req.open("GET", "http://127.0.0.1/", true); +req.onload = function () { chrome.test.notifyFail(); } +req.send(null); |