OLD | NEW |
---|---|
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 Loading... | |
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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
516 it != listeners.end(); it++) { | 521 it != listeners.end(); it++) { |
517 const EventListener* listener = *it; | 522 const EventListener* listener = *it; |
518 if (restrict_to_extension_id.empty() || | 523 if (restrict_to_extension_id.empty() || |
519 restrict_to_extension_id == listener->extension_id()) { | 524 restrict_to_extension_id == listener->extension_id()) { |
520 if (listener->process()) { | 525 if (listener->process()) { |
521 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(), | 526 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(), |
522 listener->extension_id()); | 527 listener->extension_id()); |
523 if (!ContainsKey(already_dispatched, dispatch_id)) { | 528 if (!ContainsKey(already_dispatched, dispatch_id)) { |
524 DispatchEventToProcess(listener->extension_id(), | 529 DispatchEventToProcess(listener->extension_id(), |
525 listener->listener_url(), listener->process(), | 530 listener->listener_url(), listener->process(), |
526 event, listener->filter()); | 531 event, listener->filter(), false); |
Devlin
2015/08/05 21:34:09
there are a few more of the anonymous bools than I
not at google - send to devlin
2015/08/07 20:55:03
Sure.
| |
527 } | 532 } |
528 } | 533 } |
529 } | 534 } |
530 } | 535 } |
531 } | 536 } |
532 | 537 |
533 void EventRouter::DispatchLazyEvent( | 538 void EventRouter::DispatchLazyEvent( |
534 const std::string& extension_id, | 539 const std::string& extension_id, |
535 const linked_ptr<Event>& event, | 540 const linked_ptr<Event>& event, |
536 std::set<EventDispatchIdentifier>* already_dispatched, | 541 std::set<EventDispatchIdentifier>* already_dispatched, |
(...skipping 23 matching lines...) Expand all Loading... | |
560 std::make_pair(incognito_context, extension_id)); | 565 std::make_pair(incognito_context, extension_id)); |
561 } | 566 } |
562 } | 567 } |
563 } | 568 } |
564 | 569 |
565 void EventRouter::DispatchEventToProcess( | 570 void EventRouter::DispatchEventToProcess( |
566 const std::string& extension_id, | 571 const std::string& extension_id, |
567 const GURL& listener_url, | 572 const GURL& listener_url, |
568 content::RenderProcessHost* process, | 573 content::RenderProcessHost* process, |
569 const linked_ptr<Event>& event, | 574 const linked_ptr<Event>& event, |
570 const base::DictionaryValue* listener_filter) { | 575 const base::DictionaryValue* listener_filter, |
576 bool did_enqueue) { | |
571 BrowserContext* listener_context = process->GetBrowserContext(); | 577 BrowserContext* listener_context = process->GetBrowserContext(); |
572 ProcessMap* process_map = ProcessMap::Get(listener_context); | 578 ProcessMap* process_map = ProcessMap::Get(listener_context); |
573 | 579 |
574 // NOTE: |extension| being NULL does not necessarily imply that this event | 580 // 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 | 581 // shouldn't be dispatched. Events can be dispatched to WebUI and webviews as |
576 // well. It all depends on what GetMostLikelyContextType returns. | 582 // well. It all depends on what GetMostLikelyContextType returns. |
577 const Extension* extension = | 583 const Extension* extension = |
578 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID( | 584 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID( |
579 extension_id); | 585 extension_id); |
580 | 586 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
628 !event->will_dispatch_callback.Run(listener_context, extension, | 634 !event->will_dispatch_callback.Run(listener_context, extension, |
629 event->event_args.get(), | 635 event->event_args.get(), |
630 listener_filter)) { | 636 listener_filter)) { |
631 return; | 637 return; |
632 } | 638 } |
633 | 639 |
634 int event_id = g_extension_event_id.GetNext(); | 640 int event_id = g_extension_event_id.GetNext(); |
635 DispatchExtensionMessage(process, listener_context, extension_id, event_id, | 641 DispatchExtensionMessage(process, listener_context, extension_id, event_id, |
636 event->event_name, event->event_args.get(), | 642 event->event_name, event->event_args.get(), |
637 event->user_gesture, event->filter_info); | 643 event->user_gesture, event->filter_info); |
644 ReportEvent(event->histogram_value, listener_url, did_enqueue); | |
638 | 645 |
639 if (extension) { | 646 if (extension) { |
640 IncrementInFlightEvents(listener_context, extension, event_id, | 647 IncrementInFlightEvents(listener_context, extension, event_id, |
641 event->event_name); | 648 event->event_name); |
642 } | 649 } |
643 } | 650 } |
644 | 651 |
645 bool EventRouter::CanDispatchEventToBrowserContext( | 652 bool EventRouter::CanDispatchEventToBrowserContext( |
646 BrowserContext* context, | 653 BrowserContext* context, |
647 const Extension* extension, | 654 const Extension* extension, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 queue->AddPendingTask(context, extension->id(), | 693 queue->AddPendingTask(context, extension->id(), |
687 base::Bind(&EventRouter::DispatchPendingEvent, | 694 base::Bind(&EventRouter::DispatchPendingEvent, |
688 base::Unretained(this), dispatched_event)); | 695 base::Unretained(this), dispatched_event)); |
689 return true; | 696 return true; |
690 } | 697 } |
691 | 698 |
692 return false; | 699 return false; |
693 } | 700 } |
694 | 701 |
695 // static | 702 // static |
696 void EventRouter::IncrementInFlightEventsOnUI(void* browser_context_id, | 703 void EventRouter::DoDispatchEventToSenderBookkeepingOnUI( |
697 const std::string& extension_id, | 704 void* browser_context_id, |
698 int event_id, | 705 const std::string& extension_id, |
699 const std::string& event_name) { | 706 const GURL& url, |
707 int event_id, | |
708 events::HistogramValue histogram_value, | |
709 const std::string& event_name) { | |
700 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 710 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
701 BrowserContext* browser_context = | 711 BrowserContext* browser_context = |
702 reinterpret_cast<BrowserContext*>(browser_context_id); | 712 reinterpret_cast<BrowserContext*>(browser_context_id); |
703 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context)) | 713 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context)) |
704 return; | 714 return; |
705 EventRouter* event_router = EventRouter::Get(browser_context); | |
706 if (!event_router) | |
707 return; | |
708 const Extension* extension = | 715 const Extension* extension = |
709 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID( | 716 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID( |
710 extension_id); | 717 extension_id); |
711 if (!extension) | 718 if (!extension) |
712 return; | 719 return; |
720 EventRouter* event_router = EventRouter::Get(browser_context); | |
713 event_router->IncrementInFlightEvents(browser_context, extension, event_id, | 721 event_router->IncrementInFlightEvents(browser_context, extension, event_id, |
714 event_name); | 722 event_name); |
723 event_router->ReportEvent(histogram_value, url, false); | |
715 } | 724 } |
716 | 725 |
717 void EventRouter::IncrementInFlightEvents(BrowserContext* context, | 726 void EventRouter::IncrementInFlightEvents(BrowserContext* context, |
718 const Extension* extension, | 727 const Extension* extension, |
719 int event_id, | 728 int event_id, |
720 const std::string& event_name) { | 729 const std::string& event_name) { |
721 // TODO(chirantan): Turn this on once crbug.com/464513 is fixed. | 730 // TODO(chirantan): Turn this on once crbug.com/464513 is fixed. |
722 // DCHECK_CURRENTLY_ON(BrowserThread::UI); | 731 // DCHECK_CURRENTLY_ON(BrowserThread::UI); |
723 | 732 |
724 // Only increment in-flight events if the lazy background page is active, | 733 // Only increment in-flight events if the lazy background page is active, |
(...skipping 15 matching lines...) Expand all Loading... | |
740 // The event ACK is routed to the background host, so this should never be | 749 // The event ACK is routed to the background host, so this should never be |
741 // NULL. | 750 // NULL. |
742 CHECK(host); | 751 CHECK(host); |
743 // TODO(mpcomplete): We should never get this message unless | 752 // TODO(mpcomplete): We should never get this message unless |
744 // HasLazyBackgroundPage is true. Find out why we're getting it anyway. | 753 // HasLazyBackgroundPage is true. Find out why we're getting it anyway. |
745 if (host->extension() && | 754 if (host->extension() && |
746 BackgroundInfo::HasLazyBackgroundPage(host->extension())) | 755 BackgroundInfo::HasLazyBackgroundPage(host->extension())) |
747 pm->DecrementLazyKeepaliveCount(host->extension()); | 756 pm->DecrementLazyKeepaliveCount(host->extension()); |
748 } | 757 } |
749 | 758 |
759 void EventRouter::ReportEvent(events::HistogramValue histogram_value, | |
760 const GURL& url, | |
761 bool did_enqueue) { | |
762 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
763 | |
764 // At this point, we're only interested in reporting events for extensions. | |
765 if (!url.SchemeIs(kExtensionScheme)) | |
Devlin
2015/08/05 21:34:09
Doesn't this mean we won't log any events for mess
not at google - send to devlin
2015/08/07 20:55:03
The URL was the target URL which assuming messagin
| |
766 return; | |
767 | |
768 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); | |
769 const Extension* extension = | |
770 registry->enabled_extensions().GetExtensionOrAppByURL(url); | |
771 if (!extension) { | |
772 NOTREACHED() << "Reporting event for non-existent extension at " << url; | |
Devlin
2015/08/05 21:34:09
Doing a NOTREACHED(); return; is typically a disco
not at google - send to devlin
2015/08/07 20:55:03
Deliberate choice - I don't trust call sites, espe
| |
773 return; | |
774 } | |
775 | |
776 // TODO(kalman): UMA for dispatched event. | |
777 // TODO(kalman): UMA specifically for component extensions. | |
not at google - send to devlin
2015/08/05 20:23:43
I will add the UMA_HISTOGRAM_ENUMERATION calls in
| |
778 | |
779 switch (GetExtensionPageType(extension, url, did_enqueue)) { | |
780 case EXTENSION_PAGE_NONE: | |
781 break; | |
782 case EXTENSION_PAGE_VIEW: | |
783 // TODO(kalman): UMA for dispatched event to view. | |
784 break; | |
785 case EXTENSION_PAGE_PERSISTENT_BACKGROUND: | |
786 // TODO(kalman): UMA for dispatched event to persistent background page. | |
787 break; | |
788 case EXTENSION_PAGE_DORMANT_EVENT: | |
789 // TODO(kalman): UMA for dispatched event that woke up event page. | |
790 break; | |
791 case EXTENSION_PAGE_AWAKE_EVENT: | |
792 // TODO(kalman): UMA for dispatched event to awake up event page. | |
793 break; | |
794 } | |
795 } | |
796 | |
797 EventRouter::ExtensionPageType EventRouter::GetExtensionPageType( | |
798 const Extension* extension, | |
799 const GURL& url, | |
800 bool did_enqueue) { | |
801 if (!extension) | |
Devlin
2015/08/05 21:34:09
When could this happen?
not at google - send to devlin
2015/08/07 20:55:03
In a previous version of the patch, I guess - and
| |
802 return EXTENSION_PAGE_NONE; | |
803 if (url == BackgroundInfo::GetBackgroundURL(extension)) { | |
804 if (BackgroundInfo::HasPersistentBackgroundPage(extension)) | |
805 return EXTENSION_PAGE_PERSISTENT_BACKGROUND; | |
806 if (BackgroundInfo::HasLazyBackgroundPage(extension)) | |
807 return did_enqueue ? EXTENSION_PAGE_DORMANT_EVENT | |
808 : EXTENSION_PAGE_AWAKE_EVENT; | |
809 } | |
810 return EXTENSION_PAGE_VIEW; | |
811 } | |
812 | |
750 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event, | 813 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event, |
751 ExtensionHost* host) { | 814 ExtensionHost* host) { |
752 if (!host) | 815 if (!host) |
753 return; | 816 return; |
754 | 817 |
755 if (listeners_.HasProcessListener(host->render_process_host(), | 818 if (listeners_.HasProcessListener(host->render_process_host(), |
756 host->extension()->id())) { | 819 host->extension()->id())) { |
757 // URL events cannot be lazy therefore can't be pending, hence the GURL(). | 820 // URL events cannot be lazy therefore can't be pending, hence the GURL(). |
758 DispatchEventToProcess(host->extension()->id(), GURL(), | 821 DispatchEventToProcess(host->extension()->id(), GURL(), |
759 host->render_process_host(), event, nullptr); | 822 host->render_process_host(), event, nullptr, true); |
760 } | 823 } |
761 } | 824 } |
762 | 825 |
763 void EventRouter::Observe(int type, | 826 void EventRouter::Observe(int type, |
764 const content::NotificationSource& source, | 827 const content::NotificationSource& source, |
765 const content::NotificationDetails& details) { | 828 const content::NotificationDetails& details) { |
766 switch (type) { | 829 switch (type) { |
767 case extensions::NOTIFICATION_EXTENSION_ENABLED: { | 830 case extensions::NOTIFICATION_EXTENSION_ENABLED: { |
768 // If the extension has a lazy background page, make sure it gets loaded | 831 // If the extension has a lazy background page, make sure it gets loaded |
769 // to register the events the extension is interested in. | 832 // to register the events the extension is interested in. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
855 const std::string& extension_id, | 918 const std::string& extension_id, |
856 const GURL& listener_url, | 919 const GURL& listener_url, |
857 content::BrowserContext* browser_context) | 920 content::BrowserContext* browser_context) |
858 : event_name(event_name), | 921 : event_name(event_name), |
859 extension_id(extension_id), | 922 extension_id(extension_id), |
860 listener_url(listener_url), | 923 listener_url(listener_url), |
861 browser_context(browser_context) { | 924 browser_context(browser_context) { |
862 } | 925 } |
863 | 926 |
864 } // namespace extensions | 927 } // namespace extensions |
OLD | NEW |