| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef EXTENSIONS_BROWSER_EVENTS_LAZY_EVENT_DISPATCHER_H_ |
| #define EXTENSIONS_BROWSER_EVENTS_LAZY_EVENT_DISPATCHER_H_ |
| |
| #include <set> |
| #include <utility> |
| |
| #include "base/callback.h" |
| #include "extensions/browser/lazy_context_task_queue.h" |
| #include "extensions/common/extension_id.h" |
| |
| namespace base { |
| class DictionaryValue; |
| } |
| |
| namespace content { |
| class BrowserContext; |
| } |
| |
| namespace extensions { |
| class EventListener; |
| class Extension; |
| class LazyContextId; |
| struct Event; |
| |
| // Helper class for EventRouter to dispatch lazy events to lazy contexts. |
| // |
| // Manages waking up lazy contexts if they are stopped. |
| class LazyEventDispatcher { |
| public: |
| using DispatchFunction = base::RepeatingCallback<void( |
| std::unique_ptr<Event>, |
| std::unique_ptr<LazyContextTaskQueue::ContextInfo>)>; |
| |
| LazyEventDispatcher(content::BrowserContext* browser_context, |
| DispatchFunction dispatch_function); |
| ~LazyEventDispatcher(); |
| |
| // Dispatches the lazy |event| to |extension_id|. |
| // |
| // Ensures that all lazy background pages that are interested in the given |
| // event are loaded, and queues the event if the page is not ready yet. |
| void DispatchToEventPage(const Event& event, |
| const ExtensionId& extension_id, |
| const base::DictionaryValue* listener_filter); |
| // Dispatches the lazy |event| to |extension_id|'s service worker. |
| // |
| // Service workers are started if they were stopped, before dispatching the |
| // event. |
| void DispatchToServiceWorker(const Event& event, |
| const ExtensionId& extension_id, |
| const GURL& service_worker_scope, |
| const base::DictionaryValue* listener_filter); |
| |
| // Returns whether or not an event listener identical to |listener| is queued |
| // for dispatch already. |
| bool HasAlreadyDispatched(content::BrowserContext* context, |
| const EventListener* listener) const; |
| |
| private: |
| using EventPageDispatchIdentifier = |
| std::pair<const content::BrowserContext*, std::string>; |
| using ServiceWorkerDispatchIdentifier = |
| std::pair<const content::BrowserContext*, GURL>; |
| |
| void DispatchToLazyContext(const Event& event, |
| LazyContextId* dispatch_context, |
| const base::DictionaryValue* listener_filter); |
| |
| // Possibly loads given extension's background page or extension Service |
| // Worker in preparation to dispatch an event. Returns true if the event was |
| // queued for subsequent dispatch, false otherwise. |
| bool QueueEventDispatch(const Event& event, |
| const LazyContextId& dispatch_context, |
| const Extension* extension, |
| const base::DictionaryValue* listener_filter); |
| |
| bool HasAlreadyDispatchedImpl(const LazyContextId& dispatch_context) const; |
| |
| void RecordAlreadyDispatched(const LazyContextId& dispatch_context); |
| |
| content::BrowserContext* GetIncognitoContext(const Extension* extension); |
| |
| content::BrowserContext* const browser_context_; |
| DispatchFunction dispatch_function_; |
| |
| // TODO(lazyboy): Instead of keeping these two std::sets, compbine them using |
| // LazyContextId key when service worker event listeners are more common. |
| std::set<EventPageDispatchIdentifier> dispatched_ids_for_event_page_; |
| std::set<ServiceWorkerDispatchIdentifier> dispatched_ids_for_service_worker_; |
| |
| DISALLOW_COPY_AND_ASSIGN(LazyEventDispatcher); |
| }; |
| |
| } // namespace extensions |
| |
| #endif // EXTENSIONS_BROWSER_EVENTS_LAZY_EVENT_DISPATCHER_H_ |