summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-01 21:38:16 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-01 21:38:16 +0000
commitd05ef99c71c3d4db779be737102807cbab88ca45 (patch)
treeb64aa3b5117ecce666372bbc77b6558984194bfa
parent1e1a3ce6a6e266ce93b78fa3c0534aec3db3e2c3 (diff)
downloadchromium_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
-rw-r--r--chrome/browser/extensions/extension_io_event_router.cc39
-rwxr-xr-xchrome/browser/extensions/extension_io_event_router.h40
-rwxr-xr-xchrome/browser/extensions/extension_webrequest_api.cc43
-rwxr-xr-xchrome/browser/extensions/extension_webrequest_api.h35
-rw-r--r--chrome/browser/extensions/extension_webrequest_apitest.cc7
-rw-r--r--chrome/browser/io_thread.cc1
-rw-r--r--chrome/browser/net/chrome_network_delegate.cc21
-rw-r--r--chrome/browser/net/chrome_network_delegate.h5
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc6
-rw-r--r--chrome/browser/net/chrome_url_request_context.h13
-rw-r--r--chrome/browser/profiles/profile.cc4
-rw-r--r--chrome/browser/profiles/profile.h4
-rw-r--r--chrome/browser/profiles/profile_impl.cc11
-rw-r--r--chrome/browser/profiles/profile_impl.h2
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/events/complexLoad/a.html1
-rwxr-xr-xchrome/test/data/extensions/api_test/webrequest/events/complexLoad/b.html1
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/events/complexLoad/b.jpg0
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/events/manifest.json7
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/events/simpleLoad/a.html1
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/events/test.html101
-rw-r--r--chrome/test/testing_profile.h1
-rw-r--r--net/http/http_network_delegate.h4
-rw-r--r--net/url_request/url_request.cc6
-rw-r--r--net/url_request/url_request_context.h5
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(); }