#ifndef EXTENSIONS_BROWSER_EVENTS_EVENT_DISPATCH_HELPER_H_
#define EXTENSIONS_BROWSER_EVENTS_EVENT_DISPATCH_HELPER_H_
#include <set>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/values.h"
#include "extensions/browser/lazy_context_id.h"
#include "extensions/browser/lazy_context_task_queue.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/mojom/context_type.mojom.h"
namespace content {
class BrowserContext;
class RenderProcessHost;
}
namespace extensions {
class EventListener;
class EventListenerMap;
class Extension;
class ExtensionRegistry;
struct Event;
struct ActiveContextId {
raw_ptr<content::RenderProcessHost> render_process;
int worker_thread_id;
ExtensionId extension_id;
raw_ptr<content::BrowserContext> browser_context;
GURL listener_url;
auto operator<=>(const ActiveContextId&) const = default;
};
class EventDispatchHelper {
public:
using DispatchFunction = base::RepeatingCallback<void(
std::unique_ptr<Event>,
std::unique_ptr<LazyContextTaskQueue::ContextInfo>)>;
using DispatchToProcessFunction =
base::RepeatingCallback<void(const ExtensionId& extension_id,
const GURL& listener_url,
content::RenderProcessHost* process,
int64_t service_worker_version_id,
int worker_thread_id,
std::unique_ptr<Event> event,
bool did_enqueue)>;
EventDispatchHelper(const EventDispatchHelper&) = delete;
EventDispatchHelper& operator=(const EventDispatchHelper&) = delete;
static void DispatchEvent(
content::BrowserContext& browser_context,
EventListenerMap& listeners,
DispatchFunction dispatch_function,
DispatchToProcessFunction dispatch_to_process_function,
const ExtensionId& restrict_to_extension_id,
const GURL& restrict_to_url,
std::unique_ptr<Event> event);
static bool CheckFeatureAvailability(
const Event& event,
const Extension* extension,
const GURL& listener_url,
content::RenderProcessHost& process,
content::BrowserContext& listener_context,
mojom::ContextType target_context_type);
private:
EventDispatchHelper(const ExtensionRegistry& extension_registry,
content::BrowserContext& browser_context,
EventListenerMap& listeners,
DispatchFunction dispatch_function,
DispatchToProcessFunction dispatch_to_process_function);
~EventDispatchHelper();
void DispatchEventImpl(const ExtensionId& restrict_to_extension_id,
const GURL& restrict_to_url,
std::unique_ptr<Event> event);
void DispatchEventToLazyListener(const ExtensionId& restrict_to_extension_id,
const GURL& restrict_to_url,
Event& event,
const EventListener* listener);
void DispatchEventToActiveListener(
const ExtensionId& restrict_to_extension_id,
const GURL& restrict_to_url,
const Event& event,
const EventListener* listener);
void TryQueueEventForLazyListener(Event& event,
const LazyContextId& dispatch_context,
const base::Value::Dict* listener_filter);
bool TryQueueEventDispatch(Event& event,
const LazyContextId& dispatch_context,
const Extension* extension,
const base::Value::Dict* listener_filter);
std::unique_ptr<Event> CreateEventForDispatch(
const Event& event,
const base::Value::Dict* listener_filter,
const Extension* extension,
content::BrowserContext& listener_context,
mojom::ContextType target_context_type,
bool* dispatch_separate_event_out);
void RecordAlreadyQueued(const LazyContextId& dispatch_context);
bool IsAlreadyQueued(const LazyContextId& dispatch_context) const;
bool ListenerMeetsRestrictions(const EventListener* listener,
const ExtensionId& restrict_to_extension_id,
const GURL& restrict_to_url) const;
content::BrowserContext* GetIncognitoContextIfAccessible(
const ExtensionId& extension_id) const;
content::BrowserContext* GetIncognitoContext() const;
LazyContextId LazyContextIdForListener(
const EventListener* listener,
content::BrowserContext& browser_context) const;
const Extension* GetExtension(const ExtensionId& extension_id) const;
const raw_ref<const ExtensionRegistry> extension_registry_;
const raw_ref<content::BrowserContext> browser_context_;
const raw_ref<EventListenerMap> listeners_;
DispatchFunction dispatch_function_;
DispatchToProcessFunction dispatch_to_process_function_;
std::set<LazyContextId> dispatched_ids_;
std::set<ActiveContextId> dispatched_active_ids_;
std::set<LazyContextId> contexts_pending_dispatch_;
};
}
#endif