Chromium Code Reviews| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/atomic_sequence_num.h" | 11 #include "base/atomic_sequence_num.h" |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/command_line.h" | |
| 14 #include "base/lazy_instance.h" | |
| 15 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 16 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 17 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
| 18 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 19 #include "base/values.h" | 17 #include "base/values.h" |
| 20 #include "content/public/browser/notification_service.h" | 18 #include "content/public/browser/notification_service.h" |
| 21 #include "content/public/browser/render_process_host.h" | 19 #include "content/public/browser/render_process_host.h" |
| 22 #include "extensions/browser/api_activity_monitor.h" | 20 #include "extensions/browser/api_activity_monitor.h" |
| 23 #include "extensions/browser/event_router_factory.h" | 21 #include "extensions/browser/event_router_factory.h" |
| 24 #include "extensions/browser/extension_host.h" | 22 #include "extensions/browser/extension_host.h" |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 } | 185 } |
| 188 | 186 |
| 189 void EventRouter::RegisterObserver(Observer* observer, | 187 void EventRouter::RegisterObserver(Observer* observer, |
| 190 const std::string& event_name) { | 188 const std::string& event_name) { |
| 191 // Observing sub-event names like "foo.onBar/123" is not allowed. | 189 // Observing sub-event names like "foo.onBar/123" is not allowed. |
| 192 DCHECK(event_name.find('/') == std::string::npos); | 190 DCHECK(event_name.find('/') == std::string::npos); |
| 193 observers_[event_name] = observer; | 191 observers_[event_name] = observer; |
| 194 } | 192 } |
| 195 | 193 |
| 196 void EventRouter::UnregisterObserver(Observer* observer) { | 194 void EventRouter::UnregisterObserver(Observer* observer) { |
| 197 std::vector<ObserverMap::iterator> iters_to_remove; | 195 std::vector<ObserverMap::iterator> iters_to_remove; |
|
Devlin
2017/05/20 00:49:16
It seems a shame to construct a vector just for th
Lei Zhang
2017/05/20 01:04:14
Sure.
I see people do it both ways and I don't ha
| |
| 198 for (ObserverMap::iterator iter = observers_.begin(); | 196 for (ObserverMap::iterator iter = observers_.begin(); |
| 199 iter != observers_.end(); ++iter) { | 197 iter != observers_.end(); ++iter) { |
| 200 if (iter->second == observer) | 198 if (iter->second == observer) |
| 201 iters_to_remove.push_back(iter); | 199 iters_to_remove.push_back(iter); |
| 202 } | 200 } |
| 203 for (size_t i = 0; i < iters_to_remove.size(); ++i) | 201 for (auto& iter : iters_to_remove) |
| 204 observers_.erase(iters_to_remove[i]); | 202 observers_.erase(iter); |
| 205 } | 203 } |
| 206 | 204 |
| 207 void EventRouter::OnListenerAdded(const EventListener* listener) { | 205 void EventRouter::OnListenerAdded(const EventListener* listener) { |
| 208 const EventListenerInfo details(listener->event_name(), | 206 const EventListenerInfo details(listener->event_name(), |
| 209 listener->extension_id(), | 207 listener->extension_id(), |
| 210 listener->listener_url(), | 208 listener->listener_url(), |
| 211 listener->GetBrowserContext()); | 209 listener->GetBrowserContext()); |
| 212 std::string base_event_name = GetBaseEventName(listener->event_name()); | 210 std::string base_event_name = GetBaseEventName(listener->event_name()); |
| 213 ObserverMap::iterator observer = observers_.find(base_event_name); | 211 ObserverMap::iterator observer = observers_.find(base_event_name); |
| 214 if (observer != observers_.end()) | 212 if (observer != observers_.end()) |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 | 274 |
| 277 void EventRouter::AddFilteredEventListener(const std::string& event_name, | 275 void EventRouter::AddFilteredEventListener(const std::string& event_name, |
| 278 content::RenderProcessHost* process, | 276 content::RenderProcessHost* process, |
| 279 const std::string& extension_id, | 277 const std::string& extension_id, |
| 280 const base::DictionaryValue& filter, | 278 const base::DictionaryValue& filter, |
| 281 bool add_lazy_listener) { | 279 bool add_lazy_listener) { |
| 282 listeners_.AddListener(EventListener::ForExtension( | 280 listeners_.AddListener(EventListener::ForExtension( |
| 283 event_name, extension_id, process, | 281 event_name, extension_id, process, |
| 284 std::unique_ptr<DictionaryValue>(filter.DeepCopy()))); | 282 std::unique_ptr<DictionaryValue>(filter.DeepCopy()))); |
| 285 | 283 |
| 286 if (add_lazy_listener) { | 284 if (!add_lazy_listener) |
| 287 bool added = listeners_.AddListener(EventListener::ForExtension( | 285 return; |
| 288 event_name, extension_id, NULL, | |
| 289 std::unique_ptr<DictionaryValue>(filter.DeepCopy()))); | |
| 290 | 286 |
| 291 if (added) | 287 bool added = listeners_.AddListener(EventListener::ForExtension( |
| 292 AddFilterToEvent(event_name, extension_id, &filter); | 288 event_name, extension_id, nullptr, |
| 293 } | 289 std::unique_ptr<DictionaryValue>(filter.DeepCopy()))); |
| 290 if (added) | |
| 291 AddFilterToEvent(event_name, extension_id, &filter); | |
| 294 } | 292 } |
| 295 | 293 |
| 296 void EventRouter::RemoveFilteredEventListener( | 294 void EventRouter::RemoveFilteredEventListener( |
| 297 const std::string& event_name, | 295 const std::string& event_name, |
| 298 content::RenderProcessHost* process, | 296 content::RenderProcessHost* process, |
| 299 const std::string& extension_id, | 297 const std::string& extension_id, |
| 300 const base::DictionaryValue& filter, | 298 const base::DictionaryValue& filter, |
| 301 bool remove_lazy_listener) { | 299 bool remove_lazy_listener) { |
| 302 std::unique_ptr<EventListener> listener = EventListener::ForExtension( | 300 std::unique_ptr<EventListener> listener = EventListener::ForExtension( |
| 303 event_name, extension_id, process, | 301 event_name, extension_id, process, |
| 304 std::unique_ptr<DictionaryValue>(filter.DeepCopy())); | 302 std::unique_ptr<DictionaryValue>(filter.DeepCopy())); |
| 305 | 303 |
| 306 listeners_.RemoveListener(listener.get()); | 304 listeners_.RemoveListener(listener.get()); |
| 307 | 305 |
| 308 if (remove_lazy_listener) { | 306 if (remove_lazy_listener) { |
| 309 listener->MakeLazy(); | 307 listener->MakeLazy(); |
| 310 bool removed = listeners_.RemoveListener(listener.get()); | 308 bool removed = listeners_.RemoveListener(listener.get()); |
| 311 | 309 |
| 312 if (removed) | 310 if (removed) |
| 313 RemoveFilterFromEvent(event_name, extension_id, &filter); | 311 RemoveFilterFromEvent(event_name, extension_id, &filter); |
| 314 } | 312 } |
| 315 } | 313 } |
| 316 | 314 |
| 317 bool EventRouter::HasEventListener(const std::string& event_name) { | 315 bool EventRouter::HasEventListener(const std::string& event_name) const { |
| 318 return listeners_.HasListenerForEvent(event_name); | 316 return listeners_.HasListenerForEvent(event_name); |
| 319 } | 317 } |
| 320 | 318 |
| 321 bool EventRouter::ExtensionHasEventListener(const std::string& extension_id, | 319 bool EventRouter::ExtensionHasEventListener( |
| 322 const std::string& event_name) { | 320 const std::string& extension_id, |
| 321 const std::string& event_name) const { | |
| 323 return listeners_.HasListenerForExtension(extension_id, event_name); | 322 return listeners_.HasListenerForExtension(extension_id, event_name); |
| 324 } | 323 } |
| 325 | 324 |
| 326 std::set<std::string> EventRouter::GetRegisteredEvents( | 325 std::set<std::string> EventRouter::GetRegisteredEvents( |
| 327 const std::string& extension_id) const { | 326 const std::string& extension_id) const { |
| 328 std::set<std::string> events; | 327 std::set<std::string> events; |
| 329 const ListValue* events_value = NULL; | 328 const ListValue* events_value = NULL; |
| 330 | 329 |
| 331 if (!extension_prefs_ || | 330 if (!extension_prefs_ || |
| 332 !extension_prefs_->ReadPrefAsList( | 331 !extension_prefs_->ReadPrefAsList( |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 569 | 568 |
| 570 bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent( | 569 bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent( |
| 571 BrowserContext* context, | 570 BrowserContext* context, |
| 572 const Extension* extension, | 571 const Extension* extension, |
| 573 const linked_ptr<Event>& event, | 572 const linked_ptr<Event>& event, |
| 574 const base::DictionaryValue* listener_filter) { | 573 const base::DictionaryValue* listener_filter) { |
| 575 if (!CanDispatchEventToBrowserContext(context, extension, event)) | 574 if (!CanDispatchEventToBrowserContext(context, extension, event)) |
| 576 return false; | 575 return false; |
| 577 | 576 |
| 578 LazyBackgroundTaskQueue* queue = LazyBackgroundTaskQueue::Get(context); | 577 LazyBackgroundTaskQueue* queue = LazyBackgroundTaskQueue::Get(context); |
| 579 if (queue->ShouldEnqueueTask(context, extension)) { | 578 if (!queue->ShouldEnqueueTask(context, extension)) |
| 580 linked_ptr<Event> dispatched_event(event); | 579 return false; |
| 581 | 580 |
| 582 // If there's a dispatch callback, call it now (rather than dispatch time) | 581 linked_ptr<Event> dispatched_event(event); |
| 583 // to avoid lifetime issues. Use a separate copy of the event args, so they | 582 |
| 584 // last until the event is dispatched. | 583 // If there's a dispatch callback, call it now (rather than dispatch time) |
| 585 if (!event->will_dispatch_callback.is_null()) { | 584 // to avoid lifetime issues. Use a separate copy of the event args, so they |
| 586 dispatched_event.reset(event->DeepCopy()); | 585 // last until the event is dispatched. |
| 587 if (!dispatched_event->will_dispatch_callback.Run( | 586 if (!event->will_dispatch_callback.is_null()) { |
| 588 context, extension, dispatched_event.get(), listener_filter)) { | 587 dispatched_event.reset(event->DeepCopy()); |
| 589 // The event has been canceled. | 588 if (!dispatched_event->will_dispatch_callback.Run( |
| 590 return true; | 589 context, extension, dispatched_event.get(), listener_filter)) { |
| 591 } | 590 // The event has been canceled. |
| 592 // Ensure we don't call it again at dispatch time. | 591 return true; |
| 593 dispatched_event->will_dispatch_callback.Reset(); | |
| 594 } | 592 } |
| 595 | 593 // Ensure we don't call it again at dispatch time. |
| 596 queue->AddPendingTask(context, extension->id(), | 594 dispatched_event->will_dispatch_callback.Reset(); |
| 597 base::Bind(&EventRouter::DispatchPendingEvent, | |
| 598 base::Unretained(this), dispatched_event)); | |
| 599 return true; | |
| 600 } | 595 } |
| 601 | 596 |
| 602 return false; | 597 queue->AddPendingTask(context, extension->id(), |
| 598 base::Bind(&EventRouter::DispatchPendingEvent, | |
| 599 base::Unretained(this), dispatched_event)); | |
| 600 return true; | |
| 603 } | 601 } |
| 604 | 602 |
| 605 // static | 603 // static |
| 606 void EventRouter::DoDispatchEventToSenderBookkeepingOnUI( | 604 void EventRouter::DoDispatchEventToSenderBookkeepingOnUI( |
| 607 void* browser_context_id, | 605 void* browser_context_id, |
| 608 const std::string& extension_id, | 606 const std::string& extension_id, |
| 609 int event_id, | 607 int event_id, |
| 610 events::HistogramValue histogram_value, | 608 events::HistogramValue histogram_value, |
| 611 const std::string& event_name) { | 609 const std::string& event_name) { |
| 612 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 610 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 filtered_events->SetWithoutPathExpansion(event_name, | 747 filtered_events->SetWithoutPathExpansion(event_name, |
| 750 base::WrapUnique(filter_list)); | 748 base::WrapUnique(filter_list)); |
| 751 } | 749 } |
| 752 | 750 |
| 753 filter_list->Append(filter->CreateDeepCopy()); | 751 filter_list->Append(filter->CreateDeepCopy()); |
| 754 } | 752 } |
| 755 | 753 |
| 756 void EventRouter::Observe(int type, | 754 void EventRouter::Observe(int type, |
| 757 const content::NotificationSource& source, | 755 const content::NotificationSource& source, |
| 758 const content::NotificationDetails& details) { | 756 const content::NotificationDetails& details) { |
| 759 switch (type) { | 757 DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_ENABLED, type); |
| 760 case extensions::NOTIFICATION_EXTENSION_ENABLED: { | 758 // If the extension has a lazy background page, make sure it gets loaded |
| 761 // If the extension has a lazy background page, make sure it gets loaded | 759 // to register the events the extension is interested in. |
| 762 // to register the events the extension is interested in. | 760 const Extension* extension = content::Details<const Extension>(details).ptr(); |
| 763 const Extension* extension = | 761 if (BackgroundInfo::HasLazyBackgroundPage(extension)) { |
| 764 content::Details<const Extension>(details).ptr(); | 762 LazyBackgroundTaskQueue* queue = |
| 765 if (BackgroundInfo::HasLazyBackgroundPage(extension)) { | 763 LazyBackgroundTaskQueue::Get(browser_context_); |
| 766 LazyBackgroundTaskQueue* queue = | 764 queue->AddPendingTask(browser_context_, extension->id(), |
| 767 LazyBackgroundTaskQueue::Get(browser_context_); | 765 base::Bind(&DoNothing)); |
| 768 queue->AddPendingTask(browser_context_, extension->id(), | |
| 769 base::Bind(&DoNothing)); | |
| 770 } | |
| 771 break; | |
| 772 } | |
| 773 default: | |
| 774 NOTREACHED(); | |
| 775 } | 766 } |
| 776 } | 767 } |
| 777 | 768 |
| 778 void EventRouter::OnExtensionLoaded(content::BrowserContext* browser_context, | 769 void EventRouter::OnExtensionLoaded(content::BrowserContext* browser_context, |
| 779 const Extension* extension) { | 770 const Extension* extension) { |
| 780 // Add all registered lazy listeners to our cache. | 771 // Add all registered lazy listeners to our cache. |
| 781 std::set<std::string> registered_events = | 772 std::set<std::string> registered_events = |
| 782 GetRegisteredEvents(extension->id()); | 773 GetRegisteredEvents(extension->id()); |
| 783 listeners_.LoadUnfilteredLazyListeners(extension->id(), registered_events); | 774 listeners_.LoadUnfilteredLazyListeners(extension->id(), registered_events); |
| 784 const DictionaryValue* filtered_events = GetFilteredEvents(extension->id()); | 775 const DictionaryValue* filtered_events = GetFilteredEvents(extension->id()); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 848 const std::string& extension_id, | 839 const std::string& extension_id, |
| 849 const GURL& listener_url, | 840 const GURL& listener_url, |
| 850 content::BrowserContext* browser_context) | 841 content::BrowserContext* browser_context) |
| 851 : event_name(event_name), | 842 : event_name(event_name), |
| 852 extension_id(extension_id), | 843 extension_id(extension_id), |
| 853 listener_url(listener_url), | 844 listener_url(listener_url), |
| 854 browser_context(browser_context) { | 845 browser_context(browser_context) { |
| 855 } | 846 } |
| 856 | 847 |
| 857 } // namespace extensions | 848 } // namespace extensions |
| OLD | NEW |