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

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: devlin 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
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 GURL& url,
153 const std::string& event_name, 154 const std::string& extension_id,
154 scoped_ptr<ListValue> event_args, 155 events::HistogramValue histogram_value,
155 UserGestureState user_gesture, 156 const std::string& event_name,
156 const EventFilteringInfo& info) { 157 scoped_ptr<ListValue> event_args,
158 UserGestureState user_gesture,
159 const EventFilteringInfo& info) {
157 int event_id = g_extension_event_id.GetNext(); 160 int event_id = g_extension_event_id.GetNext();
158 161
159 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 162 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
163 DoDispatchEventToSenderBookkeepingOnUI(browser_context_id, extension_id,
164 url, event_id, histogram_value,
165 event_name);
166 } else {
160 // This is called from WebRequest API. 167 // This is called from WebRequest API.
161 // TODO(lazyboy): Skip this entirely: http://crbug.com/488747. 168 // TODO(lazyboy): Skip this entirely: http://crbug.com/488747.
162 BrowserThread::PostTask( 169 BrowserThread::PostTask(
163 BrowserThread::UI, FROM_HERE, 170 BrowserThread::UI, FROM_HERE,
164 base::Bind(&EventRouter::IncrementInFlightEventsOnUI, 171 base::Bind(&EventRouter::DoDispatchEventToSenderBookkeepingOnUI,
165 browser_context_id, extension_id, event_id, event_name)); 172 browser_context_id, extension_id, url, event_id,
166 } else { 173 histogram_value, event_name));
167 IncrementInFlightEventsOnUI(browser_context_id, extension_id, event_id,
168 event_name);
169 } 174 }
170 175
171 DispatchExtensionMessage(ipc_sender, browser_context_id, extension_id, 176 DispatchExtensionMessage(ipc_sender, browser_context_id, extension_id,
172 event_id, event_name, event_args.get(), user_gesture, 177 event_id, event_name, event_args.get(), user_gesture,
173 info); 178 info);
174 } 179 }
175 180
176 EventRouter::EventRouter(BrowserContext* browser_context, 181 EventRouter::EventRouter(BrowserContext* browser_context,
177 ExtensionPrefs* extension_prefs) 182 ExtensionPrefs* extension_prefs)
178 : browser_context_(browser_context), 183 : browser_context_(browser_context),
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 listeners_.GetEventListeners(*event)); 498 listeners_.GetEventListeners(*event));
494 499
495 std::set<EventDispatchIdentifier> already_dispatched; 500 std::set<EventDispatchIdentifier> already_dispatched;
496 501
497 // We dispatch events for lazy background pages first because attempting to do 502 // 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. 503 // so will cause those that are being suspended to cancel that suspension.
499 // As canceling a suspension entails sending an event to the affected 504 // 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 505 // 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 506 // the event we are dispatching here, we dispatch to the lazy listeners here
502 // first. 507 // first.
503 for (std::set<const EventListener*>::iterator it = listeners.begin(); 508 for (const EventListener* listener : listeners) {
504 it != listeners.end(); it++) {
505 const EventListener* listener = *it;
506 if (restrict_to_extension_id.empty() || 509 if (restrict_to_extension_id.empty() ||
507 restrict_to_extension_id == listener->extension_id()) { 510 restrict_to_extension_id == listener->extension_id()) {
508 if (listener->IsLazy()) { 511 if (listener->IsLazy()) {
509 DispatchLazyEvent(listener->extension_id(), event, &already_dispatched, 512 DispatchLazyEvent(listener->extension_id(), event, &already_dispatched,
510 listener->filter()); 513 listener->filter());
511 } 514 }
512 } 515 }
513 } 516 }
514 517
515 for (std::set<const EventListener*>::iterator it = listeners.begin(); 518 for (const EventListener* listener : listeners) {
516 it != listeners.end(); it++) {
517 const EventListener* listener = *it;
518 if (restrict_to_extension_id.empty() || 519 if (restrict_to_extension_id.empty() ||
519 restrict_to_extension_id == listener->extension_id()) { 520 restrict_to_extension_id == listener->extension_id()) {
520 if (listener->process()) { 521 if (listener->process()) {
521 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(), 522 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(),
522 listener->extension_id()); 523 listener->extension_id());
523 if (!ContainsKey(already_dispatched, dispatch_id)) { 524 if (!ContainsKey(already_dispatched, dispatch_id)) {
524 DispatchEventToProcess(listener->extension_id(), 525 DispatchEventToProcess(listener->extension_id(),
525 listener->listener_url(), listener->process(), 526 listener->listener_url(), listener->process(),
526 event, listener->filter()); 527 event, listener->filter(),
528 false /* did_enqueue */);
527 } 529 }
528 } 530 }
529 } 531 }
530 } 532 }
531 } 533 }
532 534
533 void EventRouter::DispatchLazyEvent( 535 void EventRouter::DispatchLazyEvent(
534 const std::string& extension_id, 536 const std::string& extension_id,
535 const linked_ptr<Event>& event, 537 const linked_ptr<Event>& event,
536 std::set<EventDispatchIdentifier>* already_dispatched, 538 std::set<EventDispatchIdentifier>* already_dispatched,
(...skipping 23 matching lines...) Expand all
560 std::make_pair(incognito_context, extension_id)); 562 std::make_pair(incognito_context, extension_id));
561 } 563 }
562 } 564 }
563 } 565 }
564 566
565 void EventRouter::DispatchEventToProcess( 567 void EventRouter::DispatchEventToProcess(
566 const std::string& extension_id, 568 const std::string& extension_id,
567 const GURL& listener_url, 569 const GURL& listener_url,
568 content::RenderProcessHost* process, 570 content::RenderProcessHost* process,
569 const linked_ptr<Event>& event, 571 const linked_ptr<Event>& event,
570 const base::DictionaryValue* listener_filter) { 572 const base::DictionaryValue* listener_filter,
573 bool did_enqueue) {
571 BrowserContext* listener_context = process->GetBrowserContext(); 574 BrowserContext* listener_context = process->GetBrowserContext();
572 ProcessMap* process_map = ProcessMap::Get(listener_context); 575 ProcessMap* process_map = ProcessMap::Get(listener_context);
573 576
574 // NOTE: |extension| being NULL does not necessarily imply that this event 577 // 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 578 // shouldn't be dispatched. Events can be dispatched to WebUI and webviews as
576 // well. It all depends on what GetMostLikelyContextType returns. 579 // well. It all depends on what GetMostLikelyContextType returns.
577 const Extension* extension = 580 const Extension* extension =
578 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID( 581 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
579 extension_id); 582 extension_id);
580 583
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 listener_filter)) { 633 listener_filter)) {
631 return; 634 return;
632 } 635 }
633 636
634 int event_id = g_extension_event_id.GetNext(); 637 int event_id = g_extension_event_id.GetNext();
635 DispatchExtensionMessage(process, listener_context, extension_id, event_id, 638 DispatchExtensionMessage(process, listener_context, extension_id, event_id,
636 event->event_name, event->event_args.get(), 639 event->event_name, event->event_args.get(),
637 event->user_gesture, event->filter_info); 640 event->user_gesture, event->filter_info);
638 641
639 if (extension) { 642 if (extension) {
643 ReportEvent(event->histogram_value, extension, did_enqueue);
640 IncrementInFlightEvents(listener_context, extension, event_id, 644 IncrementInFlightEvents(listener_context, extension, event_id,
641 event->event_name); 645 event->event_name);
642 } 646 }
643 } 647 }
644 648
645 bool EventRouter::CanDispatchEventToBrowserContext( 649 bool EventRouter::CanDispatchEventToBrowserContext(
646 BrowserContext* context, 650 BrowserContext* context,
647 const Extension* extension, 651 const Extension* extension,
648 const linked_ptr<Event>& event) { 652 const linked_ptr<Event>& event) {
649 // Is this event from a different browser context than the renderer (ie, an 653 // 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(), 690 queue->AddPendingTask(context, extension->id(),
687 base::Bind(&EventRouter::DispatchPendingEvent, 691 base::Bind(&EventRouter::DispatchPendingEvent,
688 base::Unretained(this), dispatched_event)); 692 base::Unretained(this), dispatched_event));
689 return true; 693 return true;
690 } 694 }
691 695
692 return false; 696 return false;
693 } 697 }
694 698
695 // static 699 // static
696 void EventRouter::IncrementInFlightEventsOnUI(void* browser_context_id, 700 void EventRouter::DoDispatchEventToSenderBookkeepingOnUI(
697 const std::string& extension_id, 701 void* browser_context_id,
698 int event_id, 702 const std::string& extension_id,
699 const std::string& event_name) { 703 const GURL& url,
704 int event_id,
705 events::HistogramValue histogram_value,
706 const std::string& event_name) {
700 DCHECK_CURRENTLY_ON(BrowserThread::UI); 707 DCHECK_CURRENTLY_ON(BrowserThread::UI);
701 BrowserContext* browser_context = 708 BrowserContext* browser_context =
702 reinterpret_cast<BrowserContext*>(browser_context_id); 709 reinterpret_cast<BrowserContext*>(browser_context_id);
703 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context)) 710 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
704 return; 711 return;
705 EventRouter* event_router = EventRouter::Get(browser_context);
706 if (!event_router)
707 return;
708 const Extension* extension = 712 const Extension* extension =
709 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID( 713 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
710 extension_id); 714 extension_id);
711 if (!extension) 715 if (!extension)
712 return; 716 return;
717 EventRouter* event_router = EventRouter::Get(browser_context);
713 event_router->IncrementInFlightEvents(browser_context, extension, event_id, 718 event_router->IncrementInFlightEvents(browser_context, extension, event_id,
714 event_name); 719 event_name);
720 event_router->ReportEvent(histogram_value, extension,
721 false /* did_enqueue */);
715 } 722 }
716 723
717 void EventRouter::IncrementInFlightEvents(BrowserContext* context, 724 void EventRouter::IncrementInFlightEvents(BrowserContext* context,
718 const Extension* extension, 725 const Extension* extension,
719 int event_id, 726 int event_id,
720 const std::string& event_name) { 727 const std::string& event_name) {
721 // TODO(chirantan): Turn this on once crbug.com/464513 is fixed. 728 // TODO(chirantan): Turn this on once crbug.com/464513 is fixed.
722 // DCHECK_CURRENTLY_ON(BrowserThread::UI); 729 // DCHECK_CURRENTLY_ON(BrowserThread::UI);
723 730
724 // Only increment in-flight events if the lazy background page is active, 731 // 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 747 // The event ACK is routed to the background host, so this should never be
741 // NULL. 748 // NULL.
742 CHECK(host); 749 CHECK(host);
743 // TODO(mpcomplete): We should never get this message unless 750 // TODO(mpcomplete): We should never get this message unless
744 // HasLazyBackgroundPage is true. Find out why we're getting it anyway. 751 // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
745 if (host->extension() && 752 if (host->extension() &&
746 BackgroundInfo::HasLazyBackgroundPage(host->extension())) 753 BackgroundInfo::HasLazyBackgroundPage(host->extension()))
747 pm->DecrementLazyKeepaliveCount(host->extension()); 754 pm->DecrementLazyKeepaliveCount(host->extension());
748 } 755 }
749 756
757 void EventRouter::ReportEvent(events::HistogramValue histogram_value,
758 const Extension* extension,
759 bool did_enqueue) {
760 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
761
762 // TODO(kalman): UMA for dispatched event.
763 // TODO(kalman): UMA specifically for component extensions.
764
765 // Note: for these, all we know is that the extension *has* a persistent or
766 // event page, not that the event is being dispatched *to* such a page.
not at google - send to devlin 2015/08/07 20:55:03 This is new as well, I had forgotten that for even
767 //
768 // However, this is an academic distinction, since extensions with any
769 // background page have that background page running (or in the case of
770 // dormant event pages, must be started) regardless of where the event is
771 // being dispatched. Events are dispatched to a *process* not a *frame*.
772 if (BackgroundInfo::HasPersistentBackgroundPage(extension)) {
773 // TODO(kalman): UMA for dispatched event to an extension with a persistent
774 // background page.
775 } else if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
776 if (did_enqueue) {
777 // TODO(kalman): UMA for dispatched event to an extension with an event
778 // page, and the event page was woken up to do so.
779 } else {
780 // TODO(kalman): UMA for dispatched event to an extension with an event
781 // page that was already running.
782 }
783 }
784 }
785
750 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event, 786 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event,
751 ExtensionHost* host) { 787 ExtensionHost* host) {
752 if (!host) 788 if (!host)
753 return; 789 return;
754 790
755 if (listeners_.HasProcessListener(host->render_process_host(), 791 if (listeners_.HasProcessListener(host->render_process_host(),
756 host->extension()->id())) { 792 host->extension()->id())) {
757 // URL events cannot be lazy therefore can't be pending, hence the GURL(). 793 DispatchEventToProcess(host->extension()->id(), host->GetURL(),
758 DispatchEventToProcess(host->extension()->id(), GURL(), 794 host->render_process_host(), event, nullptr,
759 host->render_process_host(), event, nullptr); 795 true /* did_enqueue */);
760 } 796 }
761 } 797 }
762 798
763 void EventRouter::Observe(int type, 799 void EventRouter::Observe(int type,
764 const content::NotificationSource& source, 800 const content::NotificationSource& source,
765 const content::NotificationDetails& details) { 801 const content::NotificationDetails& details) {
766 switch (type) { 802 switch (type) {
767 case extensions::NOTIFICATION_EXTENSION_ENABLED: { 803 case extensions::NOTIFICATION_EXTENSION_ENABLED: {
768 // If the extension has a lazy background page, make sure it gets loaded 804 // If the extension has a lazy background page, make sure it gets loaded
769 // to register the events the extension is interested in. 805 // 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, 891 const std::string& extension_id,
856 const GURL& listener_url, 892 const GURL& listener_url,
857 content::BrowserContext* browser_context) 893 content::BrowserContext* browser_context)
858 : event_name(event_name), 894 : event_name(event_name),
859 extension_id(extension_id), 895 extension_id(extension_id),
860 listener_url(listener_url), 896 listener_url(listener_url),
861 browser_context(browser_context) { 897 browser_context(browser_context) {
862 } 898 }
863 899
864 } // namespace extensions 900 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698