summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/api/messaging/message_service.cc137
-rw-r--r--chrome/browser/extensions/api/messaging/message_service.h13
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api_unittest.cc73
-rw-r--r--extensions/browser/api/web_request/web_request_api.cc93
-rw-r--r--extensions/browser/api/web_request/web_request_api.h22
-rw-r--r--extensions/browser/event_router.cc96
-rw-r--r--extensions/browser/event_router.h47
-rw-r--r--extensions/browser/extension_event_histogram_value.h35
-rw-r--r--extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc23
-rw-r--r--extensions/browser/guest_view/guest_view_events.cc102
-rw-r--r--extensions/browser/guest_view/guest_view_events.h23
-rw-r--r--extensions/browser/guest_view/web_view/web_view_constants.cc5
-rw-r--r--extensions/browser/guest_view/web_view/web_view_constants.h5
-rw-r--r--extensions/extensions.gypi2
-rw-r--r--extensions/renderer/resources/extension_custom_bindings.js2
-rw-r--r--tools/metrics/histograms/histograms.xml31
16 files changed, 554 insertions, 155 deletions
diff --git a/chrome/browser/extensions/api/messaging/message_service.cc b/chrome/browser/extensions/api/messaging/message_service.cc
index b5ef18d..36e1e32 100644
--- a/chrome/browser/extensions/api/messaging/message_service.cc
+++ b/chrome/browser/extensions/api/messaging/message_service.cc
@@ -23,6 +23,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "components/guest_view/common/guest_view_constants.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -51,6 +52,7 @@
#include "url/gurl.h"
using content::BrowserContext;
+using content::BrowserThread;
using content::SiteInstance;
using content::WebContents;
@@ -71,6 +73,8 @@ namespace extensions {
MessageService::PolicyPermission MessageService::IsNativeMessagingHostAllowed(
const PrefService* pref_service,
const std::string& native_host_name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
PolicyPermission allow_result = ALLOW_ALL;
if (pref_service->IsManagedPreference(
pref_names::kNativeMessagingUserLevelHosts)) {
@@ -190,6 +194,8 @@ content::RenderProcessHost*
// static
void MessageService::AllocatePortIdPair(int* port1, int* port2) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
unsigned channel_id =
static_cast<unsigned>(g_next_channel_id.GetNext()) % (kint32max/2);
unsigned port1_id = channel_id * 2;
@@ -212,6 +218,8 @@ MessageService::MessageService(BrowserContext* context)
: lazy_background_task_queue_(
LazyBackgroundTaskQueue::Get(context)),
weak_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
content::NotificationService::AllBrowserContextsAndSources());
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
@@ -219,6 +227,8 @@ MessageService::MessageService(BrowserContext* context)
}
MessageService::~MessageService() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end());
channels_.clear();
}
@@ -244,6 +254,8 @@ void MessageService::OpenChannelToExtension(
const GURL& source_url,
const std::string& channel_name,
bool include_tls_channel_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
content::RenderProcessHost* source =
content::RenderProcessHost::FromID(source_process_id);
if (!source)
@@ -399,6 +411,8 @@ void MessageService::OpenChannelToNativeApp(
int receiver_port_id,
const std::string& source_extension_id,
const std::string& native_app_name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
content::RenderProcessHost* source =
content::RenderProcessHost::FromID(source_process_id);
if (!source)
@@ -477,6 +491,8 @@ void MessageService::OpenChannelToTab(int source_process_id,
int frame_id,
const std::string& extension_id,
const std::string& channel_name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
content::RenderProcessHost* source =
content::RenderProcessHost::FromID(source_process_id);
if (!source)
@@ -516,8 +532,17 @@ void MessageService::OpenChannelToTab(int source_process_id,
// frame's process can also receive the port.
receiver_routing_id = MSG_ROUTING_CONTROL;
}
- receiver.reset(new ExtensionMessagePort(
- contents->GetRenderProcessHost(), receiver_routing_id, extension_id));
+ receiver.reset(new ExtensionMessagePort(contents->GetRenderProcessHost(),
+ receiver_routing_id, extension_id));
+
+ const Extension* extension = nullptr;
+ if (!extension_id.empty()) {
+ // Source extension == target extension so the extension must exist, or
+ // where did the IPC come from?
+ extension = ExtensionRegistry::Get(profile)->enabled_extensions().GetByID(
+ extension_id);
+ DCHECK(extension);
+ }
scoped_ptr<OpenChannelParams> params(new OpenChannelParams(
source_process_id,
@@ -530,10 +555,17 @@ void MessageService::OpenChannelToTab(int source_process_id,
channel_name,
false, // Connections to tabs don't get TLS channel IDs.
false)); // Connections to tabs aren't webview guests.
- OpenChannelImpl(params.Pass());
+ OpenChannelImpl(contents->GetBrowserContext(), params.Pass(), extension,
+ false /* did_enqueue */);
}
-void MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) {
+void MessageService::OpenChannelImpl(BrowserContext* browser_context,
+ scoped_ptr<OpenChannelParams> params,
+ const Extension* target_extension,
+ bool did_enqueue) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_EQ(target_extension != nullptr, !params->target_extension_id.empty());
+
content::RenderProcessHost* source =
content::RenderProcessHost::FromID(params->source_process_id);
if (!source)
@@ -545,21 +577,12 @@ void MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) {
return;
}
- // Add extra paranoid CHECKs, since we have crash reports of this being NULL.
- // http://code.google.com/p/chromium/issues/detail?id=19067
- CHECK(params->receiver->GetRenderProcessHost());
-
MessageChannel* channel(new MessageChannel);
channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL,
params->source_extension_id));
channel->receiver.reset(params->receiver.release());
-
- CHECK(channel->receiver->GetRenderProcessHost());
-
AddChannel(channel, params->receiver_port_id);
- CHECK(channel->receiver->GetRenderProcessHost());
-
int guest_process_id = content::ChildProcessHost::kInvalidUniqueID;
int guest_render_frame_routing_id = MSG_ROUTING_NONE;
if (params->include_guest_process_info) {
@@ -577,17 +600,42 @@ void MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) {
// Send the connect event to the receiver. Give it the opener's port ID (the
// opener has the opposite port ID).
- channel->receiver->DispatchOnConnect(params->receiver_port_id,
- params->channel_name,
- params->source_tab.Pass(),
- params->source_frame_id,
- params->target_frame_id,
- guest_process_id,
- guest_render_frame_routing_id,
- params->source_extension_id,
- params->target_extension_id,
- params->source_url,
- params->tls_channel_id);
+ channel->receiver->DispatchOnConnect(
+ params->receiver_port_id, params->channel_name, params->source_tab.Pass(),
+ params->source_frame_id, params->target_frame_id, guest_process_id,
+ guest_render_frame_routing_id, params->source_extension_id,
+ params->target_extension_id, params->source_url, params->tls_channel_id);
+
+ // Report the event to the event router, if the target is an extension.
+ //
+ // First, determine what event this will be (runtime.onConnect vs
+ // runtime.onMessage etc), and what the event target is (view vs background
+ // page etc).
+ //
+ // Yes - even though this is opening a channel, they may actually be
+ // runtime.onRequest/onMessage events because those single-use events are
+ // built using the connect framework (see messaging.js).
+ //
+ // Likewise, if you're wondering about native messaging events, these are
+ // only initiated *by* the extension, so aren't really events, just the
+ // endpoint of a communication channel.
+ if (target_extension) {
+ events::HistogramValue histogram_value = events::UNKNOWN;
+ bool is_external =
+ params->source_extension_id != params->target_extension_id;
+ if (params->channel_name == "chrome.runtime.onRequest") {
+ histogram_value = is_external ? events::RUNTIME_ON_REQUEST_EXTERNAL
+ : events::RUNTIME_ON_REQUEST;
+ } else if (params->channel_name == "chrome.runtime.onMessage") {
+ histogram_value = is_external ? events::RUNTIME_ON_MESSAGE_EXTERNAL
+ : events::RUNTIME_ON_MESSAGE;
+ } else {
+ histogram_value = is_external ? events::RUNTIME_ON_CONNECT_EXTERNAL
+ : events::RUNTIME_ON_CONNECT;
+ }
+ EventRouter::Get(browser_context)
+ ->ReportEvent(histogram_value, target_extension, did_enqueue);
+ }
// Keep both ends of the channel alive until the channel is closed.
channel->opener->IncrementLazyKeepaliveCount();
@@ -595,6 +643,8 @@ void MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) {
}
void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
int channel_id = GET_CHANNEL_ID(receiver_port_id);
CHECK(channels_.find(channel_id) == channels_.end());
channels_[channel_id] = channel;
@@ -603,6 +653,8 @@ void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) {
void MessageService::CloseChannel(int port_id,
const std::string& error_message) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
// Note: The channel might be gone already, if the other side closed first.
int channel_id = GET_CHANNEL_ID(port_id);
MessageChannelMap::iterator it = channels_.find(channel_id);
@@ -625,6 +677,8 @@ void MessageService::CloseChannelImpl(
int closing_port_id,
const std::string& error_message,
bool notify_other_port) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
MessageChannel* channel = channel_iter->second;
// Notify the other side.
@@ -644,6 +698,8 @@ void MessageService::CloseChannelImpl(
}
void MessageService::PostMessage(int source_port_id, const Message& message) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
int channel_id = GET_CHANNEL_ID(source_port_id);
MessageChannelMap::iterator iter = channels_.find(channel_id);
if (iter == channels_.end()) {
@@ -659,6 +715,8 @@ void MessageService::PostMessage(int source_port_id, const Message& message) {
void MessageService::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
switch (type) {
case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
@@ -674,8 +732,10 @@ void MessageService::Observe(int type,
}
void MessageService::OnProcessClosed(content::RenderProcessHost* process) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
// Close any channels that share this renderer. We notify the opposite
- // port that his pair has closed.
+ // port that its pair has closed.
for (MessageChannelMap::iterator it = channels_.begin();
it != channels_.end(); ) {
MessageChannelMap::iterator current = it++;
@@ -702,6 +762,8 @@ void MessageService::OnProcessClosed(content::RenderProcessHost* process) {
void MessageService::EnqueuePendingMessage(int source_port_id,
int channel_id,
const Message& message) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
PendingChannelMap::iterator pending_for_incognito =
pending_incognito_channels_.find(channel_id);
if (pending_for_incognito != pending_incognito_channels_.end()) {
@@ -732,6 +794,8 @@ void MessageService::EnqueuePendingMessageForLazyBackgroundLoad(
int source_port_id,
int channel_id,
const Message& message) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
PendingLazyBackgroundPageChannelMap::iterator pending =
pending_lazy_background_page_channels_.find(channel_id);
if (pending != pending_lazy_background_page_channels_.end()) {
@@ -745,6 +809,8 @@ void MessageService::EnqueuePendingMessageForLazyBackgroundLoad(
void MessageService::DispatchMessage(int source_port_id,
MessageChannel* channel,
const Message& message) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
// Figure out which port the ID corresponds to.
int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id);
MessagePort* port = IS_OPENER_PORT_ID(dest_port_id) ?
@@ -758,6 +824,8 @@ bool MessageService::MaybeAddPendingLazyBackgroundPageOpenChannelTask(
const Extension* extension,
scoped_ptr<OpenChannelParams>* params,
const PendingMessagesQueue& pending_messages) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
if (!BackgroundInfo::HasLazyBackgroundPage(extension))
return false;
@@ -788,6 +856,8 @@ bool MessageService::MaybeAddPendingLazyBackgroundPageOpenChannelTask(
void MessageService::OnOpenChannelAllowed(scoped_ptr<OpenChannelParams> params,
bool allowed) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
int channel_id = GET_CHANNEL_ID(params->receiver_port_id);
PendingChannelMap::iterator pending_for_incognito =
@@ -852,13 +922,16 @@ void MessageService::OnOpenChannelAllowed(scoped_ptr<OpenChannelParams> params,
// page.
if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask(
context, target_extension, &params, pending_messages)) {
- OpenChannelImpl(params.Pass());
+ OpenChannelImpl(context, params.Pass(), target_extension,
+ false /* did_enqueue */);
DispatchPendingMessages(pending_messages, channel_id);
}
}
void MessageService::GotChannelID(scoped_ptr<OpenChannelParams> params,
const std::string& tls_channel_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
params->tls_channel_id.assign(tls_channel_id);
int channel_id = GET_CHANNEL_ID(params->receiver_port_id);
@@ -891,7 +964,8 @@ void MessageService::GotChannelID(scoped_ptr<OpenChannelParams> params,
if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask(
context, target_extension, &params, pending_messages)) {
- OpenChannelImpl(params.Pass());
+ OpenChannelImpl(context, params.Pass(), target_extension,
+ false /* did_enqueue */);
DispatchPendingMessages(pending_messages, channel_id);
}
}
@@ -900,24 +974,31 @@ void MessageService::PendingLazyBackgroundPageOpenChannel(
scoped_ptr<OpenChannelParams> params,
int source_process_id,
ExtensionHost* host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
if (!host)
return; // TODO(mpcomplete): notify source of disconnect?
params->receiver.reset(new ExtensionMessagePort(host->render_process_host(),
MSG_ROUTING_CONTROL,
params->target_extension_id));
- OpenChannelImpl(params.Pass());
+ OpenChannelImpl(host->browser_context(), params.Pass(), host->extension(),
+ true /* did_enqueue */);
}
void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source,
int port_id,
const std::string& error_message) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, "");
port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message);
}
void MessageService::DispatchPendingMessages(const PendingMessagesQueue& queue,
int channel_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
MessageChannelMap::iterator channel_iter = channels_.find(channel_id);
if (channel_iter != channels_.end()) {
for (const PendingMessage& message : queue) {
diff --git a/chrome/browser/extensions/api/messaging/message_service.h b/chrome/browser/extensions/api/messaging/message_service.h
index e68b19e..9d209b2 100644
--- a/chrome/browser/extensions/api/messaging/message_service.h
+++ b/chrome/browser/extensions/api/messaging/message_service.h
@@ -186,8 +186,17 @@ class MessageService : public BrowserContextKeyedAPI,
typedef std::map<int, PendingLazyBackgroundPageChannel>
PendingLazyBackgroundPageChannelMap;
- // Common among OpenChannel* variants.
- void OpenChannelImpl(scoped_ptr<OpenChannelParams> params);
+ // Common implementation for opening a channel configured by |params|.
+ //
+ // |target_extension| will be non-null if |params->target_extension_id| is
+ // non-empty, that is, if the target is an extension, it must exist.
+ //
+ // |did_enqueue| will be true if the channel opening was delayed while
+ // waiting for an event page to start, false otherwise.
+ void OpenChannelImpl(content::BrowserContext* browser_context,
+ scoped_ptr<OpenChannelParams> params,
+ const Extension* target_extension,
+ bool did_enqueue);
void CloseChannelImpl(MessageChannelMap::iterator channel_iter,
int port_id,
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
index b239c63..97c39d0 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -227,12 +227,14 @@ TEST_F(ExtensionWebRequestTest, BlockingEventPrecedenceRedirect) {
const std::string kEventName(web_request::OnBeforeRequest::kEventName);
base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_);
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension1_id, extension1_id, kEventName, kEventName + "/1",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
+ &profile_, extension1_id, extension1_id, events::FOR_TEST, kEventName,
+ kEventName + "/1", filter,
+ ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
ipc_sender_factory.GetWeakPtr());
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension2_id, extension2_id, kEventName, kEventName + "/2",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
+ &profile_, extension2_id, extension2_id, events::FOR_TEST, kEventName,
+ kEventName + "/2", filter,
+ ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
ipc_sender_factory.GetWeakPtr());
net::URLRequestJobFactoryImpl job_factory;
@@ -363,13 +365,15 @@ TEST_F(ExtensionWebRequestTest, BlockingEventPrecedenceCancel) {
const std::string kEventName(web_request::OnBeforeRequest::kEventName);
base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_);
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension1_id, extension1_id, kEventName, kEventName + "/1",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
- ipc_sender_factory.GetWeakPtr());
+ &profile_, extension1_id, extension1_id, events::FOR_TEST, kEventName,
+ kEventName + "/1", filter,
+ ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
+ ipc_sender_factory.GetWeakPtr());
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension2_id, extension2_id, kEventName, kEventName + "/2",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
- ipc_sender_factory.GetWeakPtr());
+ &profile_, extension2_id, extension2_id, events::FOR_TEST, kEventName,
+ kEventName + "/2", filter,
+ ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
+ ipc_sender_factory.GetWeakPtr());
GURL request_url("about:blank");
scoped_ptr<net::URLRequest> request(context_->CreateRequest(
@@ -432,12 +436,13 @@ TEST_F(ExtensionWebRequestTest, SimulateChancelWhileBlocked) {
const std::string kEventName2(web_request::OnErrorOccurred::kEventName);
base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_);
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
- ipc_sender_factory.GetWeakPtr());
+ &profile_, extension_id, extension_id, events::FOR_TEST, kEventName,
+ kEventName + "/1", filter,
+ ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
+ ipc_sender_factory.GetWeakPtr());
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension_id, extension_id, kEventName2, kEventName2 + "/1",
- filter, 0, 0, 0, ipc_sender_factory.GetWeakPtr());
+ &profile_, extension_id, extension_id, events::FOR_TEST, kEventName2,
+ kEventName2 + "/1", filter, 0, 0, 0, ipc_sender_factory.GetWeakPtr());
GURL request_url("about:blank");
scoped_ptr<net::URLRequest> request(context_->CreateRequest(
@@ -632,8 +637,9 @@ TEST_F(ExtensionWebRequestTest, AccessRequestBodyData) {
// Subscribe to OnBeforeRequest with requestBody requirement.
ASSERT_TRUE(GenerateInfoSpec(string_spec_post, &extra_info_spec_body));
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, extra_info_spec_body, 0, 0, ipc_sender_factory.GetWeakPtr());
+ &profile_, extension_id, extension_id, events::FOR_TEST, kEventName,
+ kEventName + "/1", filter, extra_info_spec_body, 0, 0,
+ ipc_sender_factory.GetWeakPtr());
FireURLRequestWithData(kMethodPost, kMultipart, form_1, form_2);
@@ -648,8 +654,9 @@ TEST_F(ExtensionWebRequestTest, AccessRequestBodyData) {
ASSERT_TRUE(
GenerateInfoSpec(string_spec_no_post, &extra_info_spec_empty));
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, extra_info_spec_empty, 0, 0, ipc_sender_factory.GetWeakPtr());
+ &profile_, extension_id, extension_id, events::FOR_TEST, kEventName,
+ kEventName + "/1", filter, extra_info_spec_empty, 0, 0,
+ ipc_sender_factory.GetWeakPtr());
FireURLRequestWithData(kMethodPost, kMultipart, form_1, form_2);
@@ -658,8 +665,9 @@ TEST_F(ExtensionWebRequestTest, AccessRequestBodyData) {
// Subscribe to OnBeforeRequest with requestBody requirement.
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, extra_info_spec_body, 0, 0, ipc_sender_factory.GetWeakPtr());
+ &profile_, extension_id, extension_id, events::FOR_TEST, kEventName,
+ kEventName + "/1", filter, extra_info_spec_body, 0, 0,
+ ipc_sender_factory.GetWeakPtr());
// Part 3.
// Now send a POST request with body which is not parseable as a form.
@@ -716,8 +724,9 @@ TEST_F(ExtensionWebRequestTest, NoAccessRequestBodyData) {
// Subscribe to OnBeforeRequest with requestBody requirement.
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension_id, extension_id, kEventName, kEventName + "/1",
- filter, extra_info_spec, 0, 0, ipc_sender_factory.GetWeakPtr());
+ &profile_, extension_id, extension_id, events::FOR_TEST, kEventName,
+ kEventName + "/1", filter, extra_info_spec, 0, 0,
+ ipc_sender_factory.GetWeakPtr());
// The request URL can be arbitrary but must have an HTTP or HTTPS scheme.
const GURL request_url("http://www.example.com");
@@ -828,20 +837,22 @@ TEST_P(ExtensionWebRequestHeaderModificationTest, TestModifications) {
// Install two extensions that can modify headers. Extension 2 has
// higher precedence than extension 1.
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension1_id, extension1_id, kEventName, kEventName + "/1",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
+ &profile_, extension1_id, extension1_id, events::FOR_TEST, kEventName,
+ kEventName + "/1", filter,
+ ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
ipc_sender_factory.GetWeakPtr());
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension2_id, extension2_id, kEventName, kEventName + "/2",
- filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
+ &profile_, extension2_id, extension2_id, events::FOR_TEST, kEventName,
+ kEventName + "/2", filter,
+ ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0,
ipc_sender_factory.GetWeakPtr());
// Install one extension that observes the final headers.
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
- &profile_, extension3_id, extension3_id, keys::kOnSendHeadersEvent,
- std::string(keys::kOnSendHeadersEvent) + "/3", filter,
- ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS, 0, 0,
- ipc_sender_factory.GetWeakPtr());
+ &profile_, extension3_id, extension3_id, events::FOR_TEST,
+ keys::kOnSendHeadersEvent, std::string(keys::kOnSendHeadersEvent) + "/3",
+ filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS, 0,
+ 0, ipc_sender_factory.GetWeakPtr());
GURL request_url("http://doesnotexist/does_not_exist.html");
scoped_ptr<net::URLRequest> request(context_->CreateRequest(
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index 04a2bed..6af3476 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
+#include "base/macros.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -38,6 +39,7 @@
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extensions_browser_client.h"
+#include "extensions/browser/guest_view/guest_view_events.h"
#include "extensions/browser/guest_view/web_view/web_view_constants.h"
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
#include "extensions/browser/info_map.h"
@@ -96,8 +98,6 @@ const char* const kWebRequestEvents[] = {
keys::kOnHeadersReceivedEvent,
};
-const size_t kWebRequestEventsLength = arraysize(kWebRequestEvents);
-
const char* GetRequestStageAsString(
ExtensionWebRequestEventRouter::EventTypes type) {
switch (type) {
@@ -138,10 +138,10 @@ bool IsWebRequestEvent(const std::string& event_name) {
web_request_event_name.replace(
0, strlen(webview::kWebViewEventPrefix), kWebRequestEventPrefix);
}
- return std::find(
- kWebRequestEvents,
- kWebRequestEvents + kWebRequestEventsLength,
- web_request_event_name) != (kWebRequestEvents + kWebRequestEventsLength);
+ auto web_request_events_end =
+ kWebRequestEvents + arraysize(kWebRequestEvents);
+ return std::find(kWebRequestEvents, web_request_events_end,
+ web_request_event_name) != web_request_events_end;
}
// Returns whether |request| has been triggered by an extension in
@@ -372,6 +372,44 @@ void RemoveEventListenerOnIOThread(
embedder_process_id, web_view_instance_id);
}
+events::HistogramValue GetEventHistogramValue(const std::string& event_name) {
+ // Event names will either be webRequest events, or guest view (probably web
+ // view) events that map to webRequest events. Check webRequest first.
+ static struct ValueAndName {
+ events::HistogramValue histogram_value;
+ const char* event_name;
+ } values_and_names[] = {
+ {events::WEB_REQUEST_ON_BEFORE_REDIRECT, keys::kOnBeforeRedirectEvent},
+ {events::WEB_REQUEST_ON_BEFORE_REQUEST,
+ web_request::OnBeforeRequest::kEventName},
+ {events::WEB_REQUEST_ON_BEFORE_SEND_HEADERS,
+ keys::kOnBeforeSendHeadersEvent},
+ {events::WEB_REQUEST_ON_COMPLETED, keys::kOnCompletedEvent},
+ {events::WEB_REQUEST_ON_ERROR_OCCURRED,
+ web_request::OnErrorOccurred::kEventName},
+ {events::WEB_REQUEST_ON_SEND_HEADERS, keys::kOnSendHeadersEvent},
+ {events::WEB_REQUEST_ON_AUTH_REQUIRED, keys::kOnAuthRequiredEvent},
+ {events::WEB_REQUEST_ON_RESPONSE_STARTED, keys::kOnResponseStartedEvent},
+ {events::WEB_REQUEST_ON_HEADERS_RECEIVED, keys::kOnHeadersReceivedEvent}};
+ COMPILE_ASSERT(arraysize(kWebRequestEvents) == arraysize(values_and_names),
+ "kWebRequestEvents and values_and_names must be the same");
+ for (const ValueAndName& value_and_name : values_and_names) {
+ if (value_and_name.event_name == event_name)
+ return value_and_name.histogram_value;
+ }
+
+ // If there is no webRequest event, it might be a guest view webRequest event.
+ events::HistogramValue guest_view_histogram_value =
+ guest_view_events::GetEventHistogramValue(event_name);
+ if (guest_view_histogram_value != events::UNKNOWN)
+ return guest_view_histogram_value;
+
+ // There is no histogram value for this event name. It should be added to
+ // either the mapping here, or in guest_view_events.
+ NOTREACHED() << "Event " << event_name << " must have a histogram value";
+ return events::UNKNOWN;
+};
+
} // namespace
WebRequestAPI::WebRequestAPI(content::BrowserContext* context)
@@ -429,6 +467,7 @@ void WebRequestAPI::OnListenerRemoved(const EventListenerInfo& details) {
struct ExtensionWebRequestEventRouter::EventListener {
std::string extension_id;
std::string extension_name;
+ events::HistogramValue histogram_value;
std::string sub_event_name;
RequestFilter filter;
int extra_info_spec;
@@ -463,10 +502,11 @@ struct ExtensionWebRequestEventRouter::EventListener {
return false;
}
- EventListener() :
- extra_info_spec(0),
- embedder_process_id(0),
- web_view_instance_id(0) {}
+ EventListener()
+ : histogram_value(events::UNKNOWN),
+ extra_info_spec(0),
+ embedder_process_id(0),
+ web_view_instance_id(0) {}
};
// Contains info about requests that are blocked waiting for a response from
@@ -1194,30 +1234,30 @@ bool ExtensionWebRequestEventRouter::DispatchEvent(
// TODO(mpcomplete): Consider consolidating common (extension_id,json_args)
// pairs into a single message sent to a list of sub_event_names.
int num_handlers_blocking = 0;
- for (std::vector<const EventListener*>::const_iterator it = listeners.begin();
- it != listeners.end(); ++it) {
+ for (const EventListener* listener : listeners) {
// Filter out the optional keys that this listener didn't request.
scoped_ptr<base::ListValue> args_filtered(args.DeepCopy());
base::DictionaryValue* dict = NULL;
CHECK(args_filtered->GetDictionary(0, &dict) && dict);
- if (!((*it)->extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS))
+ if (!(listener->extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS))
dict->Remove(keys::kRequestHeadersKey, NULL);
- if (!((*it)->extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS))
+ if (!(listener->extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS))
dict->Remove(keys::kResponseHeadersKey, NULL);
- EventRouter::DispatchEvent(
- (*it)->ipc_sender.get(), browser_context, (*it)->extension_id,
- (*it)->sub_event_name, args_filtered.Pass(),
- EventRouter::USER_GESTURE_UNKNOWN, EventFilteringInfo());
- if ((*it)->extra_info_spec &
+ EventRouter::DispatchEventToSender(
+ listener->ipc_sender.get(), browser_context, listener->extension_id,
+ listener->histogram_value, listener->sub_event_name,
+ args_filtered.Pass(), EventRouter::USER_GESTURE_UNKNOWN,
+ EventFilteringInfo());
+ if (listener->extra_info_spec &
(ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) {
- (*it)->blocked_requests.insert(request->identifier());
+ listener->blocked_requests.insert(request->identifier());
// If this is the first delegate blocking the request, go ahead and log
// it.
if (num_handlers_blocking == 0) {
- std::string delegate_info =
- l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION,
- base::UTF8ToUTF16((*it)->extension_name));
+ std::string delegate_info = l10n_util::GetStringFUTF8(
+ IDS_LOAD_STATE_PARAMETER_EXTENSION,
+ base::UTF8ToUTF16(listener->extension_name));
// LobAndReport allows extensions that block requests to be displayed in
// the load status bar.
request->LogAndReportBlockedBy(delegate_info.c_str());
@@ -1268,6 +1308,7 @@ bool ExtensionWebRequestEventRouter::AddEventListener(
void* browser_context,
const std::string& extension_id,
const std::string& extension_name,
+ events::HistogramValue histogram_value,
const std::string& event_name,
const std::string& sub_event_name,
const RequestFilter& filter,
@@ -1281,6 +1322,7 @@ bool ExtensionWebRequestEventRouter::AddEventListener(
EventListener listener;
listener.extension_id = extension_id;
listener.extension_name = extension_name;
+ listener.histogram_value = histogram_value;
listener.sub_event_name = sub_event_name;
listener.filter = filter;
listener.extra_info_spec = extra_info_spec;
@@ -2244,8 +2286,9 @@ bool WebRequestInternalAddEventListenerFunction::RunSync() {
bool success =
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
profile_id(), extension_id_safe(), extension_name,
- event_name, sub_event_name, filter, extra_info_spec,
- embedder_process_id, web_view_instance_id, ipc_sender_weak());
+ GetEventHistogramValue(event_name), event_name, sub_event_name,
+ filter, extra_info_spec, embedder_process_id, web_view_instance_id,
+ ipc_sender_weak());
EXTENSION_FUNCTION_VALIDATE(success);
helpers::ClearCacheOnNavigation();
diff --git a/extensions/browser/api/web_request/web_request_api.h b/extensions/browser/api/web_request/web_request_api.h
index 49bed01..06ffbff 100644
--- a/extensions/browser/api/web_request/web_request_api.h
+++ b/extensions/browser/api/web_request/web_request_api.h
@@ -271,17 +271,17 @@ class ExtensionWebRequestEventRouter
// listened to. |sub_event_name| is an internal event uniquely generated in
// the extension process to correspond to the given filter and
// extra_info_spec. It returns true on success, false on failure.
- bool AddEventListener(
- void* browser_context,
- const std::string& extension_id,
- const std::string& extension_name,
- const std::string& event_name,
- const std::string& sub_event_name,
- const RequestFilter& filter,
- int extra_info_spec,
- int embedder_process_id,
- int web_view_instance_id,
- base::WeakPtr<IPC::Sender> ipc_sender);
+ bool AddEventListener(void* browser_context,
+ const std::string& extension_id,
+ const std::string& extension_name,
+ events::HistogramValue histogram_value,
+ const std::string& event_name,
+ const std::string& sub_event_name,
+ const RequestFilter& filter,
+ int extra_info_spec,
+ int embedder_process_id,
+ int web_view_instance_id,
+ base::WeakPtr<IPC::Sender> ipc_sender);
// Removes the listener for the given sub-event.
void RemoveEventListener(
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index e70d02b..c483f45 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -26,6 +26,7 @@
#include "extensions/browser/notification_types.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_map.h"
+#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_api.h"
#include "extensions/common/extension_messages.h"
@@ -147,25 +148,28 @@ std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
}
// static
-void EventRouter::DispatchEvent(IPC::Sender* ipc_sender,
- void* browser_context_id,
- const std::string& extension_id,
- const std::string& event_name,
- scoped_ptr<ListValue> event_args,
- UserGestureState user_gesture,
- const EventFilteringInfo& info) {
+void EventRouter::DispatchEventToSender(IPC::Sender* ipc_sender,
+ void* browser_context_id,
+ const std::string& extension_id,
+ events::HistogramValue histogram_value,
+ const std::string& event_name,
+ scoped_ptr<ListValue> event_args,
+ UserGestureState user_gesture,
+ const EventFilteringInfo& info) {
int event_id = g_extension_event_id.GetNext();
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ DoDispatchEventToSenderBookkeepingOnUI(browser_context_id, extension_id,
+ event_id, histogram_value,
+ event_name);
+ } else {
// This is called from WebRequest API.
// TODO(lazyboy): Skip this entirely: http://crbug.com/488747.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&EventRouter::IncrementInFlightEventsOnUI,
- browser_context_id, extension_id, event_id, event_name));
- } else {
- IncrementInFlightEventsOnUI(browser_context_id, extension_id, event_id,
- event_name);
+ base::Bind(&EventRouter::DoDispatchEventToSenderBookkeepingOnUI,
+ browser_context_id, extension_id, event_id, histogram_value,
+ event_name));
}
DispatchExtensionMessage(ipc_sender, browser_context_id, extension_id,
@@ -500,9 +504,7 @@ void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
// background page, and as that event needs to be delivered before we dispatch
// the event we are dispatching here, we dispatch to the lazy listeners here
// first.
- for (std::set<const EventListener*>::iterator it = listeners.begin();
- it != listeners.end(); it++) {
- const EventListener* listener = *it;
+ for (const EventListener* listener : listeners) {
if (restrict_to_extension_id.empty() ||
restrict_to_extension_id == listener->extension_id()) {
if (listener->IsLazy()) {
@@ -512,9 +514,7 @@ void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
}
}
- for (std::set<const EventListener*>::iterator it = listeners.begin();
- it != listeners.end(); it++) {
- const EventListener* listener = *it;
+ for (const EventListener* listener : listeners) {
if (restrict_to_extension_id.empty() ||
restrict_to_extension_id == listener->extension_id()) {
if (listener->process()) {
@@ -523,7 +523,8 @@ void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
if (!ContainsKey(already_dispatched, dispatch_id)) {
DispatchEventToProcess(listener->extension_id(),
listener->listener_url(), listener->process(),
- event, listener->filter());
+ event, listener->filter(),
+ false /* did_enqueue */);
}
}
}
@@ -567,7 +568,8 @@ void EventRouter::DispatchEventToProcess(
const GURL& listener_url,
content::RenderProcessHost* process,
const linked_ptr<Event>& event,
- const base::DictionaryValue* listener_filter) {
+ const base::DictionaryValue* listener_filter,
+ bool did_enqueue) {
BrowserContext* listener_context = process->GetBrowserContext();
ProcessMap* process_map = ProcessMap::Get(listener_context);
@@ -637,6 +639,7 @@ void EventRouter::DispatchEventToProcess(
event->user_gesture, event->filter_info);
if (extension) {
+ ReportEvent(event->histogram_value, extension, did_enqueue);
IncrementInFlightEvents(listener_context, extension, event_id,
event->event_name);
}
@@ -693,25 +696,27 @@ bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
}
// static
-void EventRouter::IncrementInFlightEventsOnUI(void* browser_context_id,
- const std::string& extension_id,
- int event_id,
- const std::string& event_name) {
+void EventRouter::DoDispatchEventToSenderBookkeepingOnUI(
+ void* browser_context_id,
+ const std::string& extension_id,
+ int event_id,
+ events::HistogramValue histogram_value,
+ const std::string& event_name) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserContext* browser_context =
reinterpret_cast<BrowserContext*>(browser_context_id);
if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
return;
- EventRouter* event_router = EventRouter::Get(browser_context);
- if (!event_router)
- return;
const Extension* extension =
ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
extension_id);
if (!extension)
return;
+ EventRouter* event_router = EventRouter::Get(browser_context);
event_router->IncrementInFlightEvents(browser_context, extension, event_id,
event_name);
+ event_router->ReportEvent(histogram_value, extension,
+ false /* did_enqueue */);
}
void EventRouter::IncrementInFlightEvents(BrowserContext* context,
@@ -747,6 +752,35 @@ void EventRouter::OnEventAck(BrowserContext* context,
pm->DecrementLazyKeepaliveCount(host->extension());
}
+void EventRouter::ReportEvent(events::HistogramValue histogram_value,
+ const Extension* extension,
+ bool did_enqueue) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // TODO(kalman): UMA for dispatched event.
+ // TODO(kalman): UMA specifically for component extensions.
+
+ // Note: for these, all we know is that the extension *has* a persistent or
+ // event page, not that the event is being dispatched *to* such a page.
+ //
+ // However, this is an academic distinction, since extensions with any
+ // background page have that background page running (or in the case of
+ // dormant event pages, must be started) regardless of where the event is
+ // being dispatched. Events are dispatched to a *process* not a *frame*.
+ if (BackgroundInfo::HasPersistentBackgroundPage(extension)) {
+ // TODO(kalman): UMA for dispatched event to an extension with a persistent
+ // background page.
+ } else if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
+ if (did_enqueue) {
+ // TODO(kalman): UMA for dispatched event to an extension with an event
+ // page, and the event page was woken up to do so.
+ } else {
+ // TODO(kalman): UMA for dispatched event to an extension with an event
+ // page that was already running.
+ }
+ }
+}
+
void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event,
ExtensionHost* host) {
if (!host)
@@ -754,9 +788,9 @@ void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event,
if (listeners_.HasProcessListener(host->render_process_host(),
host->extension()->id())) {
- // URL events cannot be lazy therefore can't be pending, hence the GURL().
- DispatchEventToProcess(host->extension()->id(), GURL(),
- host->render_process_host(), event, nullptr);
+ DispatchEventToProcess(host->extension()->id(), host->GetURL(),
+ host->render_process_host(), event, nullptr,
+ true /* did_enqueue */);
}
}
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h
index 767dcbc..e7b6499 100644
--- a/extensions/browser/event_router.h
+++ b/extensions/browser/event_router.h
@@ -26,6 +26,7 @@
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/event_filtering_info.h"
#include "ipc/ipc_sender.h"
+#include "url/gurl.h"
class GURL;
class PrefService;
@@ -85,13 +86,17 @@ class EventRouter : public KeyedService,
// Sends an event via ipc_sender to the given extension. Can be called on any
// thread.
- static void DispatchEvent(IPC::Sender* ipc_sender,
- void* browser_context_id,
- const std::string& extension_id,
- const std::string& event_name,
- scoped_ptr<base::ListValue> event_args,
- UserGestureState user_gesture,
- const EventFilteringInfo& info);
+ //
+ // It is very rare to call this function directly. Instead use the instance
+ // methods BroadcastEvent or DispatchEventToExtension.
+ static void DispatchEventToSender(IPC::Sender* ipc_sender,
+ void* browser_context_id,
+ const std::string& extension_id,
+ events::HistogramValue histogram_value,
+ const std::string& event_name,
+ scoped_ptr<base::ListValue> event_args,
+ UserGestureState user_gesture,
+ const EventFilteringInfo& info);
// An EventRouter is shared between |browser_context| and its associated
// incognito context. |extension_prefs| may be NULL in tests.
@@ -185,6 +190,15 @@ class EventRouter : public KeyedService,
void OnEventAck(content::BrowserContext* context,
const std::string& extension_id);
+ // Reports UMA for an event dispatched to |extension| with histogram value
+ // |histogram_value|. Must be called on the UI thread.
+ //
+ // |did_enqueue| should be true if the event was queued waiting for a process
+ // to start, like an event page.
+ void ReportEvent(events::HistogramValue histogram_value,
+ const Extension* extension,
+ bool did_enqueue);
+
private:
friend class EventRouterTest;
@@ -229,9 +243,9 @@ class EventRouter : public KeyedService,
const std::string& extension_id,
const std::string& event_name);
- // Shared by DispatchEvent*. If |restrict_to_extension_id| is empty, the
- // event is broadcast.
- // An event that just came off the pending list may not be delayed again.
+ // Shared by all event dispatch methods. If |restrict_to_extension_id| is
+ // empty, the event is broadcast. An event that just came off the pending
+ // list may not be delayed again.
void DispatchEventImpl(const std::string& restrict_to_extension_id,
const linked_ptr<Event>& event);
@@ -250,7 +264,8 @@ class EventRouter : public KeyedService,
const GURL& listener_url,
content::RenderProcessHost* process,
const linked_ptr<Event>& event,
- const base::DictionaryValue* listener_filter);
+ const base::DictionaryValue* listener_filter,
+ bool did_enqueue);
// Returns false when the event is scoped to a context and the listening
// extension does not have access to events from that context. Also fills
@@ -292,10 +307,12 @@ class EventRouter : public KeyedService,
const std::string& event_name);
// static
- static void IncrementInFlightEventsOnUI(void* browser_context_id,
- const std::string& extension_id,
- int event_id,
- const std::string& event_name);
+ static void DoDispatchEventToSenderBookkeepingOnUI(
+ void* browser_context_id,
+ const std::string& extension_id,
+ int event_id,
+ events::HistogramValue histogram_value,
+ const std::string& event_name);
void DispatchPendingEvent(const linked_ptr<Event>& event,
ExtensionHost* host);
diff --git a/extensions/browser/extension_event_histogram_value.h b/extensions/browser/extension_event_histogram_value.h
index 92054c0..03bd28c 100644
--- a/extensions/browser/extension_event_histogram_value.h
+++ b/extensions/browser/extension_event_histogram_value.h
@@ -362,8 +362,39 @@ enum HistogramValue {
SCREENLOCK_PRIVATE_ON_AUTH_ATTEMPTED,
TYPES_CHROME_SETTING_ON_CHANGE,
TYPES_PRIVATE_CHROME_DIRECT_SETTING_ON_CHANGE,
- WEB_VIEW_INTERNAL_ON_MESSAGE, // TODO(kalman): where are the rest of the
- // webview events?
+ WEB_VIEW_INTERNAL_ON_MESSAGE,
+ EXTENSION_VIEW_INTERNAL_ON_LOAD_COMMIT,
+ RUNTIME_ON_REQUEST,
+ RUNTIME_ON_REQUEST_EXTERNAL,
+ CHROME_WEB_VIEW_INTERNAL_ON_CONTEXT_MENU_SHOW,
+ WEB_VIEW_INTERNAL_ON_BEFORE_REQUEST,
+ WEB_VIEW_INTERNAL_ON_BEFORE_SEND_HEADERS,
+ WEB_VIEW_INTERNAL_ON_CLOSE,
+ WEB_VIEW_INTERNAL_ON_COMPLETED,
+ WEB_VIEW_INTERNAL_ON_CONSOLE_MESSAGE,
+ WEB_VIEW_INTERNAL_ON_CONTENT_LOAD,
+ WEB_VIEW_INTERNAL_ON_DIALOG,
+ WEB_VIEW_INTERNAL_ON_DROP_LINK,
+ WEB_VIEW_INTERNAL_ON_EXIT,
+ WEB_VIEW_INTERNAL_ON_EXIT_FULLSCREEN,
+ WEB_VIEW_INTERNAL_ON_FIND_REPLY,
+ WEB_VIEW_INTERNAL_ON_FRAME_NAME_CHANGED,
+ WEB_VIEW_INTERNAL_ON_HEADERS_RECEIVED,
+ WEB_VIEW_INTERNAL_ON_LOAD_ABORT,
+ WEB_VIEW_INTERNAL_ON_LOAD_COMMIT,
+ WEB_VIEW_INTERNAL_ON_LOAD_PROGRESS,
+ WEB_VIEW_INTERNAL_ON_LOAD_REDIRECT,
+ WEB_VIEW_INTERNAL_ON_LOAD_START,
+ WEB_VIEW_INTERNAL_ON_LOAD_STOP,
+ WEB_VIEW_INTERNAL_ON_NEW_WINDOW,
+ WEB_VIEW_INTERNAL_ON_PERMISSION_REQUEST,
+ WEB_VIEW_INTERNAL_ON_RESPONSE_STARTED,
+ WEB_VIEW_INTERNAL_ON_RESPONSIVE,
+ WEB_VIEW_INTERNAL_ON_SIZE_CHANGED,
+ WEB_VIEW_INTERNAL_ON_UNRESPONSIVE,
+ WEB_VIEW_INTERNAL_ON_ZOOM_CHANGE,
+ GUEST_VIEW_INTERNAL_ON_RESIZE,
+
// Last entry: Add new entries above, then run:
// python tools/metrics/histograms/update_extension_histograms.py
ENUM_BOUNDARY
diff --git a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
index c76988f..ac15622 100644
--- a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
+++ b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
@@ -6,6 +6,7 @@
#include "components/guest_view/browser/guest_view_base.h"
#include "components/guest_view/browser/guest_view_manager.h"
+#include "components/guest_view/common/guest_view_constants.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_process_host.h"
#include "extensions/browser/api/extensions_api_client.h"
@@ -13,6 +14,7 @@
#include "extensions/browser/guest_view/app_view/app_view_guest.h"
#include "extensions/browser/guest_view/extension_options/extension_options_guest.h"
#include "extensions/browser/guest_view/extension_view/extension_view_guest.h"
+#include "extensions/browser/guest_view/guest_view_events.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "extensions/browser/guest_view/surface_worker/surface_worker_guest.h"
#include "extensions/browser/guest_view/web_view/web_view_guest.h"
@@ -44,14 +46,19 @@ void ExtensionsGuestViewManagerDelegate::DispatchEvent(
scoped_ptr<base::ListValue> event_args(new base::ListValue());
event_args->Append(args.release());
- EventRouter::DispatchEvent(
- guest->owner_web_contents(),
- guest->browser_context(),
- guest->owner_host(),
- event_name,
- event_args.Pass(),
- EventRouter::USER_GESTURE_UNKNOWN,
- info);
+ // GetEventHistogramValue maps guest view event names to their histogram
+ // value. It needs to be like this because the guest view component doesn't
+ // know about extensions, so GuestViewEvent can't have an
+ // extensions::events::HistogramValue as an argument.
+ events::HistogramValue histogram_value =
+ guest_view_events::GetEventHistogramValue(event_name);
+ DCHECK_NE(events::UNKNOWN, histogram_value) << "Event " << event_name
+ << " must have a histogram value";
+
+ content::WebContents* owner = guest->owner_web_contents();
+ EventRouter::DispatchEventToSender(
+ owner, guest->browser_context(), guest->owner_host(), histogram_value,
+ event_name, event_args.Pass(), EventRouter::USER_GESTURE_UNKNOWN, info);
}
bool ExtensionsGuestViewManagerDelegate::IsGuestAvailableToContext(
diff --git a/extensions/browser/guest_view/guest_view_events.cc b/extensions/browser/guest_view/guest_view_events.cc
new file mode 100644
index 0000000..843083b
--- /dev/null
+++ b/extensions/browser/guest_view/guest_view_events.cc
@@ -0,0 +1,102 @@
+// Copyright 2015 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 "extensions/browser/guest_view/guest_view_events.h"
+
+#include <map>
+
+#include "base/lazy_instance.h"
+#include "components/guest_view/common/guest_view_constants.h"
+#include "extensions/browser/guest_view/extension_options/extension_options_constants.h"
+#include "extensions/browser/guest_view/extension_view/extension_view_constants.h"
+#include "extensions/browser/guest_view/web_view/web_view_constants.h"
+#include "extensions/common/api/extension_options_internal.h"
+
+namespace extensions {
+namespace guest_view_events {
+
+namespace {
+
+class EventMap {
+ public:
+ EventMap() {
+ struct NameAndValue {
+ const char* name;
+ events::HistogramValue value;
+ } names_and_values[] = {
+ {webview::kEventContextMenuShow,
+ events::CHROME_WEB_VIEW_INTERNAL_ON_CONTEXT_MENU_SHOW},
+ {api::extension_options_internal::OnClose::kEventName,
+ events::EXTENSION_OPTIONS_INTERNAL_ON_CLOSE},
+ {api::extension_options_internal::OnLoad::kEventName,
+ events::EXTENSION_OPTIONS_INTERNAL_ON_LOAD},
+ {api::extension_options_internal::OnPreferredSizeChanged::kEventName,
+ events::EXTENSION_OPTIONS_INTERNAL_ON_PREFERRED_SIZE_CHANGED},
+ {extensionview::kEventLoadCommit,
+ events::EXTENSION_VIEW_INTERNAL_ON_LOAD_COMMIT},
+ {guest_view::kEventResize, events::GUEST_VIEW_INTERNAL_ON_RESIZE},
+ {webview::kEventBeforeRequest,
+ events::WEB_VIEW_INTERNAL_ON_BEFORE_REQUEST},
+ {webview::kEventBeforeSendHeaders,
+ events::WEB_VIEW_INTERNAL_ON_BEFORE_SEND_HEADERS},
+ {webview::kEventClose, events::WEB_VIEW_INTERNAL_ON_CLOSE},
+ {webview::kEventCompleted, events::WEB_VIEW_INTERNAL_ON_COMPLETED},
+ {webview::kEventConsoleMessage,
+ events::WEB_VIEW_INTERNAL_ON_CONSOLE_MESSAGE},
+ {webview::kEventContentLoad, events::WEB_VIEW_INTERNAL_ON_CONTENT_LOAD},
+ {webview::kEventDialog, events::WEB_VIEW_INTERNAL_ON_DIALOG},
+ {webview::kEventDropLink, events::WEB_VIEW_INTERNAL_ON_DROP_LINK},
+ {webview::kEventExit, events::WEB_VIEW_INTERNAL_ON_EXIT},
+ {webview::kEventExitFullscreen,
+ events::WEB_VIEW_INTERNAL_ON_EXIT_FULLSCREEN},
+ {webview::kEventFindReply, events::WEB_VIEW_INTERNAL_ON_FIND_REPLY},
+ {webview::kEventHeadersReceived,
+ events::WEB_VIEW_INTERNAL_ON_HEADERS_RECEIVED},
+ {webview::kEventFrameNameChanged,
+ events::WEB_VIEW_INTERNAL_ON_FRAME_NAME_CHANGED},
+ {webview::kEventLoadAbort, events::WEB_VIEW_INTERNAL_ON_LOAD_ABORT},
+ {webview::kEventLoadCommit, events::WEB_VIEW_INTERNAL_ON_LOAD_COMMIT},
+ {webview::kEventLoadProgress,
+ events::WEB_VIEW_INTERNAL_ON_LOAD_PROGRESS},
+ {webview::kEventLoadRedirect,
+ events::WEB_VIEW_INTERNAL_ON_LOAD_REDIRECT},
+ {webview::kEventLoadStart, events::WEB_VIEW_INTERNAL_ON_LOAD_START},
+ {webview::kEventLoadStop, events::WEB_VIEW_INTERNAL_ON_LOAD_STOP},
+ {webview::kEventNewWindow, events::WEB_VIEW_INTERNAL_ON_NEW_WINDOW},
+ {webview::kEventPermissionRequest,
+ events::WEB_VIEW_INTERNAL_ON_PERMISSION_REQUEST},
+ {webview::kEventResponseStarted,
+ events::WEB_VIEW_INTERNAL_ON_RESPONSE_STARTED},
+ {webview::kEventResponsive, events::WEB_VIEW_INTERNAL_ON_RESPONSIVE},
+ {webview::kEventSizeChanged, events::WEB_VIEW_INTERNAL_ON_SIZE_CHANGED},
+ {webview::kEventUnresponsive,
+ events::WEB_VIEW_INTERNAL_ON_UNRESPONSIVE},
+ {webview::kEventZoomChange, events::WEB_VIEW_INTERNAL_ON_ZOOM_CHANGE},
+ };
+ for (const auto& name_and_value : names_and_values) {
+ values_[name_and_value.name] = name_and_value.value;
+ }
+ }
+
+ events::HistogramValue Get(const std::string& event_name) {
+ auto value = values_.find(event_name);
+ return value != values_.end() ? value->second : events::UNKNOWN;
+ }
+
+ private:
+ std::map<std::string, events::HistogramValue> values_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventMap);
+};
+
+base::LazyInstance<EventMap> g_event_map = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+events::HistogramValue GetEventHistogramValue(const std::string& event_name) {
+ return g_event_map.Get().Get(event_name);
+}
+
+} // namespace guest_view_events
+} // namespace extensions
diff --git a/extensions/browser/guest_view/guest_view_events.h b/extensions/browser/guest_view/guest_view_events.h
new file mode 100644
index 0000000..ba7e496
--- /dev/null
+++ b/extensions/browser/guest_view/guest_view_events.h
@@ -0,0 +1,23 @@
+// Copyright 2015 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 EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_EVENTS_H_
+#define EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_EVENTS_H_
+
+#include <string>
+
+#include "extensions/browser/extension_event_histogram_value.h"
+
+namespace extensions {
+namespace guest_view_events {
+
+// Returns the events::HistogramValue for the |event_name| guest view event.
+// This knows about all events for all guest view types, whether web view,
+// extension options, the guest view base class, etc.
+events::HistogramValue GetEventHistogramValue(const std::string& event_name);
+
+} // namespace guest_view_events
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_EVENTS_H_
diff --git a/extensions/browser/guest_view/web_view/web_view_constants.cc b/extensions/browser/guest_view/web_view/web_view_constants.cc
index 18ae46f..52834fa 100644
--- a/extensions/browser/guest_view/web_view/web_view_constants.cc
+++ b/extensions/browser/guest_view/web_view/web_view_constants.cc
@@ -21,7 +21,10 @@ const char kAPILoadDataInvalidBaseURL[] = "Invalid base URL \"%s\".";
const char kAPILoadDataInvalidVirtualURL[] = "Invalid virtual URL \"%s\".";
// Events.
+const char kEventBeforeRequest[] = "webViewInternal.onBeforeRequest";
+const char kEventBeforeSendHeaders[] = "webViewInternal.onBeforeSendHeaders";
const char kEventClose[] = "webViewInternal.onClose";
+const char kEventCompleted[] = "webViewInternal.onCompleted";
const char kEventConsoleMessage[] = "webViewInternal.onConsoleMessage";
const char kEventContentLoad[] = "webViewInternal.onContentLoad";
const char kEventContextMenuShow[] = "chromeWebViewInternal.onContextMenuShow";
@@ -31,6 +34,7 @@ const char kEventExit[] = "webViewInternal.onExit";
const char kEventExitFullscreen[] = "webViewInternal.onExitFullscreen";
const char kEventFindReply[] = "webViewInternal.onFindReply";
const char kEventFrameNameChanged[] = "webViewInternal.onFrameNameChanged";
+const char kEventHeadersReceived[] = "webViewInternal.onHeadersReceived";
const char kEventLoadAbort[] = "webViewInternal.onLoadAbort";
const char kEventLoadCommit[] = "webViewInternal.onLoadCommit";
const char kEventLoadProgress[] = "webViewInternal.onLoadProgress";
@@ -40,6 +44,7 @@ const char kEventLoadStop[] = "webViewInternal.onLoadStop";
const char kEventMessage[] = "webViewInternal.onMessage";
const char kEventNewWindow[] = "webViewInternal.onNewWindow";
const char kEventPermissionRequest[] = "webViewInternal.onPermissionRequest";
+const char kEventResponseStarted[] = "webViewInternal.onResponseStarted";
const char kEventResponsive[] = "webViewInternal.onResponsive";
const char kEventSizeChanged[] = "webViewInternal.onSizeChanged";
const char kEventUnresponsive[] = "webViewInternal.onUnresponsive";
diff --git a/extensions/browser/guest_view/web_view/web_view_constants.h b/extensions/browser/guest_view/web_view/web_view_constants.h
index 8dfd287..7bc877b 100644
--- a/extensions/browser/guest_view/web_view/web_view_constants.h
+++ b/extensions/browser/guest_view/web_view/web_view_constants.h
@@ -27,7 +27,10 @@ extern const char kAPILoadDataInvalidBaseURL[];
extern const char kAPILoadDataInvalidVirtualURL[];
// Events.
+extern const char kEventBeforeRequest[];
+extern const char kEventBeforeSendHeaders[];
extern const char kEventClose[];
+extern const char kEventCompleted[];
extern const char kEventConsoleMessage[];
extern const char kEventContentLoad[];
extern const char kEventContextMenuShow[];
@@ -37,6 +40,7 @@ extern const char kEventExit[];
extern const char kEventExitFullscreen[];
extern const char kEventFindReply[];
extern const char kEventFrameNameChanged[];
+extern const char kEventHeadersReceived[];
extern const char kEventLoadAbort[];
extern const char kEventLoadCommit[];
extern const char kEventLoadProgress[];
@@ -46,6 +50,7 @@ extern const char kEventLoadStop[];
extern const char kEventMessage[];
extern const char kEventNewWindow[];
extern const char kEventPermissionRequest[];
+extern const char kEventResponseStarted[];
extern const char kEventResponsive[];
extern const char kEventSizeChanged[];
extern const char kEventUnresponsive[];
diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi
index 1686c66..e690780 100644
--- a/extensions/extensions.gypi
+++ b/extensions/extensions.gypi
@@ -665,6 +665,8 @@
'browser/guest_view/extensions_guest_view_manager_delegate.h',
'browser/guest_view/extensions_guest_view_message_filter.cc',
'browser/guest_view/extensions_guest_view_message_filter.h',
+ 'browser/guest_view/guest_view_events.cc',
+ 'browser/guest_view/guest_view_events.h',
'browser/guest_view/mime_handler_view/mime_handler_stream_manager.cc',
'browser/guest_view/mime_handler_view/mime_handler_stream_manager.h',
'browser/guest_view/mime_handler_view/mime_handler_view_constants.cc',
diff --git a/extensions/renderer/resources/extension_custom_bindings.js b/extensions/renderer/resources/extension_custom_bindings.js
index d114f52..155b762 100644
--- a/extensions/renderer/resources/extension_custom_bindings.js
+++ b/extensions/renderer/resources/extension_custom_bindings.js
@@ -9,8 +9,6 @@ var binding = require('binding').Binding.create('extension');
var messaging = require('messaging');
var runtimeNatives = requireNative('runtime');
var GetExtensionViews = runtimeNatives.GetExtensionViews;
-var OpenChannelToExtension = runtimeNatives.OpenChannelToExtension;
-var OpenChannelToNativeApp = runtimeNatives.OpenChannelToNativeApp;
var chrome = requireNative('chrome').GetChrome();
var inIncognitoContext = requireNative('process').InIncognitoContext();
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 0a816b7..c7fd3f5 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -56077,6 +56077,37 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
<int value="342" label="TYPES_CHROME_SETTING_ON_CHANGE"/>
<int value="343" label="TYPES_PRIVATE_CHROME_DIRECT_SETTING_ON_CHANGE"/>
<int value="344" label="WEB_VIEW_INTERNAL_ON_MESSAGE"/>
+ <int value="345" label="EXTENSION_VIEW_INTERNAL_ON_LOAD_COMMIT"/>
+ <int value="346" label="RUNTIME_ON_REQUEST"/>
+ <int value="347" label="RUNTIME_ON_REQUEST_EXTERNAL"/>
+ <int value="348" label="CHROME_WEB_VIEW_INTERNAL_ON_CONTEXT_MENU_SHOW"/>
+ <int value="349" label="WEB_VIEW_INTERNAL_ON_BEFORE_REQUEST"/>
+ <int value="350" label="WEB_VIEW_INTERNAL_ON_BEFORE_SEND_HEADERS"/>
+ <int value="351" label="WEB_VIEW_INTERNAL_ON_CLOSE"/>
+ <int value="352" label="WEB_VIEW_INTERNAL_ON_COMPLETED"/>
+ <int value="353" label="WEB_VIEW_INTERNAL_ON_CONSOLE_MESSAGE"/>
+ <int value="354" label="WEB_VIEW_INTERNAL_ON_CONTENT_LOAD"/>
+ <int value="355" label="WEB_VIEW_INTERNAL_ON_DIALOG"/>
+ <int value="356" label="WEB_VIEW_INTERNAL_ON_DROP_LINK"/>
+ <int value="357" label="WEB_VIEW_INTERNAL_ON_EXIT"/>
+ <int value="358" label="WEB_VIEW_INTERNAL_ON_EXIT_FULLSCREEN"/>
+ <int value="359" label="WEB_VIEW_INTERNAL_ON_FIND_REPLY"/>
+ <int value="360" label="WEB_VIEW_INTERNAL_ON_FRAME_NAME_CHANGED"/>
+ <int value="361" label="WEB_VIEW_INTERNAL_ON_HEADERS_RECEIVED"/>
+ <int value="362" label="WEB_VIEW_INTERNAL_ON_LOAD_ABORT"/>
+ <int value="363" label="WEB_VIEW_INTERNAL_ON_LOAD_COMMIT"/>
+ <int value="364" label="WEB_VIEW_INTERNAL_ON_LOAD_PROGRESS"/>
+ <int value="365" label="WEB_VIEW_INTERNAL_ON_LOAD_REDIRECT"/>
+ <int value="366" label="WEB_VIEW_INTERNAL_ON_LOAD_START"/>
+ <int value="367" label="WEB_VIEW_INTERNAL_ON_LOAD_STOP"/>
+ <int value="368" label="WEB_VIEW_INTERNAL_ON_NEW_WINDOW"/>
+ <int value="369" label="WEB_VIEW_INTERNAL_ON_PERMISSION_REQUEST"/>
+ <int value="370" label="WEB_VIEW_INTERNAL_ON_RESPONSE_STARTED"/>
+ <int value="371" label="WEB_VIEW_INTERNAL_ON_RESPONSIVE"/>
+ <int value="372" label="WEB_VIEW_INTERNAL_ON_SIZE_CHANGED"/>
+ <int value="373" label="WEB_VIEW_INTERNAL_ON_UNRESPONSIVE"/>
+ <int value="374" label="WEB_VIEW_INTERNAL_ON_ZOOM_CHANGE"/>
+ <int value="375" label="GUEST_VIEW_INTERNAL_ON_RESIZE"/>
</enum>
<enum name="ExtensionFileWriteResult" type="int">