blob: e09ee607797f59c7cf8d15a21c5756322ef2129c [file] [log] [blame]
// 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_