Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(953)

Side by Side Diff: extensions/browser/event_router.cc

Issue 1272373003: Add extension event histogram values for messaging, webRequest, and webview. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: last Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « extensions/browser/event_router.h ('k') | extensions/browser/extension_event_histogram_value.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/browser/event_router.h" 5 #include "extensions/browser/event_router.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/atomic_sequence_num.h" 9 #include "base/atomic_sequence_num.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
13 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "content/public/browser/notification_service.h" 16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/render_process_host.h" 17 #include "content/public/browser/render_process_host.h"
18 #include "extensions/browser/api_activity_monitor.h" 18 #include "extensions/browser/api_activity_monitor.h"
19 #include "extensions/browser/event_router_factory.h" 19 #include "extensions/browser/event_router_factory.h"
20 #include "extensions/browser/extension_host.h" 20 #include "extensions/browser/extension_host.h"
21 #include "extensions/browser/extension_prefs.h" 21 #include "extensions/browser/extension_prefs.h"
22 #include "extensions/browser/extension_registry.h" 22 #include "extensions/browser/extension_registry.h"
23 #include "extensions/browser/extension_system.h" 23 #include "extensions/browser/extension_system.h"
24 #include "extensions/browser/extensions_browser_client.h" 24 #include "extensions/browser/extensions_browser_client.h"
25 #include "extensions/browser/lazy_background_task_queue.h" 25 #include "extensions/browser/lazy_background_task_queue.h"
26 #include "extensions/browser/notification_types.h" 26 #include "extensions/browser/notification_types.h"
27 #include "extensions/browser/process_manager.h" 27 #include "extensions/browser/process_manager.h"
28 #include "extensions/browser/process_map.h" 28 #include "extensions/browser/process_map.h"
29 #include "extensions/common/constants.h"
29 #include "extensions/common/extension.h" 30 #include "extensions/common/extension.h"
30 #include "extensions/common/extension_api.h" 31 #include "extensions/common/extension_api.h"
31 #include "extensions/common/extension_messages.h" 32 #include "extensions/common/extension_messages.h"
32 #include "extensions/common/extension_urls.h" 33 #include "extensions/common/extension_urls.h"
33 #include "extensions/common/features/feature.h" 34 #include "extensions/common/features/feature.h"
34 #include "extensions/common/features/feature_provider.h" 35 #include "extensions/common/features/feature_provider.h"
35 #include "extensions/common/manifest_handlers/background_info.h" 36 #include "extensions/common/manifest_handlers/background_info.h"
36 #include "extensions/common/manifest_handlers/incognito_info.h" 37 #include "extensions/common/manifest_handlers/incognito_info.h"
37 #include "extensions/common/permissions/permissions_data.h" 38 #include "extensions/common/permissions/permissions_data.h"
38 39
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 return EventRouterFactory::GetForBrowserContext(browser_context); 141 return EventRouterFactory::GetForBrowserContext(browser_context);
141 } 142 }
142 143
143 // static 144 // static
144 std::string EventRouter::GetBaseEventName(const std::string& full_event_name) { 145 std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
145 size_t slash_sep = full_event_name.find('/'); 146 size_t slash_sep = full_event_name.find('/');
146 return full_event_name.substr(0, slash_sep); 147 return full_event_name.substr(0, slash_sep);
147 } 148 }
148 149
149 // static 150 // static
150 void EventRouter::DispatchEvent(IPC::Sender* ipc_sender, 151 void EventRouter::DispatchEventToSender(IPC::Sender* ipc_sender,
151 void* browser_context_id, 152 void* browser_context_id,
152 const std::string& extension_id, 153 const std::string& extension_id,
153 const std::string& event_name, 154 events::HistogramValue histogram_value,
154 scoped_ptr<ListValue> event_args, 155 const std::string& event_name,
155 UserGestureState user_gesture, 156 scoped_ptr<ListValue> event_args,
156 const EventFilteringInfo& info) { 157 UserGestureState user_gesture,
158 const EventFilteringInfo& info) {
157 int event_id = g_extension_event_id.GetNext(); 159 int event_id = g_extension_event_id.GetNext();
158 160
159 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 161 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
162 DoDispatchEventToSenderBookkeepingOnUI(browser_context_id, extension_id,
163 event_id, histogram_value,
164 event_name);
165 } else {
160 // This is called from WebRequest API. 166 // This is called from WebRequest API.
161 // TODO(lazyboy): Skip this entirely: http://crbug.com/488747. 167 // TODO(lazyboy): Skip this entirely: http://crbug.com/488747.
162 BrowserThread::PostTask( 168 BrowserThread::PostTask(
163 BrowserThread::UI, FROM_HERE, 169 BrowserThread::UI, FROM_HERE,
164 base::Bind(&EventRouter::IncrementInFlightEventsOnUI, 170 base::Bind(&EventRouter::DoDispatchEventToSenderBookkeepingOnUI,
165 browser_context_id, extension_id, event_id, event_name)); 171 browser_context_id, extension_id, event_id, histogram_value,
166 } else { 172 event_name));
167 IncrementInFlightEventsOnUI(browser_context_id, extension_id, event_id,
168 event_name);
169 } 173 }
170 174
171 DispatchExtensionMessage(ipc_sender, browser_context_id, extension_id, 175 DispatchExtensionMessage(ipc_sender, browser_context_id, extension_id,
172 event_id, event_name, event_args.get(), user_gesture, 176 event_id, event_name, event_args.get(), user_gesture,
173 info); 177 info);
174 } 178 }
175 179
176 EventRouter::EventRouter(BrowserContext* browser_context, 180 EventRouter::EventRouter(BrowserContext* browser_context,
177 ExtensionPrefs* extension_prefs) 181 ExtensionPrefs* extension_prefs)
178 : browser_context_(browser_context), 182 : browser_context_(browser_context),
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 listeners_.GetEventListeners(*event)); 497 listeners_.GetEventListeners(*event));
494 498
495 std::set<EventDispatchIdentifier> already_dispatched; 499 std::set<EventDispatchIdentifier> already_dispatched;
496 500
497 // We dispatch events for lazy background pages first because attempting to do 501 // We dispatch events for lazy background pages first because attempting to do
498 // so will cause those that are being suspended to cancel that suspension. 502 // so will cause those that are being suspended to cancel that suspension.
499 // As canceling a suspension entails sending an event to the affected 503 // As canceling a suspension entails sending an event to the affected
500 // background page, and as that event needs to be delivered before we dispatch 504 // background page, and as that event needs to be delivered before we dispatch
501 // the event we are dispatching here, we dispatch to the lazy listeners here 505 // the event we are dispatching here, we dispatch to the lazy listeners here
502 // first. 506 // first.
503 for (std::set<const EventListener*>::iterator it = listeners.begin(); 507 for (const EventListener* listener : listeners) {
504 it != listeners.end(); it++) {
505 const EventListener* listener = *it;
506 if (restrict_to_extension_id.empty() || 508 if (restrict_to_extension_id.empty() ||
507 restrict_to_extension_id == listener->extension_id()) { 509 restrict_to_extension_id == listener->extension_id()) {
508 if (listener->IsLazy()) { 510 if (listener->IsLazy()) {
509 DispatchLazyEvent(listener->extension_id(), event, &already_dispatched, 511 DispatchLazyEvent(listener->extension_id(), event, &already_dispatched,
510 listener->filter()); 512 listener->filter());
511 } 513 }
512 } 514 }
513 } 515 }
514 516
515 for (std::set<const EventListener*>::iterator it = listeners.begin(); 517 for (const EventListener* listener : listeners) {
516 it != listeners.end(); it++) {
517 const EventListener* listener = *it;
518 if (restrict_to_extension_id.empty() || 518 if (restrict_to_extension_id.empty() ||
519 restrict_to_extension_id == listener->extension_id()) { 519 restrict_to_extension_id == listener->extension_id()) {
520 if (listener->process()) { 520 if (listener->process()) {
521 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(), 521 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(),
522 listener->extension_id()); 522 listener->extension_id());
523 if (!ContainsKey(already_dispatched, dispatch_id)) { 523 if (!ContainsKey(already_dispatched, dispatch_id)) {
524 DispatchEventToProcess(listener->extension_id(), 524 DispatchEventToProcess(listener->extension_id(),
525 listener->listener_url(), listener->process(), 525 listener->listener_url(), listener->process(),
526 event, listener->filter()); 526 event, listener->filter(),
527 false /* did_enqueue */);
527 } 528 }
528 } 529 }
529 } 530 }
530 } 531 }
531 } 532 }
532 533
533 void EventRouter::DispatchLazyEvent( 534 void EventRouter::DispatchLazyEvent(
534 const std::string& extension_id, 535 const std::string& extension_id,
535 const linked_ptr<Event>& event, 536 const linked_ptr<Event>& event,
536 std::set<EventDispatchIdentifier>* already_dispatched, 537 std::set<EventDispatchIdentifier>* already_dispatched,
(...skipping 23 matching lines...) Expand all
560 std::make_pair(incognito_context, extension_id)); 561 std::make_pair(incognito_context, extension_id));
561 } 562 }
562 } 563 }
563 } 564 }
564 565
565 void EventRouter::DispatchEventToProcess( 566 void EventRouter::DispatchEventToProcess(
566 const std::string& extension_id, 567 const std::string& extension_id,
567 const GURL& listener_url, 568 const GURL& listener_url,
568 content::RenderProcessHost* process, 569 content::RenderProcessHost* process,
569 const linked_ptr<Event>& event, 570 const linked_ptr<Event>& event,
570 const base::DictionaryValue* listener_filter) { 571 const base::DictionaryValue* listener_filter,
572 bool did_enqueue) {
571 BrowserContext* listener_context = process->GetBrowserContext(); 573 BrowserContext* listener_context = process->GetBrowserContext();
572 ProcessMap* process_map = ProcessMap::Get(listener_context); 574 ProcessMap* process_map = ProcessMap::Get(listener_context);
573 575
574 // NOTE: |extension| being NULL does not necessarily imply that this event 576 // NOTE: |extension| being NULL does not necessarily imply that this event
575 // shouldn't be dispatched. Events can be dispatched to WebUI and webviews as 577 // shouldn't be dispatched. Events can be dispatched to WebUI and webviews as
576 // well. It all depends on what GetMostLikelyContextType returns. 578 // well. It all depends on what GetMostLikelyContextType returns.
577 const Extension* extension = 579 const Extension* extension =
578 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID( 580 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
579 extension_id); 581 extension_id);
580 582
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 listener_filter)) { 632 listener_filter)) {
631 return; 633 return;
632 } 634 }
633 635
634 int event_id = g_extension_event_id.GetNext(); 636 int event_id = g_extension_event_id.GetNext();
635 DispatchExtensionMessage(process, listener_context, extension_id, event_id, 637 DispatchExtensionMessage(process, listener_context, extension_id, event_id,
636 event->event_name, event->event_args.get(), 638 event->event_name, event->event_args.get(),
637 event->user_gesture, event->filter_info); 639 event->user_gesture, event->filter_info);
638 640
639 if (extension) { 641 if (extension) {
642 ReportEvent(event->histogram_value, extension, did_enqueue);
640 IncrementInFlightEvents(listener_context, extension, event_id, 643 IncrementInFlightEvents(listener_context, extension, event_id,
641 event->event_name); 644 event->event_name);
642 } 645 }
643 } 646 }
644 647
645 bool EventRouter::CanDispatchEventToBrowserContext( 648 bool EventRouter::CanDispatchEventToBrowserContext(
646 BrowserContext* context, 649 BrowserContext* context,
647 const Extension* extension, 650 const Extension* extension,
648 const linked_ptr<Event>& event) { 651 const linked_ptr<Event>& event) {
649 // Is this event from a different browser context than the renderer (ie, an 652 // Is this event from a different browser context than the renderer (ie, an
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 queue->AddPendingTask(context, extension->id(), 689 queue->AddPendingTask(context, extension->id(),
687 base::Bind(&EventRouter::DispatchPendingEvent, 690 base::Bind(&EventRouter::DispatchPendingEvent,
688 base::Unretained(this), dispatched_event)); 691 base::Unretained(this), dispatched_event));
689 return true; 692 return true;
690 } 693 }
691 694
692 return false; 695 return false;
693 } 696 }
694 697
695 // static 698 // static
696 void EventRouter::IncrementInFlightEventsOnUI(void* browser_context_id, 699 void EventRouter::DoDispatchEventToSenderBookkeepingOnUI(
697 const std::string& extension_id, 700 void* browser_context_id,
698 int event_id, 701 const std::string& extension_id,
699 const std::string& event_name) { 702 int event_id,
703 events::HistogramValue histogram_value,
704 const std::string& event_name) {
700 DCHECK_CURRENTLY_ON(BrowserThread::UI); 705 DCHECK_CURRENTLY_ON(BrowserThread::UI);
701 BrowserContext* browser_context = 706 BrowserContext* browser_context =
702 reinterpret_cast<BrowserContext*>(browser_context_id); 707 reinterpret_cast<BrowserContext*>(browser_context_id);
703 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context)) 708 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
704 return; 709 return;
705 EventRouter* event_router = EventRouter::Get(browser_context);
706 if (!event_router)
707 return;
708 const Extension* extension = 710 const Extension* extension =
709 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID( 711 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
710 extension_id); 712 extension_id);
711 if (!extension) 713 if (!extension)
712 return; 714 return;
715 EventRouter* event_router = EventRouter::Get(browser_context);
713 event_router->IncrementInFlightEvents(browser_context, extension, event_id, 716 event_router->IncrementInFlightEvents(browser_context, extension, event_id,
714 event_name); 717 event_name);
718 event_router->ReportEvent(histogram_value, extension,
719 false /* did_enqueue */);
715 } 720 }
716 721
717 void EventRouter::IncrementInFlightEvents(BrowserContext* context, 722 void EventRouter::IncrementInFlightEvents(BrowserContext* context,
718 const Extension* extension, 723 const Extension* extension,
719 int event_id, 724 int event_id,
720 const std::string& event_name) { 725 const std::string& event_name) {
721 // TODO(chirantan): Turn this on once crbug.com/464513 is fixed. 726 // TODO(chirantan): Turn this on once crbug.com/464513 is fixed.
722 // DCHECK_CURRENTLY_ON(BrowserThread::UI); 727 // DCHECK_CURRENTLY_ON(BrowserThread::UI);
723 728
724 // Only increment in-flight events if the lazy background page is active, 729 // Only increment in-flight events if the lazy background page is active,
(...skipping 15 matching lines...) Expand all
740 // The event ACK is routed to the background host, so this should never be 745 // The event ACK is routed to the background host, so this should never be
741 // NULL. 746 // NULL.
742 CHECK(host); 747 CHECK(host);
743 // TODO(mpcomplete): We should never get this message unless 748 // TODO(mpcomplete): We should never get this message unless
744 // HasLazyBackgroundPage is true. Find out why we're getting it anyway. 749 // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
745 if (host->extension() && 750 if (host->extension() &&
746 BackgroundInfo::HasLazyBackgroundPage(host->extension())) 751 BackgroundInfo::HasLazyBackgroundPage(host->extension()))
747 pm->DecrementLazyKeepaliveCount(host->extension()); 752 pm->DecrementLazyKeepaliveCount(host->extension());
748 } 753 }
749 754
755 void EventRouter::ReportEvent(events::HistogramValue histogram_value,
756 const Extension* extension,
757 bool did_enqueue) {
758 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
759
760 // TODO(kalman): UMA for dispatched event.
761 // TODO(kalman): UMA specifically for component extensions.
762
763 // Note: for these, all we know is that the extension *has* a persistent or
764 // event page, not that the event is being dispatched *to* such a page.
765 //
766 // However, this is an academic distinction, since extensions with any
767 // background page have that background page running (or in the case of
768 // dormant event pages, must be started) regardless of where the event is
769 // being dispatched. Events are dispatched to a *process* not a *frame*.
770 if (BackgroundInfo::HasPersistentBackgroundPage(extension)) {
771 // TODO(kalman): UMA for dispatched event to an extension with a persistent
772 // background page.
773 } else if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
774 if (did_enqueue) {
775 // TODO(kalman): UMA for dispatched event to an extension with an event
776 // page, and the event page was woken up to do so.
777 } else {
778 // TODO(kalman): UMA for dispatched event to an extension with an event
779 // page that was already running.
780 }
781 }
782 }
783
750 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event, 784 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event,
751 ExtensionHost* host) { 785 ExtensionHost* host) {
752 if (!host) 786 if (!host)
753 return; 787 return;
754 788
755 if (listeners_.HasProcessListener(host->render_process_host(), 789 if (listeners_.HasProcessListener(host->render_process_host(),
756 host->extension()->id())) { 790 host->extension()->id())) {
757 // URL events cannot be lazy therefore can't be pending, hence the GURL(). 791 DispatchEventToProcess(host->extension()->id(), host->GetURL(),
758 DispatchEventToProcess(host->extension()->id(), GURL(), 792 host->render_process_host(), event, nullptr,
759 host->render_process_host(), event, nullptr); 793 true /* did_enqueue */);
760 } 794 }
761 } 795 }
762 796
763 void EventRouter::Observe(int type, 797 void EventRouter::Observe(int type,
764 const content::NotificationSource& source, 798 const content::NotificationSource& source,
765 const content::NotificationDetails& details) { 799 const content::NotificationDetails& details) {
766 switch (type) { 800 switch (type) {
767 case extensions::NOTIFICATION_EXTENSION_ENABLED: { 801 case extensions::NOTIFICATION_EXTENSION_ENABLED: {
768 // If the extension has a lazy background page, make sure it gets loaded 802 // If the extension has a lazy background page, make sure it gets loaded
769 // to register the events the extension is interested in. 803 // to register the events the extension is interested in.
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 const std::string& extension_id, 889 const std::string& extension_id,
856 const GURL& listener_url, 890 const GURL& listener_url,
857 content::BrowserContext* browser_context) 891 content::BrowserContext* browser_context)
858 : event_name(event_name), 892 : event_name(event_name),
859 extension_id(extension_id), 893 extension_id(extension_id),
860 listener_url(listener_url), 894 listener_url(listener_url),
861 browser_context(browser_context) { 895 browser_context(browser_context) {
862 } 896 }
863 897
864 } // namespace extensions 898 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/event_router.h ('k') | extensions/browser/extension_event_histogram_value.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698