diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-01 21:38:16 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-01 21:38:16 +0000 |
commit | d05ef99c71c3d4db779be737102807cbab88ca45 (patch) | |
tree | b64aa3b5117ecce666372bbc77b6558984194bfa | |
parent | 1e1a3ce6a6e266ce93b78fa3c0534aec3db3e2c3 (diff) | |
download | chromium_src-d05ef99c71c3d4db779be737102807cbab88ca45.zip chromium_src-d05ef99c71c3d4db779be737102807cbab88ca45.tar.gz chromium_src-d05ef99c71c3d4db779be737102807cbab88ca45.tar.bz2 |
Unreverting: First steps towards webRequest extension API.
Only an asynchronous version of onBeforeRequest is implement, with
limited data being passed.
Original CL: http://src.chromium.org/viewvc/chrome?view=rev&revision=73196
BUG=60101
TEST=no
Review URL: http://codereview.chromium.org/6246032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73344 0039d316-1c4b-4281-b951-d872f2087c98
25 files changed, 356 insertions, 6 deletions
diff --git a/chrome/browser/extensions/extension_io_event_router.cc b/chrome/browser/extensions/extension_io_event_router.cc new file mode 100644 index 0000000..64ddfc0 --- /dev/null +++ b/chrome/browser/extensions/extension_io_event_router.cc @@ -0,0 +1,39 @@ +// 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. + +#include "chrome/browser/extensions/extension_io_event_router.h" + +#include "googleurl/src/gurl.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/browser/extensions/extension_event_router.h" +#include "chrome/browser/profiles/profile.h" + +ExtensionIOEventRouter::ExtensionIOEventRouter(Profile* profile) + : profile_(profile) { +} + +ExtensionIOEventRouter::~ExtensionIOEventRouter() { +} + +void ExtensionIOEventRouter::DispatchEvent( + const std::string& event_name, const std::string& event_args) const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, + &ExtensionIOEventRouter::DispatchEventOnUIThread, + event_name, event_args)); +} + +void ExtensionIOEventRouter::DispatchEventOnUIThread( + const std::string& event_name, const std::string& event_args) 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_, GURL()); +} diff --git a/chrome/browser/extensions/extension_io_event_router.h b/chrome/browser/extensions/extension_io_event_router.h new file mode 100755 index 0000000..1a27890 --- /dev/null +++ b/chrome/browser/extensions/extension_io_event_router.h @@ -0,0 +1,40 @@ +// 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. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_IO_EVENT_ROUTER_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_IO_EVENT_ROUTER_H_ +#pragma once + +#include <string> + +#include "base/ref_counted.h" + +class Profile; + +// For now, this just forwards events from the IO thread to the +// ExtensionEventRouter on the UI thread. +// TODO(mpcomplete): eventually I want this to have its own copy of the event +// listeners so it can bypass the jump to the UI thread. +class ExtensionIOEventRouter + : public base::RefCountedThreadSafe<ExtensionIOEventRouter> { + public: + explicit ExtensionIOEventRouter(Profile* profile); + ~ExtensionIOEventRouter(); + + void DestroyingProfile() { profile_ = NULL; } + + // Dispatch the named event to every extension listening to that event. + void DispatchEvent(const std::string& event_name, + const std::string& event_args) const; + + private: + Profile* profile_; + + void DispatchEventOnUIThread(const std::string& event_name, + const std::string& event_args) const; + + DISALLOW_COPY_AND_ASSIGN(ExtensionIOEventRouter); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_IO_EVENT_ROUTER_H_ diff --git a/chrome/browser/extensions/extension_webrequest_api.cc b/chrome/browser/extensions/extension_webrequest_api.cc new file mode 100755 index 0000000..3ca3fca --- /dev/null +++ b/chrome/browser/extensions/extension_webrequest_api.cc @@ -0,0 +1,43 @@ +// 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. + +#include "chrome/browser/extensions/extension_webrequest_api.h" + +#include "base/json/json_writer.h" +#include "base/values.h" +#include "chrome/browser/extensions/extension_io_event_router.h" +#include "chrome/browser/extensions/extension_webrequest_api_constants.h" +#include "googleurl/src/gurl.h" + +namespace keys = extension_webrequest_api_constants; + +// static +ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() { + return Singleton<ExtensionWebRequestEventRouter>::get(); +} + +ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter() { +} + +ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() { +} + +void ExtensionWebRequestEventRouter::OnBeforeRequest( + const ExtensionIOEventRouter* event_router, const GURL& url, + const std::string& method) { + ListValue args; + DictionaryValue* dict = new DictionaryValue(); + dict->SetString(keys::kUrlKey, url.spec()); + dict->SetString(keys::kMethodKey, method); + // TODO(mpcomplete): implement + dict->SetInteger(keys::kTabIdKey, 0); + dict->SetInteger(keys::kRequestIdKey, 0); + dict->SetString(keys::kTypeKey, "main_frame"); + dict->SetInteger(keys::kTimeStampKey, 1); + args.Append(dict); + + std::string json_args; + base::JSONWriter::Write(&args, false, &json_args); + event_router->DispatchEvent(keys::kOnBeforeRequest, json_args); +} diff --git a/chrome/browser/extensions/extension_webrequest_api.h b/chrome/browser/extensions/extension_webrequest_api.h new file mode 100755 index 0000000..1945627 --- /dev/null +++ b/chrome/browser/extensions/extension_webrequest_api.h @@ -0,0 +1,35 @@ +// 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. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBREQUEST_API_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBREQUEST_API_H_ +#pragma once + +#include <string> + +#include "base/singleton.h" + +class ExtensionIOEventRouter; +class GURL; + +// IO thread +class ExtensionWebRequestEventRouter { + public: + static ExtensionWebRequestEventRouter* GetInstance(); + + // TODO(mpcomplete): additional params + void OnBeforeRequest(const ExtensionIOEventRouter* event_router, + const GURL& url, const std::string& method); + + private: + friend struct DefaultSingletonTraits<ExtensionWebRequestEventRouter>; + + ExtensionWebRequestEventRouter(); + ~ExtensionWebRequestEventRouter(); + + DISALLOW_COPY_AND_ASSIGN(ExtensionWebRequestEventRouter); +}; + + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBREQUEST_API_H_ diff --git a/chrome/browser/extensions/extension_webrequest_apitest.cc b/chrome/browser/extensions/extension_webrequest_apitest.cc index 833312f..7c25be8 100644 --- a/chrome/browser/extensions/extension_webrequest_apitest.cc +++ b/chrome/browser/extensions/extension_webrequest_apitest.cc @@ -12,3 +12,10 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebRequest) { ASSERT_TRUE(RunExtensionTest("webrequest/api")) << message_; } + +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebRequestEvents) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + + ASSERT_TRUE(RunExtensionTest("webrequest/events")) << message_; +} diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index d5af8f0..127f53e 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -193,6 +193,7 @@ ConstructProxyScriptFetcherContext(IOThread::Globals* globals, globals->proxy_script_fetcher_http_transaction_factory.get()); // In-memory cookie store. context->set_cookie_store(new net::CookieMonster(NULL, NULL)); + // TODO(mpcomplete): give it a SystemNetworkDelegate. return context; } diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index a657b26..0c92721 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc @@ -5,11 +5,32 @@ #include "chrome/browser/net/chrome_network_delegate.h" #include "base/logging.h" +#include "chrome/browser/extensions/extension_webrequest_api.h" +#include "chrome/browser/net/chrome_url_request_context.h" #include "net/http/http_request_headers.h" +#include "net/url_request/url_request.h" + +namespace { + +// Get the event router from the request context. Currently only +// ChromeURLRequestContexts use a network delegate, so the cast is guaranteed to +// work. +const ExtensionIOEventRouter* GetIOEventRouter( + net::URLRequestContext* context) { + return static_cast<ChromeURLRequestContext*>(context)-> + extension_io_event_router(); +} + +} // namespace ChromeNetworkDelegate::ChromeNetworkDelegate() {} ChromeNetworkDelegate::~ChromeNetworkDelegate() {} +void ChromeNetworkDelegate::OnBeforeURLRequest(net::URLRequest* request) { + ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest( + GetIOEventRouter(request->context()), request->url(), request->method()); +} + void ChromeNetworkDelegate::OnSendHttpRequest( net::HttpRequestHeaders* headers) { DCHECK(headers); diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h index 55336d6..8bff160 100644 --- a/chrome/browser/net/chrome_network_delegate.h +++ b/chrome/browser/net/chrome_network_delegate.h @@ -10,15 +10,14 @@ #include "net/http/http_network_delegate.h" // ChromeNetworkDelegate is the central point from within the chrome code to -// add hooks into the network stack. In the future, we can use this for -// extensions to register hooks for the network stack. +// add hooks into the network stack. class ChromeNetworkDelegate : public net::HttpNetworkDelegate { public: ChromeNetworkDelegate(); ~ChromeNetworkDelegate(); // net::HttpNetworkDelegate methods: - + virtual void OnBeforeURLRequest(net::URLRequest* request); virtual void OnSendHttpRequest(net::HttpRequestHeaders* headers); // TODO(willchan): Add functions for consumers to register ways to diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc index dc6853a..81e0474 100644 --- a/chrome/browser/net/chrome_url_request_context.cc +++ b/chrome/browser/net/chrome_url_request_context.cc @@ -263,6 +263,7 @@ ChromeURLRequestContext* FactoryForOriginal::Create() { context->set_host_resolver(io_thread_globals->host_resolver.get()); context->set_cert_verifier(io_thread_globals->cert_verifier.get()); context->set_dnsrr_resolver(io_thread_globals->dnsrr_resolver.get()); + context->set_network_delegate(&io_thread_globals->network_delegate); context->set_http_auth_handler_factory( io_thread_globals->http_auth_handler_factory.get()); @@ -368,6 +369,7 @@ ChromeURLRequestContext* FactoryForExtensions::Create() { chrome::kExtensionScheme}; cookie_monster->SetCookieableSchemes(schemes, 2); context->set_cookie_store(cookie_monster); + context->set_network_delegate(&io_thread_globals->network_delegate); // TODO(cbentzel): How should extensions handle HTTP Authentication? context->set_http_auth_handler_factory( io_thread_globals->http_auth_handler_factory.get()); @@ -402,6 +404,7 @@ ChromeURLRequestContext* FactoryForOffTheRecord::Create() { context->set_cert_verifier(io_thread_globals->cert_verifier.get()); context->set_http_auth_handler_factory( io_thread_globals->http_auth_handler_factory.get()); + context->set_network_delegate(&io_thread_globals->network_delegate); const CommandLine& command_line = *CommandLine::ForCurrentProcess(); context->set_proxy_service( @@ -477,6 +480,7 @@ ChromeURLRequestContext* FactoryForMedia::Create() { // TODO(willchan): Make a global ProxyService available in IOThread::Globals. context->set_proxy_service(main_context->proxy_service()); + context->set_network_delegate(main_context->network_delegate()); // Also share the cookie store of the common profile. context->set_cookie_store(main_context->cookie_store()); @@ -855,6 +859,7 @@ ChromeURLRequestContextFactory::ChromeURLRequestContextFactory(Profile* profile) blob_storage_context_ = profile->GetBlobStorageContext(); file_system_context_ = profile->GetFileSystemContext(); extension_info_map_ = profile->GetExtensionInfoMap(); + extension_io_event_router_ = profile->GetExtensionIOEventRouter(); prerender_manager_ = profile->GetPrerenderManager(); } @@ -881,5 +886,6 @@ void ChromeURLRequestContextFactory::ApplyProfileParametersToContext( context->set_blob_storage_context(blob_storage_context_); context->set_file_system_context(file_system_context_); context->set_extension_info_map(extension_info_map_); + context->set_extension_io_event_router(extension_io_event_router_); context->set_prerender_manager(prerender_manager_); } diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h index f65f63c..50f2d66 100644 --- a/chrome/browser/net/chrome_url_request_context.h +++ b/chrome/browser/net/chrome_url_request_context.h @@ -14,6 +14,8 @@ #include "chrome/browser/chrome_blob_storage_context.h" #include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/extensions/extension_info_map.h" +#include "chrome/browser/extensions/extension_io_event_router.h" +#include "chrome/browser/extensions/extension_webrequest_api.h" #include "chrome/browser/host_zoom_map.h" #include "chrome/browser/io_thread.h" #include "chrome/browser/net/chrome_cookie_policy.h" @@ -91,6 +93,10 @@ class ChromeURLRequestContext : public net::URLRequestContext { return extension_info_map_; } + const ExtensionIOEventRouter* extension_io_event_router() const { + return extension_io_event_router_; + } + PrerenderManager* prerender_manager() { return prerender_manager_.get(); } @@ -155,9 +161,8 @@ class ChromeURLRequestContext : public net::URLRequestContext { void set_extension_info_map(ExtensionInfoMap* map) { extension_info_map_ = map; } - void set_network_delegate( - net::HttpNetworkDelegate* network_delegate) { - network_delegate_ = network_delegate; + void set_extension_io_event_router(ExtensionIOEventRouter* router) { + extension_io_event_router_ = router; } void set_prerender_manager(PrerenderManager* prerender_manager) { prerender_manager_ = prerender_manager; @@ -183,6 +188,7 @@ class ChromeURLRequestContext : public net::URLRequestContext { scoped_refptr<fileapi::SandboxedFileSystemContext> file_system_context_; // TODO(aa): This should use chrome/common/extensions/extension_set.h. scoped_refptr<ExtensionInfoMap> extension_info_map_; + scoped_refptr<ExtensionIOEventRouter> extension_io_event_router_; scoped_refptr<PrerenderManager> prerender_manager_; bool is_off_the_record_; @@ -353,6 +359,7 @@ class ChromeURLRequestContextFactory { scoped_refptr<ChromeBlobStorageContext> blob_storage_context_; scoped_refptr<fileapi::SandboxedFileSystemContext> file_system_context_; scoped_refptr<ExtensionInfoMap> extension_info_map_; + scoped_refptr<ExtensionIOEventRouter> extension_io_event_router_; scoped_refptr<PrerenderManager> prerender_manager_; FilePath profile_dir_path_; diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index c16e3bc..1eb4077 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc @@ -261,6 +261,10 @@ class OffTheRecordProfileImpl : public Profile, return GetOriginalProfile()->GetExtensionEventRouter(); } + virtual ExtensionIOEventRouter* GetExtensionIOEventRouter() { + return GetOriginalProfile()->GetExtensionIOEventRouter(); + } + virtual SSLHostState* GetSSLHostState() { if (!ssl_host_state_.get()) ssl_host_state_.reset(new SSLHostState()); diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h index 8af0983..618d44b 100644 --- a/chrome/browser/profiles/profile.h +++ b/chrome/browser/profiles/profile.h @@ -58,6 +58,7 @@ class Extension; class ExtensionDevToolsManager; class ExtensionEventRouter; class ExtensionInfoMap; +class ExtensionIOEventRouter; class ExtensionMessageService; class ExtensionPrefValueMap; class ExtensionProcessManager; @@ -218,6 +219,9 @@ class Profile { // Accessor. The instance is created at startup. virtual ExtensionEventRouter* GetExtensionEventRouter() = 0; + // Accessor. The instance is created at startup. + virtual ExtensionIOEventRouter* GetExtensionIOEventRouter() = 0; + // Retrieves a pointer to the SSLHostState associated with this profile. // The SSLHostState is lazily created the first time that this method is // called. diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 0363424..bb47a75 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc @@ -33,6 +33,7 @@ #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_event_router.h" #include "chrome/browser/extensions/extension_info_map.h" +#include "chrome/browser/extensions/extension_io_event_router.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extension_pref_store.h" #include "chrome/browser/extensions/extension_process_manager.h" @@ -318,6 +319,7 @@ ProfileImpl::ProfileImpl(const FilePath& path) background_contents_service_.reset( new BackgroundContentsService(this, CommandLine::ForCurrentProcess())); + extension_io_event_router_ = new ExtensionIOEventRouter(this); extension_info_map_ = new ExtensionInfoMap(); GetPolicyContext()->Initialize(); @@ -343,6 +345,7 @@ void ProfileImpl::InitExtensions() { extension_process_manager_.reset(ExtensionProcessManager::Create(this)); extension_event_router_.reset(new ExtensionEventRouter(this)); + extension_io_event_router_ = new ExtensionIOEventRouter(this); extension_message_service_ = new ExtensionMessageService(this); ExtensionErrorReporter::Init(true); // allow noisy errors. @@ -526,6 +529,7 @@ ProfileImpl::~ProfileImpl() { if (default_request_context_ == request_context_) default_request_context_ = NULL; + CleanupRequestContext(request_context_); CleanupRequestContext(media_request_context_); CleanupRequestContext(extensions_request_context_); @@ -542,6 +546,9 @@ ProfileImpl::~ProfileImpl() { // HistoryService first. favicon_service_ = NULL; + if (extension_io_event_router_) + extension_io_event_router_->DestroyingProfile(); + if (extension_message_service_) extension_message_service_->DestroyingProfile(); @@ -660,6 +667,10 @@ ExtensionEventRouter* ProfileImpl::GetExtensionEventRouter() { return extension_event_router_.get(); } +ExtensionIOEventRouter* ProfileImpl::GetExtensionIOEventRouter() { + return extension_io_event_router_.get(); +} + SSLHostState* ProfileImpl::GetSSLHostState() { if (!ssl_host_state_.get()) ssl_host_state_.reset(new SSLHostState()); diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index 6eb1597..d455bb9 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h @@ -61,6 +61,7 @@ class ProfileImpl : public Profile, virtual ExtensionProcessManager* GetExtensionProcessManager(); virtual ExtensionMessageService* GetExtensionMessageService(); virtual ExtensionEventRouter* GetExtensionEventRouter(); + virtual ExtensionIOEventRouter* GetExtensionIOEventRouter(); virtual FaviconService* GetFaviconService(ServiceAccessType sat); virtual HistoryService* GetHistoryService(ServiceAccessType sat); virtual HistoryService* GetHistoryServiceWithoutCreating(); @@ -193,6 +194,7 @@ class ProfileImpl : public Profile, scoped_ptr<ExtensionProcessManager> extension_process_manager_; scoped_refptr<ExtensionMessageService> extension_message_service_; scoped_ptr<ExtensionEventRouter> extension_event_router_; + scoped_refptr<ExtensionIOEventRouter> extension_io_event_router_; scoped_ptr<SSLHostState> ssl_host_state_; scoped_refptr<net::TransportSecurityState> transport_security_state_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 70407db..7d652ea 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1133,6 +1133,8 @@ 'browser/extensions/extension_input_api.h', 'browser/extensions/extension_install_ui.cc', 'browser/extensions/extension_install_ui.h', + 'browser/extensions/extension_io_event_router.cc', + 'browser/extensions/extension_io_event_router.h', 'browser/extensions/extension_management_api.cc', 'browser/extensions/extension_management_api.h', 'browser/extensions/extension_menu_manager.cc', @@ -1191,6 +1193,8 @@ 'browser/extensions/extension_tts_api_win.cc', 'browser/extensions/extension_updater.cc', 'browser/extensions/extension_updater.h', + 'browser/extensions/extension_webrequest_api.cc', + 'browser/extensions/extension_webrequest_api.h', 'browser/extensions/extension_webnavigation_api.cc', 'browser/extensions/extension_webnavigation_api.h', 'browser/extensions/extension_webnavigation_api_constants.cc', diff --git a/chrome/test/data/extensions/api_test/webrequest/events/complexLoad/a.html b/chrome/test/data/extensions/api_test/webrequest/events/complexLoad/a.html new file mode 100644 index 0000000..eabe7b8 --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrequest/events/complexLoad/a.html @@ -0,0 +1 @@ +<iframe src="b.html"></iframe> diff --git a/chrome/test/data/extensions/api_test/webrequest/events/complexLoad/b.html b/chrome/test/data/extensions/api_test/webrequest/events/complexLoad/b.html new file mode 100755 index 0000000..4ef22cc --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrequest/events/complexLoad/b.html @@ -0,0 +1 @@ +<img src="b.jpg"></a>
diff --git a/chrome/test/data/extensions/api_test/webrequest/events/complexLoad/b.jpg b/chrome/test/data/extensions/api_test/webrequest/events/complexLoad/b.jpg new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrequest/events/complexLoad/b.jpg diff --git a/chrome/test/data/extensions/api_test/webrequest/events/manifest.json b/chrome/test/data/extensions/api_test/webrequest/events/manifest.json new file mode 100644 index 0000000..1511d09 --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrequest/events/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "request", + "version": "1.0", + "description": "Tests the webRequest API events.", + "permissions": ["experimental", "tabs"], + "background_page": "test.html" +} diff --git a/chrome/test/data/extensions/api_test/webrequest/events/simpleLoad/a.html b/chrome/test/data/extensions/api_test/webrequest/events/simpleLoad/a.html new file mode 100644 index 0000000..18ecdcb --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrequest/events/simpleLoad/a.html @@ -0,0 +1 @@ +<html></html> diff --git a/chrome/test/data/extensions/api_test/webrequest/events/test.html b/chrome/test/data/extensions/api_test/webrequest/events/test.html new file mode 100644 index 0000000..9d4203b --- /dev/null +++ b/chrome/test/data/extensions/api_test/webrequest/events/test.html @@ -0,0 +1,101 @@ +<script> +var expectedEventData; +var capturedEventData; + +function expect(data) { + expectedEventData = data; + capturedEventData = []; +} + +function checkExpectations() { + if (capturedEventData.length < expectedEventData.length) { + return; + } + // TODO(mpcomplete): allow partial ordering of events + chrome.test.assertEq(JSON.stringify(expectedEventData), + JSON.stringify(capturedEventData)); + chrome.test.succeed(); +} + +function captureEvent(name, details) { + // TODO(mpcomplete): implement the rest of the parameters. + delete details.requestId; + delete details.tabId; + delete details.timeStamp; + delete details.type; + capturedEventData.push([name, details]); + checkExpectations(); +} + +chrome.experimental.webRequest.onBeforeRequest.addListener( + function(details) { + captureEvent("onBeforeRequest", details); +}); +chrome.experimental.webRequest.onRequestSent.addListener( + function(details) { + captureEvent("onRequestSent", details); +}); +chrome.experimental.webRequest.onHeadersReceived.addListener( + function(details) { + captureEvent("onHeadersReceived", details); +}); +chrome.experimental.webRequest.onBeforeRedirect.addListener( + function(details) { + captureEvent("onBeforeRedirect", details); +}); +chrome.experimental.webRequest.onCompleted.addListener( + function(details) { + captureEvent("onCompleted", details); +}); +chrome.experimental.webRequest.onErrorOccurred.addListener( + function(details) { + captureEvent("onErrorOccurred", details); +}); + +var getURL = chrome.extension.getURL; +chrome.tabs.getSelected(null, function(tab) { + var tabId = tab.id; + + chrome.test.runTests([ + // Navigates to a blank page. + function simpleLoad() { + expect([ + [ "onBeforeRequest", + { + method: "GET", + url: getURL("simpleLoad/a.html") + } + ], + ]); + chrome.tabs.update(tabId, { url: getURL("simpleLoad/a.html") }); + }, + + // Navigates to a page with subresources. + // TODO(mpcomplete): add multiple subresources; requires support for + // recognizing partial ordering. + function simpleLoad() { + expect([ + [ "onBeforeRequest", + { + method: "GET", + url: getURL("complexLoad/a.html") + } + ], + [ "onBeforeRequest", + { + method: "GET", + url: getURL("complexLoad/b.html") + } + ], + [ "onBeforeRequest", + { + method: "GET", + url: getURL("complexLoad/b.jpg") + } + ], + ]); + chrome.tabs.update(tabId, { url: getURL("complexLoad/a.html") }); + }, + ]); +}); +</script> diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h index eaa77e8..a9244b7 100644 --- a/chrome/test/testing_profile.h +++ b/chrome/test/testing_profile.h @@ -150,6 +150,7 @@ class TestingProfile : public Profile { virtual ExtensionProcessManager* GetExtensionProcessManager() { return NULL; } virtual ExtensionMessageService* GetExtensionMessageService() { return NULL; } virtual ExtensionEventRouter* GetExtensionEventRouter() { return NULL; } + virtual ExtensionIOEventRouter* GetExtensionIOEventRouter() { return NULL; } virtual SSLHostState* GetSSLHostState() { return NULL; } virtual net::TransportSecurityState* GetTransportSecurityState() { return NULL; diff --git a/net/http/http_network_delegate.h b/net/http/http_network_delegate.h index 6b60aba..1533bc3 100644 --- a/net/http/http_network_delegate.h +++ b/net/http/http_network_delegate.h @@ -9,9 +9,13 @@ namespace net { class HttpRequestHeaders; +class URLRequest; class HttpNetworkDelegate { public: + // Called before a request is sent. + virtual void OnBeforeURLRequest(net::URLRequest* request) = 0; + // Called right before the HTTP headers are sent. Allows the delegate to // read/write |headers| before they get sent out. virtual void OnSendHttpRequest(HttpRequestHeaders* headers) = 0; diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 300c9c6..c2d0f4f 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc @@ -13,6 +13,7 @@ #include "net/base/net_log.h" #include "net/base/ssl_cert_request_info.h" #include "net/base/upload_data.h" +#include "net/http/http_network_delegate.h" #include "net/http/http_response_headers.h" #include "net/http/http_util.h" #include "net/url_request/url_request_context.h" @@ -346,6 +347,11 @@ void URLRequest::StartJob(URLRequestJob* job) { DCHECK(!is_pending_); DCHECK(!job_); + // TODO(mpcomplete): pass in request ID? + // TODO(mpcomplete): allow delegate to potentially delay/cancel request. + if (context_ && context_->network_delegate()) + context_->network_delegate()->OnBeforeURLRequest(this); + net_log_.BeginEvent( net::NetLog::TYPE_URL_REQUEST_START_JOB, make_scoped_refptr(new URLRequestStartEventParameters( diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h index 2c737ca..18315dc 100644 --- a/net/url_request/url_request_context.h +++ b/net/url_request/url_request_context.h @@ -115,6 +115,11 @@ class URLRequestContext return ftp_transaction_factory_; } + void set_network_delegate(HttpNetworkDelegate* network_delegate) { + network_delegate_ = network_delegate; + } + HttpNetworkDelegate* network_delegate() { return network_delegate_; } + // Gets the cookie store for this context (may be null, in which case // cookies are not stored). CookieStore* cookie_store() { return cookie_store_.get(); } |