summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-22 23:18:50 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-22 23:18:50 +0000
commitfc4facd5d143da6ccb96619981d12e9b9fc6467c (patch)
tree93cc7217ccde59452946120e03c6532c9f534620 /chrome/browser
parent2862086530e94dab7ab55e842601661aabd8a408 (diff)
downloadchromium_src-fc4facd5d143da6ccb96619981d12e9b9fc6467c.zip
chromium_src-fc4facd5d143da6ccb96619981d12e9b9fc6467c.tar.gz
chromium_src-fc4facd5d143da6ccb96619981d12e9b9fc6467c.tar.bz2
Add tabId, type, and timeStamp parameters to extension webRequest events.
Also added support for filtering based on resource type, tabId, and windowId. BUG=60101 TEST=covered by apitests Review URL: http://codereview.chromium.org/6685010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79066 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_process_impl.cc5
-rwxr-xr-xchrome/browser/extensions/extension_tab_id_map.cc150
-rwxr-xr-xchrome/browser/extensions/extension_tab_id_map.h56
-rw-r--r--chrome/browser/extensions/extension_webrequest_api.cc122
-rw-r--r--chrome/browser/extensions/extension_webrequest_api.h8
5 files changed, 314 insertions, 27 deletions
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 751a42a..06739bc 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -25,6 +25,7 @@
#include "chrome/browser/download/download_file_manager.h"
#include "chrome/browser/download/save_file_manager.h"
#include "chrome/browser/extensions/extension_event_router_forwarder.h"
+#include "chrome/browser/extensions/extension_tab_id_map.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/google/google_url_tracker.h"
#include "chrome/browser/gpu_process_host_ui_shim.h"
@@ -135,6 +136,8 @@ BrowserProcessImpl::BrowserProcessImpl(const CommandLine& command_line)
net_log_.reset(new ChromeNetLog);
extension_event_router_forwarder_ = new ExtensionEventRouterForwarder;
+
+ ExtensionTabIdMap::GetInstance()->Init();
}
BrowserProcessImpl::~BrowserProcessImpl() {
@@ -198,6 +201,8 @@ BrowserProcessImpl::~BrowserProcessImpl() {
resource_dispatcher_host()->Shutdown();
}
+ ExtensionTabIdMap::GetInstance()->Shutdown();
+
// The policy providers managed by |browser_policy_connector_| need to shut
// down while the IO and FILE threads are still alive.
browser_policy_connector_.reset();
diff --git a/chrome/browser/extensions/extension_tab_id_map.cc b/chrome/browser/extensions/extension_tab_id_map.cc
new file mode 100755
index 0000000..ea3dac1
--- /dev/null
+++ b/chrome/browser/extensions/extension_tab_id_map.cc
@@ -0,0 +1,150 @@
+// 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_tab_id_map.h"
+
+#include "content/browser/browser_thread.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/renderer_host/render_process_host.h"
+#include "content/common/notification_registrar.h"
+#include "content/common/notification_observer.h"
+#include "content/common/notification_service.h"
+
+// ExtensionTabIdMap is a Singleton, so it doesn't need refcounting.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(ExtensionTabIdMap);
+
+//
+// ExtensionTabIdMap::TabObserver
+//
+
+// This class listens for notifications about new and closed tabs on the UI
+// thread, and notifies the ExtensionTabIdMap on the IO thread. It should only
+// ever be accessed on the UI thread.
+class ExtensionTabIdMap::TabObserver : public NotificationObserver {
+ public:
+ TabObserver();
+ ~TabObserver();
+
+ private:
+ // NotificationObserver interface.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ NotificationRegistrar registrar_;
+};
+
+ExtensionTabIdMap::TabObserver::TabObserver() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
+ NotificationService::AllSources());
+ registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
+ NotificationService::AllSources());
+ registrar_.Add(this, NotificationType::TAB_PARENTED,
+ NotificationService::AllSources());
+}
+
+ExtensionTabIdMap::TabObserver::~TabObserver() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+void ExtensionTabIdMap::TabObserver::Observe(
+ NotificationType type, const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB: {
+ TabContents* contents = Source<TabContents>(source).ptr();
+ RenderViewHost* host = Details<RenderViewHost>(details).ptr();
+ // TODO(mpcmoplete): How can we tell if window_id is bogus? It may not
+ // have been set yet.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ ExtensionTabIdMap::GetInstance(),
+ &ExtensionTabIdMap::SetTabAndWindowId,
+ host->process()->id(), host->routing_id(),
+ contents->controller().session_id().id(),
+ contents->controller().window_id().id()));
+ break;
+ }
+ case NotificationType::TAB_PARENTED: {
+ NavigationController* controller =
+ Source<NavigationController>(source).ptr();
+ RenderViewHost* host = controller->tab_contents()->render_view_host();
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ ExtensionTabIdMap::GetInstance(),
+ &ExtensionTabIdMap::SetTabAndWindowId,
+ host->process()->id(), host->routing_id(),
+ controller->session_id().id(),
+ controller->window_id().id()));
+ break;
+ }
+ case NotificationType::RENDER_VIEW_HOST_DELETED: {
+ RenderViewHost* host = Details<RenderViewHost>(details).ptr();
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ ExtensionTabIdMap::GetInstance(),
+ &ExtensionTabIdMap::ClearTabAndWindowId,
+ host->process()->id(), host->routing_id()));
+ break;
+ }
+ default:
+ NOTREACHED();
+ return;
+ }
+}
+
+//
+// ExtensionTabIdMap
+//
+
+ExtensionTabIdMap::ExtensionTabIdMap() : observer_(NULL) {
+}
+
+ExtensionTabIdMap::~ExtensionTabIdMap() {
+}
+
+// static
+ExtensionTabIdMap* ExtensionTabIdMap::GetInstance() {
+ return Singleton<ExtensionTabIdMap>::get();
+}
+
+void ExtensionTabIdMap::Init() {
+ observer_ = new TabObserver;
+}
+
+void ExtensionTabIdMap::Shutdown() {
+ delete observer_;
+}
+
+void ExtensionTabIdMap::SetTabAndWindowId(
+ int render_process_host_id, int routing_id, int tab_id, int window_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ RenderId render_id(render_process_host_id, routing_id);
+ map_[render_id] = TabAndWindowId(tab_id, window_id);
+}
+
+void ExtensionTabIdMap::ClearTabAndWindowId(
+ int render_process_host_id, int routing_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ RenderId render_id(render_process_host_id, routing_id);
+ map_.erase(render_id);
+}
+
+bool ExtensionTabIdMap::GetTabAndWindowId(
+ int render_process_host_id, int routing_id, int* tab_id, int* window_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ RenderId render_id(render_process_host_id, routing_id);
+ TabAndWindowIdMap::iterator iter = map_.find(render_id);
+ if (iter != map_.end()) {
+ *tab_id = iter->second.first;
+ *window_id = iter->second.second;
+ return true;
+ }
+ return false;
+}
diff --git a/chrome/browser/extensions/extension_tab_id_map.h b/chrome/browser/extensions/extension_tab_id_map.h
new file mode 100755
index 0000000..1fce693
--- /dev/null
+++ b/chrome/browser/extensions/extension_tab_id_map.h
@@ -0,0 +1,56 @@
+// 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_TAB_ID_MAP_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_TAB_ID_MAP_H_
+#pragma once
+
+#include <map>
+#include <utility>
+
+#include "base/basictypes.h"
+#include "base/singleton.h"
+
+// This class keeps track of a map between renderer IDs and tab/window IDs, for
+// use on the IO thread. All methods should be called on the IO thread except
+// for Init and Shutdown.
+class ExtensionTabIdMap {
+ public:
+ static ExtensionTabIdMap* GetInstance();
+
+ // These are called on the UI thread to start and stop listening to tab
+ // notifications.
+ void Init();
+ void Shutdown();
+
+ // Looks up the tab and window ID for a given render view. Returns true
+ // if we have the IDs in our map. Called on the IO thread.
+ bool GetTabAndWindowId(
+ int render_process_host_id, int routing_id, int* tab_id, int* window_id);
+
+ private:
+ class TabObserver;
+ friend class TabObserver;
+ friend struct DefaultSingletonTraits<ExtensionTabIdMap>;
+
+ typedef std::pair<int, int> RenderId;
+ typedef std::pair<int, int> TabAndWindowId;
+ typedef std::map<RenderId, TabAndWindowId> TabAndWindowIdMap;
+
+ ExtensionTabIdMap();
+ ~ExtensionTabIdMap();
+
+ // Adds or removes a render view from our map.
+ void SetTabAndWindowId(
+ int render_process_host_id, int routing_id, int tab_id, int window_id);
+ void ClearTabAndWindowId(
+ int render_process_host_id, int routing_id);
+
+ TabObserver* observer_;
+ TabAndWindowIdMap map_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionTabIdMap);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_TAB_ID_MAP_H_
diff --git a/chrome/browser/extensions/extension_webrequest_api.cc b/chrome/browser/extensions/extension_webrequest_api.cc
index 46d14c1..56a464d 100644
--- a/chrome/browser/extensions/extension_webrequest_api.cc
+++ b/chrome/browser/extensions/extension_webrequest_api.cc
@@ -11,12 +11,15 @@
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_event_router_forwarder.h"
+#include "chrome/browser/extensions/extension_tab_id_map.h"
#include "chrome/browser/extensions/extension_webrequest_api_constants.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_extent.h"
#include "chrome/common/extensions/url_pattern.h"
#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/resource_dispatcher_host.h"
+#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request.h"
#include "googleurl/src/gurl.h"
@@ -35,8 +38,7 @@ static const char *kWebRequestEvents[] = {
keys::kOnRequestSent
};
-// TODO(mpcomplete): should this be a set of flags?
-static const char* kRequestFilterTypes[] = {
+static const char* kResourceTypeStrings[] = {
"main_frame",
"sub_frame",
"stylesheet",
@@ -46,18 +48,64 @@ static const char* kRequestFilterTypes[] = {
"other",
};
+static ResourceType::Type kResourceTypeValues[] = {
+ ResourceType::MAIN_FRAME,
+ ResourceType::SUB_FRAME,
+ ResourceType::STYLESHEET,
+ ResourceType::SCRIPT,
+ ResourceType::IMAGE,
+ ResourceType::OBJECT,
+ ResourceType::LAST_TYPE, // represents "other"
+};
+
+COMPILE_ASSERT(
+ arraysize(kResourceTypeStrings) == arraysize(kResourceTypeValues),
+ keep_resource_types_in_sync);
+
+#define ARRAYEND(array) (array + arraysize(array))
+
static bool IsWebRequestEvent(const std::string& event_name) {
- return std::find(kWebRequestEvents,
- kWebRequestEvents + arraysize(kWebRequestEvents),
- event_name) !=
- kWebRequestEvents + arraysize(kWebRequestEvents);
+ return std::find(kWebRequestEvents, ARRAYEND(kWebRequestEvents),
+ event_name) != ARRAYEND(kWebRequestEvents);
+}
+
+static const char* ResourceTypeToString(ResourceType::Type type) {
+ ResourceType::Type* iter =
+ std::find(kResourceTypeValues, ARRAYEND(kResourceTypeValues), type);
+ if (iter == ARRAYEND(kResourceTypeValues))
+ return "other";
+
+ return kResourceTypeStrings[iter - kResourceTypeValues];
}
-static bool IsValidRequestFilterType(const std::string& type) {
- return std::find(kRequestFilterTypes,
- kRequestFilterTypes + arraysize(kRequestFilterTypes),
- type) !=
- kRequestFilterTypes + arraysize(kRequestFilterTypes);
+static bool ParseResourceType(const std::string& type_str,
+ ResourceType::Type* type) {
+ const char** iter =
+ std::find(kResourceTypeStrings, ARRAYEND(kResourceTypeStrings), type_str);
+ if (iter == ARRAYEND(kResourceTypeStrings))
+ return false;
+ *type = kResourceTypeValues[iter - kResourceTypeStrings];
+ return true;
+}
+
+static void ExtractRequestInfo(net::URLRequest* request,
+ int* tab_id,
+ int* window_id,
+ ResourceType::Type* resource_type) {
+ if (!request->GetUserData(NULL))
+ return;
+
+ ResourceDispatcherHostRequestInfo* info =
+ ResourceDispatcherHost::InfoForRequest(request);
+ ExtensionTabIdMap::GetInstance()->GetTabAndWindowId(
+ info->child_id(), info->route_id(), tab_id, window_id);
+
+ // Restrict the resource type to the values we care about.
+ ResourceType::Type* iter =
+ std::find(kResourceTypeValues, ARRAYEND(kResourceTypeValues),
+ info->resource_type());
+ *resource_type = (iter != ARRAYEND(kResourceTypeValues)) ?
+ *iter : ResourceType::LAST_TYPE;
}
static void AddEventListenerOnIOThread(
@@ -89,10 +137,11 @@ static void EventHandledOnIOThread(
// filter what network events an extension cares about.
struct ExtensionWebRequestEventRouter::RequestFilter {
ExtensionExtent urls;
- std::vector<std::string> types;
+ std::vector<ResourceType::Type> types;
int tab_id;
int window_id;
+ RequestFilter() : tab_id(-1), window_id(-1) {}
bool InitFromValue(const DictionaryValue& value);
};
@@ -167,12 +216,13 @@ bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue(
}
} else if (*key == "types") {
ListValue* types_value = NULL;
- if (!value.GetList("urls", &types_value))
+ if (!value.GetList("types", &types_value))
return false;
for (size_t i = 0; i < types_value->GetSize(); ++i) {
- std::string type;
- if (!types_value->GetString(i, &type) ||
- !IsValidRequestFilterType(type))
+ std::string type_str;
+ ResourceType::Type type;
+ if (!types_value->GetString(i, &type_str) ||
+ !ParseResourceType(type_str, &type))
return false;
types.push_back(type);
}
@@ -238,21 +288,28 @@ bool ExtensionWebRequestEventRouter::OnBeforeRequest(
// TODO(jochen): Figure out what to do with events from the system context.
if (profile_id == Profile::kInvalidProfileId)
return false;
+
+ int tab_id = -1;
+ int window_id = -1;
+ ResourceType::Type resource_type = ResourceType::LAST_TYPE;
+ ExtractRequestInfo(request, &tab_id, &window_id, &resource_type);
+
std::vector<const EventListener*> listeners =
- GetMatchingListeners(profile_id, keys::kOnBeforeRequest, request->url());
+ GetMatchingListeners(profile_id, keys::kOnBeforeRequest, request->url(),
+ tab_id, window_id, resource_type);
if (listeners.empty())
return false;
ListValue args;
DictionaryValue* dict = new DictionaryValue();
- dict->SetString(keys::kUrlKey, request->url().spec());
- dict->SetString(keys::kMethodKey, request->method());
- // TODO(mpcomplete): implement
- dict->SetInteger(keys::kTabIdKey, 0);
dict->SetString(keys::kRequestIdKey,
base::Uint64ToString(request->identifier()));
- dict->SetString(keys::kTypeKey, "main_frame");
- dict->SetInteger(keys::kTimeStampKey, 1);
+ dict->SetString(keys::kUrlKey, request->url().spec());
+ dict->SetString(keys::kMethodKey, request->method());
+ dict->SetInteger(keys::kTabIdKey, tab_id);
+ dict->SetString(keys::kTypeKey, ResourceTypeToString(resource_type));
+ dict->SetDouble(keys::kTimeStampKey,
+ request->request_time().ToDoubleT() * 1000);
args.Append(dict);
std::string json_args;
@@ -361,15 +418,28 @@ std::vector<const ExtensionWebRequestEventRouter::EventListener*>
ExtensionWebRequestEventRouter::GetMatchingListeners(
ProfileId profile_id,
const std::string& event_name,
- const GURL& url) {
+ const GURL& url,
+ int tab_id,
+ int window_id,
+ ResourceType::Type resource_type) {
// TODO(mpcomplete): handle profile_id == invalid (should collect all
// listeners).
std::vector<const EventListener*> matching_listeners;
std::set<EventListener>& listeners = listeners_[profile_id][event_name];
for (std::set<EventListener>::iterator it = listeners.begin();
it != listeners.end(); ++it) {
- if (it->filter.urls.is_empty() || it->filter.urls.ContainsURL(url))
- matching_listeners.push_back(&(*it));
+ if (!it->filter.urls.is_empty() && !it->filter.urls.ContainsURL(url))
+ continue;
+ if (it->filter.tab_id != -1 && tab_id != it->filter.tab_id)
+ continue;
+ if (it->filter.window_id != -1 && window_id != it->filter.window_id)
+ continue;
+ if (!it->filter.types.empty() &&
+ std::find(it->filter.types.begin(), it->filter.types.end(),
+ resource_type) == it->filter.types.end())
+ continue;
+
+ matching_listeners.push_back(&(*it));
}
return matching_listeners;
}
diff --git a/chrome/browser/extensions/extension_webrequest_api.h b/chrome/browser/extensions/extension_webrequest_api.h
index 0cd52a3..5d64fdc 100644
--- a/chrome/browser/extensions/extension_webrequest_api.h
+++ b/chrome/browser/extensions/extension_webrequest_api.h
@@ -16,6 +16,7 @@
#include "chrome/browser/profiles/profile.h"
#include "ipc/ipc_message.h"
#include "net/base/completion_callback.h"
+#include "webkit/glue/resource_type.h"
class ExtensionEventRouterForwarder;
class GURL;
@@ -83,7 +84,12 @@ class ExtensionWebRequestEventRouter {
// Returns a list of event listeners that care about the given event, based
// on their filter parameters.
std::vector<const EventListener*> GetMatchingListeners(
- ProfileId profile_id, const std::string& event_name, const GURL& url);
+ ProfileId profile_id,
+ const std::string& event_name,
+ const GURL& url,
+ int tab_id,
+ int window_id,
+ ResourceType::Type resource_type);
// Decrements the count of event handlers blocking the given request. When the
// count reaches 0 (or immediately if the request is being cancelled), we