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

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

Issue 2940883007: Move lazy event dispatching code out of EventRouter. (Closed)
Patch Set: address comments Created 3 years, 6 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/events/lazy_event_dispatcher.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 <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/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/message_loop/message_loop.h" 14 #include "base/message_loop/message_loop.h"
15 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
16 #include "base/stl_util.h" 16 #include "base/stl_util.h"
17 #include "base/values.h" 17 #include "base/values.h"
18 #include "content/public/browser/render_process_host.h" 18 #include "content/public/browser/render_process_host.h"
19 #include "extensions/browser/api_activity_monitor.h" 19 #include "extensions/browser/api_activity_monitor.h"
20 #include "extensions/browser/event_router_factory.h" 20 #include "extensions/browser/event_router_factory.h"
21 #include "extensions/browser/events/lazy_event_dispatcher.h"
21 #include "extensions/browser/extension_host.h" 22 #include "extensions/browser/extension_host.h"
22 #include "extensions/browser/extension_prefs.h" 23 #include "extensions/browser/extension_prefs.h"
23 #include "extensions/browser/extension_registry.h" 24 #include "extensions/browser/extension_registry.h"
24 #include "extensions/browser/extension_system.h" 25 #include "extensions/browser/extension_system.h"
25 #include "extensions/browser/extensions_browser_client.h" 26 #include "extensions/browser/extensions_browser_client.h"
26 #include "extensions/browser/lazy_background_task_queue.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/constants.h"
30 #include "extensions/common/extension.h" 30 #include "extensions/common/extension.h"
31 #include "extensions/common/extension_api.h" 31 #include "extensions/common/extension_api.h"
32 #include "extensions/common/extension_messages.h" 32 #include "extensions/common/extension_messages.h"
33 #include "extensions/common/extension_urls.h" 33 #include "extensions/common/extension_urls.h"
34 #include "extensions/common/features/feature.h" 34 #include "extensions/common/features/feature.h"
35 #include "extensions/common/features/feature_provider.h" 35 #include "extensions/common/features/feature_provider.h"
36 #include "extensions/common/manifest_handlers/background_info.h" 36 #include "extensions/common/manifest_handlers/background_info.h"
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 } 133 }
134 134
135 DispatchExtensionMessage(ipc_sender, 135 DispatchExtensionMessage(ipc_sender,
136 // TODO(lazyboy): |kNonWorkerThreadId| means these 136 // TODO(lazyboy): |kNonWorkerThreadId| means these
137 // will not work for extension SW. 137 // will not work for extension SW.
138 kNonWorkerThreadId, browser_context_id, extension_id, 138 kNonWorkerThreadId, browser_context_id, extension_id,
139 event_id, event_name, event_args.get(), user_gesture, 139 event_id, event_name, event_args.get(), user_gesture,
140 info); 140 info);
141 } 141 }
142 142
143 // static.
144 bool EventRouter::CanDispatchEventToBrowserContext(BrowserContext* context,
145 const Extension* extension,
146 const Event& event) {
147 // Is this event from a different browser context than the renderer (ie, an
148 // incognito tab event sent to a normal process, or vice versa).
149 bool crosses_incognito = event.restrict_to_browser_context &&
150 context != event.restrict_to_browser_context;
151 if (!crosses_incognito)
152 return true;
153 return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(extension,
154 context);
155 }
156
143 EventRouter::EventRouter(BrowserContext* browser_context, 157 EventRouter::EventRouter(BrowserContext* browser_context,
144 ExtensionPrefs* extension_prefs) 158 ExtensionPrefs* extension_prefs)
145 : browser_context_(browser_context), 159 : browser_context_(browser_context),
146 extension_prefs_(extension_prefs), 160 extension_prefs_(extension_prefs),
147 extension_registry_observer_(this), 161 extension_registry_observer_(this),
148 listeners_(this), 162 listeners_(this),
149 lazy_event_dispatch_util_(browser_context_) { 163 lazy_event_dispatch_util_(browser_context_),
164 weak_factory_(this) {
150 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); 165 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
151 } 166 }
152 167
153 EventRouter::~EventRouter() { 168 EventRouter::~EventRouter() {
154 for (auto* process : observed_process_set_) 169 for (auto* process : observed_process_set_)
155 process->RemoveObserver(this); 170 process->RemoveObserver(this);
156 } 171 }
157 172
158 void EventRouter::AddEventListener(const std::string& event_name, 173 void EventRouter::AddEventListener(const std::string& event_name,
159 content::RenderProcessHost* process, 174 content::RenderProcessHost* process,
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 439
425 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id, 440 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
426 const linked_ptr<Event>& event) { 441 const linked_ptr<Event>& event) {
427 // We don't expect to get events from a completely different browser context. 442 // We don't expect to get events from a completely different browser context.
428 DCHECK(!event->restrict_to_browser_context || 443 DCHECK(!event->restrict_to_browser_context ||
429 ExtensionsBrowserClient::Get()->IsSameContext( 444 ExtensionsBrowserClient::Get()->IsSameContext(
430 browser_context_, event->restrict_to_browser_context)); 445 browser_context_, event->restrict_to_browser_context));
431 std::set<const EventListener*> listeners( 446 std::set<const EventListener*> listeners(
432 listeners_.GetEventListeners(*event)); 447 listeners_.GetEventListeners(*event));
433 448
434 std::set<EventDispatchIdentifier> already_dispatched; 449 LazyEventDispatcher lazy_event_dispatcher(
450 browser_context_, event,
451 base::Bind(&EventRouter::DispatchPendingEvent,
452 weak_factory_.GetWeakPtr()));
435 453
436 // We dispatch events for lazy background pages first because attempting to do 454 // We dispatch events for lazy background pages first because attempting to do
437 // so will cause those that are being suspended to cancel that suspension. 455 // so will cause those that are being suspended to cancel that suspension.
438 // As canceling a suspension entails sending an event to the affected 456 // As canceling a suspension entails sending an event to the affected
439 // background page, and as that event needs to be delivered before we dispatch 457 // background page, and as that event needs to be delivered before we dispatch
440 // the event we are dispatching here, we dispatch to the lazy listeners here 458 // the event we are dispatching here, we dispatch to the lazy listeners here
441 // first. 459 // first.
442 for (const EventListener* listener : listeners) { 460 for (const EventListener* listener : listeners) {
443 if (restrict_to_extension_id.empty() || 461 if (!restrict_to_extension_id.empty() &&
444 restrict_to_extension_id == listener->extension_id()) { 462 restrict_to_extension_id != listener->extension_id()) {
445 // TODO(lazyboy): Support lazy listeners for extension SW events. 463 continue;
446 if (listener->IsLazy() && !listener->IsForServiceWorker()) { 464 }
447 DispatchLazyEvent(listener->extension_id(), event, &already_dispatched, 465 // TODO(lazyboy): Support lazy listeners for extension SW events.
448 listener->filter()); 466 if (listener->IsLazy() && !listener->IsForServiceWorker()) {
449 } 467 lazy_event_dispatcher.DispatchToEventPage(listener->extension_id(),
468 listener->filter());
450 } 469 }
451 } 470 }
452 471
453 for (const EventListener* listener : listeners) { 472 for (const EventListener* listener : listeners) {
454 if (restrict_to_extension_id.empty() || 473 if (!restrict_to_extension_id.empty() &&
455 restrict_to_extension_id == listener->extension_id()) { 474 restrict_to_extension_id != listener->extension_id()) {
456 if (listener->process()) { 475 continue;
457 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(),
458 listener->extension_id(),
459 listener->worker_thread_id());
460 if (!base::ContainsKey(already_dispatched, dispatch_id)) {
461 DispatchEventToProcess(listener->extension_id(),
462 listener->listener_url(), listener->process(),
463 listener->worker_thread_id(), event,
464 listener->filter(), false /* did_enqueue */);
465 }
466 }
467 } 476 }
477 if (!listener->process())
478 continue;
479 if (lazy_event_dispatcher.HasAlreadyDispatched(
480 listener->process()->GetBrowserContext(), listener)) {
481 continue;
482 }
483 DispatchEventToProcess(listener->extension_id(), listener->listener_url(),
484 listener->process(), listener->worker_thread_id(),
485 event, listener->filter(), false /* did_enqueue */);
468 } 486 }
469 } 487 }
470 488
471 void EventRouter::DispatchLazyEvent(
472 const std::string& extension_id,
473 const linked_ptr<Event>& event,
474 std::set<EventDispatchIdentifier>* already_dispatched,
475 const base::DictionaryValue* listener_filter) {
476 // Check both the original and the incognito browser context to see if we
477 // should load a lazy bg page to handle the event. The latter case
478 // occurs in the case of split-mode extensions.
479 const Extension* extension =
480 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
481 extension_id);
482 if (!extension)
483 return;
484
485 if (MaybeLoadLazyBackgroundPageToDispatchEvent(browser_context_, extension,
486 event, listener_filter)) {
487 already_dispatched->insert(
488 std::make_tuple(browser_context_, extension_id, kNonWorkerThreadId));
489 }
490
491 ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get();
492 if (browser_client->HasOffTheRecordContext(browser_context_) &&
493 IncognitoInfo::IsSplitMode(extension)) {
494 BrowserContext* incognito_context =
495 browser_client->GetOffTheRecordContext(browser_context_);
496 if (MaybeLoadLazyBackgroundPageToDispatchEvent(incognito_context, extension,
497 event, listener_filter)) {
498 already_dispatched->insert(
499 std::make_tuple(incognito_context, extension_id, kNonWorkerThreadId));
500 }
501 }
502 }
503
504 void EventRouter::DispatchEventToProcess( 489 void EventRouter::DispatchEventToProcess(
505 const std::string& extension_id, 490 const std::string& extension_id,
506 const GURL& listener_url, 491 const GURL& listener_url,
507 content::RenderProcessHost* process, 492 content::RenderProcessHost* process,
508 int worker_thread_id, 493 int worker_thread_id,
509 const linked_ptr<Event>& event, 494 const linked_ptr<Event>& event,
510 const base::DictionaryValue* listener_filter, 495 const base::DictionaryValue* listener_filter,
511 bool did_enqueue) { 496 bool did_enqueue) {
512 BrowserContext* listener_context = process->GetBrowserContext(); 497 BrowserContext* listener_context = process->GetBrowserContext();
513 ProcessMap* process_map = ProcessMap::Get(listener_context); 498 ProcessMap* process_map = ProcessMap::Get(listener_context);
(...skipping 18 matching lines...) Expand all
532 // to access that URL. 517 // to access that URL.
533 if (!event->event_url.is_empty() && 518 if (!event->event_url.is_empty() &&
534 event->event_url.host() != extension->id() && // event for self is ok 519 event->event_url.host() != extension->id() && // event for self is ok
535 !extension->permissions_data() 520 !extension->permissions_data()
536 ->active_permissions() 521 ->active_permissions()
537 .HasEffectiveAccessToURL(event->event_url)) { 522 .HasEffectiveAccessToURL(event->event_url)) {
538 return; 523 return;
539 } 524 }
540 // Secondly, if the event is for incognito mode, the Extension must be 525 // Secondly, if the event is for incognito mode, the Extension must be
541 // enabled in incognito mode. 526 // enabled in incognito mode.
542 if (!CanDispatchEventToBrowserContext(listener_context, extension, event)) { 527 if (!CanDispatchEventToBrowserContext(listener_context, extension,
528 *event)) {
543 return; 529 return;
544 } 530 }
545 } 531 }
546 532
547 Feature::Context target_context = 533 Feature::Context target_context =
548 process_map->GetMostLikelyContextType(extension, process->GetID()); 534 process_map->GetMostLikelyContextType(extension, process->GetID());
549 535
550 // We shouldn't be dispatching an event to a webpage, since all such events 536 // We shouldn't be dispatching an event to a webpage, since all such events
551 // (e.g. messaging) don't go through EventRouter. 537 // (e.g. messaging) don't go through EventRouter.
552 DCHECK_NE(Feature::WEB_PAGE_CONTEXT, target_context) 538 DCHECK_NE(Feature::WEB_PAGE_CONTEXT, target_context)
(...skipping 25 matching lines...) Expand all
578 event->event_args.get(), event->user_gesture, 564 event->event_args.get(), event->user_gesture,
579 event->filter_info); 565 event->filter_info);
580 566
581 if (extension) { 567 if (extension) {
582 ReportEvent(event->histogram_value, extension, did_enqueue); 568 ReportEvent(event->histogram_value, extension, did_enqueue);
583 IncrementInFlightEvents(listener_context, extension, event_id, 569 IncrementInFlightEvents(listener_context, extension, event_id,
584 event->event_name); 570 event->event_name);
585 } 571 }
586 } 572 }
587 573
588 bool EventRouter::CanDispatchEventToBrowserContext(
589 BrowserContext* context,
590 const Extension* extension,
591 const linked_ptr<Event>& event) {
592 // Is this event from a different browser context than the renderer (ie, an
593 // incognito tab event sent to a normal process, or vice versa).
594 bool cross_incognito = event->restrict_to_browser_context &&
595 context != event->restrict_to_browser_context;
596 if (!cross_incognito)
597 return true;
598 return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
599 extension, context);
600 }
601
602 bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
603 BrowserContext* context,
604 const Extension* extension,
605 const linked_ptr<Event>& event,
606 const base::DictionaryValue* listener_filter) {
607 if (!CanDispatchEventToBrowserContext(context, extension, event))
608 return false;
609
610 LazyBackgroundTaskQueue* queue = LazyBackgroundTaskQueue::Get(context);
611 if (!queue->ShouldEnqueueTask(context, extension))
612 return false;
613
614 linked_ptr<Event> dispatched_event(event);
615
616 // If there's a dispatch callback, call it now (rather than dispatch time)
617 // to avoid lifetime issues. Use a separate copy of the event args, so they
618 // last until the event is dispatched.
619 if (!event->will_dispatch_callback.is_null()) {
620 dispatched_event.reset(event->DeepCopy());
621 if (!dispatched_event->will_dispatch_callback.Run(
622 context, extension, dispatched_event.get(), listener_filter)) {
623 // The event has been canceled.
624 return true;
625 }
626 // Ensure we don't call it again at dispatch time.
627 dispatched_event->will_dispatch_callback.Reset();
628 }
629
630 queue->AddPendingTask(context, extension->id(),
631 base::Bind(&EventRouter::DispatchPendingEvent,
632 base::Unretained(this), dispatched_event));
633 return true;
634 }
635
636 // static 574 // static
637 void EventRouter::DoDispatchEventToSenderBookkeepingOnUI( 575 void EventRouter::DoDispatchEventToSenderBookkeepingOnUI(
638 void* browser_context_id, 576 void* browser_context_id,
639 const std::string& extension_id, 577 const std::string& extension_id,
640 int event_id, 578 int event_id,
641 events::HistogramValue histogram_value, 579 events::HistogramValue histogram_value,
642 const std::string& event_name) { 580 const std::string& event_name) {
643 DCHECK_CURRENTLY_ON(BrowserThread::UI); 581 DCHECK_CURRENTLY_ON(BrowserThread::UI);
644 BrowserContext* browser_context = 582 BrowserContext* browser_context =
645 reinterpret_cast<BrowserContext*>(browser_context_id); 583 reinterpret_cast<BrowserContext*>(browser_context_id);
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
907 const std::string& extension_id, 845 const std::string& extension_id,
908 const GURL& listener_url, 846 const GURL& listener_url,
909 content::BrowserContext* browser_context) 847 content::BrowserContext* browser_context)
910 : event_name(event_name), 848 : event_name(event_name),
911 extension_id(extension_id), 849 extension_id(extension_id),
912 listener_url(listener_url), 850 listener_url(listener_url),
913 browser_context(browser_context) { 851 browser_context(browser_context) {
914 } 852 }
915 853
916 } // namespace extensions 854 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/event_router.h ('k') | extensions/browser/events/lazy_event_dispatcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698