12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331 |
- // Copyright (c) 2012 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.
- #include "extensions/browser/event_router.h"
- #include <stddef.h>
- #include <algorithm>
- #include <utility>
- #include "base/atomic_sequence_num.h"
- #include "base/bind.h"
- #include "base/metrics/histogram_functions.h"
- #include "base/metrics/histogram_macros.h"
- #include "base/observer_list.h"
- #include "base/ranges/algorithm.h"
- #include "base/values.h"
- #include "components/crx_file/id_util.h"
- #include "content/public/browser/browser_context.h"
- #include "content/public/browser/browser_task_traits.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/browser/render_process_host.h"
- #include "content/public/browser/service_worker_context.h"
- #include "content/public/browser/storage_partition.h"
- #include "extensions/browser/api_activity_monitor.h"
- #include "extensions/browser/event_router_factory.h"
- #include "extensions/browser/events/lazy_event_dispatcher.h"
- #include "extensions/browser/extension_host.h"
- #include "extensions/browser/extension_prefs.h"
- #include "extensions/browser/extension_system.h"
- #include "extensions/browser/extension_util.h"
- #include "extensions/browser/extensions_browser_client.h"
- #include "extensions/browser/process_manager.h"
- #include "extensions/browser/process_map.h"
- #include "extensions/common/constants.h"
- #include "extensions/common/extension.h"
- #include "extensions/common/extension_api.h"
- #include "extensions/common/extension_messages.h"
- #include "extensions/common/extension_urls.h"
- #include "extensions/common/features/feature.h"
- #include "extensions/common/features/feature_provider.h"
- #include "extensions/common/manifest_handlers/background_info.h"
- #include "extensions/common/manifest_handlers/incognito_info.h"
- #include "extensions/common/mojom/event_dispatcher.mojom.h"
- #include "extensions/common/permissions/permissions_data.h"
- #include "ipc/ipc_channel_proxy.h"
- using base::DictionaryValue;
- using base::ListValue;
- using content::BrowserContext;
- using content::BrowserThread;
- using content::RenderProcessHost;
- namespace extensions {
- namespace {
- // A dictionary of event names to lists of filters that this extension has
- // registered from its lazy background page.
- const char kFilteredEvents[] = "filtered_events";
- // Similar to |kFilteredEvents|, but applies to extension service worker events.
- const char kFilteredServiceWorkerEvents[] = "filtered_service_worker_events";
- // A message when mojom::EventRouter::AddListenerForMainThread() is called with
- // an invalid param.
- constexpr char kAddEventListenerWithInvalidParam[] =
- "Tried to add an event listener without a valid extension ID nor listener "
- "URL";
- // A message when mojom::EventRouter::AddListenerForServiceWorker() is called
- // with an invalid worker scope URL.
- constexpr char kAddEventListenerWithInvalidWorkerScopeURL[] =
- "Tried to add an event listener for a service worker without a valid "
- "worker scope URL.";
- // A message when mojom::EventRouter::AddListenerForServiceWorker() is called
- // with an invalid extension ID.
- constexpr char kAddEventListenerWithInvalidExtensionID[] =
- "Tried to add an event listener for a service worker without a valid "
- "extension ID.";
- // A message when mojom::EventRouter::RemoveListenerForMainThread() is called
- // with an invalid param.
- constexpr char kRemoveEventListenerWithInvalidParam[] =
- "Tried to remove an event listener without a valid extension ID nor "
- "listener URL";
- // A message when mojom::EventRouter::RemoveListenerForServiceWorker() is called
- // with an invalid worker scope URL.
- constexpr char kRemoveEventListenerWithInvalidWorkerScopeURL[] =
- "Tried to remove an event listener for a service worker without a valid "
- "worker scope URL.";
- // A message when mojom::EventRouter::RemoveListenerForServiceWorker() is called
- // with an invalid extension ID.
- constexpr char kRemoveEventListenerWithInvalidExtensionID[] =
- "Tried to remove an event listener for a service worker without a valid "
- "extension ID.";
- // Sends a notification about an event to the API activity monitor and the
- // ExtensionHost for |extension_id| on the UI thread. Can be called from any
- // thread.
- void NotifyEventDispatched(content::BrowserContext* browser_context,
- const std::string& extension_id,
- const std::string& event_name,
- const base::Value::List& args) {
- // Notify the ApiActivityMonitor about the event dispatch.
- activity_monitor::OnApiEventDispatched(browser_context, extension_id,
- event_name, args);
- }
- LazyContextId LazyContextIdForBrowserContext(BrowserContext* browser_context,
- const EventListener* listener) {
- auto* registry = ExtensionRegistry::Get(browser_context);
- DCHECK(registry);
- const Extension* extension =
- registry->enabled_extensions().GetByID(listener->extension_id());
- const bool is_service_worker_based_extension =
- extension && BackgroundInfo::IsServiceWorkerBased(extension);
- // Note: It is possible that the prefs' listener->is_for_service_worker() and
- // its extension background type do not agree. This happens when one changes
- // extension's manifest, typically during unpacked extension development.
- // Fallback to non-Service worker based LazyContextId to avoid surprising
- // ServiceWorkerTaskQueue (and crashing), see https://crbug.com/1239752 for
- // details.
- // TODO(lazyboy): Clean these inconsistencies across different types of event
- // listener and their corresponding background types.
- if (is_service_worker_based_extension && listener->is_for_service_worker()) {
- return LazyContextId(browser_context, listener->extension_id(),
- listener->listener_url());
- }
- return LazyContextId(browser_context, listener->extension_id());
- }
- LazyContextId LazyContextIdForListener(const EventListener* listener) {
- return LazyContextIdForBrowserContext(
- listener->process()->GetBrowserContext(), listener);
- }
- // A global identifier used to distinguish extension events.
- base::AtomicSequenceNumber g_extension_event_id;
- } // namespace
- const char EventRouter::kRegisteredLazyEvents[] = "events";
- const char EventRouter::kRegisteredServiceWorkerEvents[] =
- "serviceworkerevents";
- // static
- void EventRouter::DispatchExtensionMessage(
- content::RenderProcessHost* rph,
- int worker_thread_id,
- content::BrowserContext* browser_context,
- const std::string& extension_id,
- int event_id,
- const std::string& event_name,
- base::Value::List event_args,
- UserGestureState user_gesture,
- mojom::EventFilteringInfoPtr info) {
- NotifyEventDispatched(browser_context, extension_id, event_name, event_args);
- auto params = mojom::DispatchEventParams::New();
- params->worker_thread_id = worker_thread_id;
- params->extension_id = extension_id;
- params->event_name = event_name;
- params->event_id = event_id;
- params->is_user_gesture = user_gesture == USER_GESTURE_ENABLED;
- params->filtering_info = std::move(info);
- Get(browser_context)
- ->RouteDispatchEvent(rph, std::move(params), std::move(event_args));
- }
- void EventRouter::RouteDispatchEvent(content::RenderProcessHost* rph,
- mojom::DispatchEventParamsPtr params,
- base::Value::List event_args) {
- // TODO(crbug.com/1302000) Add bindings for worker threads to be directly
- // channel-associated.
- mojo::AssociatedRemote<mojom::EventDispatcher>& dispatcher =
- rph_dispatcher_map_[rph];
- if (!dispatcher.is_bound()) {
- IPC::ChannelProxy* channel = rph->GetChannel();
- if (!channel) {
- return;
- }
- channel->GetRemoteAssociatedInterface(
- dispatcher.BindNewEndpointAndPassReceiver());
- }
- dispatcher->DispatchEvent(std::move(params), std::move(event_args));
- }
- // static
- EventRouter* EventRouter::Get(content::BrowserContext* browser_context) {
- return EventRouterFactory::GetForBrowserContext(browser_context);
- }
- // static
- std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
- size_t slash_sep = full_event_name.find('/');
- return full_event_name.substr(0, slash_sep);
- }
- // static
- void EventRouter::DispatchEventToSender(
- content::RenderProcessHost* rph,
- content::BrowserContext* browser_context,
- const std::string& extension_id,
- events::HistogramValue histogram_value,
- const std::string& event_name,
- int render_process_id,
- int worker_thread_id,
- int64_t service_worker_version_id,
- base::Value::List event_args,
- mojom::EventFilteringInfoPtr info) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- int event_id = g_extension_event_id.GetNext();
- DoDispatchEventToSenderBookkeeping(
- browser_context, extension_id, event_id, render_process_id,
- service_worker_version_id, histogram_value, event_name);
- DispatchExtensionMessage(rph, worker_thread_id, browser_context, extension_id,
- event_id, event_name, std::move(event_args),
- UserGestureState::USER_GESTURE_UNKNOWN,
- std::move(info));
- }
- // static.
- bool EventRouter::CanDispatchEventToBrowserContext(BrowserContext* context,
- const Extension* extension,
- const Event& event) {
- // Is this event from a different browser context than the renderer (ie, an
- // incognito tab event sent to a normal process, or vice versa).
- bool crosses_incognito = event.restrict_to_browser_context &&
- context != event.restrict_to_browser_context;
- if (!crosses_incognito)
- return true;
- return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(extension,
- context);
- }
- // static
- void EventRouter::BindForRenderer(
- int render_process_id,
- mojo::PendingAssociatedReceiver<mojom::EventRouter> receiver) {
- auto* host = RenderProcessHost::FromID(render_process_id);
- if (!host)
- return;
- EventRouter* event_router = EventRouter::Get(host->GetBrowserContext());
- event_router->receivers_.Add(event_router, std::move(receiver),
- render_process_id);
- }
- EventRouter::EventRouter(BrowserContext* browser_context,
- ExtensionPrefs* extension_prefs)
- : browser_context_(browser_context),
- extension_prefs_(extension_prefs),
- lazy_event_dispatch_util_(browser_context_) {
- extension_registry_observation_.Observe(
- ExtensionRegistry::Get(browser_context_));
- }
- EventRouter::~EventRouter() {
- for (auto* process : observed_process_set_)
- process->RemoveObserver(this);
- }
- void EventRouter::AddListenerForMainThread(mojom::EventListenerParamPtr param,
- const std::string& event_name) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto* process = RenderProcessHost::FromID(receivers_.current_context());
- if (!process)
- return;
- if (param->is_extension_id() &&
- crx_file::id_util::IdIsValid(param->get_extension_id())) {
- AddEventListener(event_name, process, param->get_extension_id());
- } else if (param->is_listener_url() && param->get_listener_url().is_valid()) {
- AddEventListenerForURL(event_name, process, param->get_listener_url());
- } else {
- mojo::ReportBadMessage(kAddEventListenerWithInvalidParam);
- }
- }
- void EventRouter::AddListenerForServiceWorker(const std::string& extension_id,
- const GURL& worker_scope_url,
- const std::string& event_name,
- int64_t service_worker_version_id,
- int32_t worker_thread_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto* process = RenderProcessHost::FromID(receivers_.current_context());
- if (!process)
- return;
- if (crx_file::id_util::IdIsValid(extension_id)) {
- if (!worker_scope_url.is_valid()) {
- mojo::ReportBadMessage(kAddEventListenerWithInvalidWorkerScopeURL);
- return;
- }
- AddServiceWorkerEventListener(event_name, process, extension_id,
- worker_scope_url, service_worker_version_id,
- worker_thread_id);
- } else {
- mojo::ReportBadMessage(kAddEventListenerWithInvalidExtensionID);
- }
- }
- void EventRouter::AddLazyListenerForMainThread(const std::string& extension_id,
- const std::string& event_name) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- AddLazyEventListener(event_name, extension_id);
- }
- void EventRouter::AddLazyListenerForServiceWorker(
- const std::string& extension_id,
- const GURL& worker_scope_url,
- const std::string& event_name) {
- std::unique_ptr<EventListener> listener =
- EventListener::ForExtensionServiceWorker(
- event_name, extension_id, nullptr, worker_scope_url,
- // Lazy listener, without worker version id and thread id.
- blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId, nullptr);
- AddLazyEventListenerImpl(std::move(listener),
- RegisteredEventType::kServiceWorker);
- }
- void EventRouter::AddFilteredListenerForMainThread(
- mojom::EventListenerParamPtr param,
- const std::string& event_name,
- base::Value filter,
- bool add_lazy_listener) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto* process = RenderProcessHost::FromID(receivers_.current_context());
- if (!process)
- return;
- AddFilteredEventListener(event_name, process, std::move(param), absl::nullopt,
- base::Value::AsDictionaryValue(filter),
- add_lazy_listener);
- }
- void EventRouter::AddFilteredListenerForServiceWorker(
- const std::string& extension_id,
- const GURL& worker_scope_url,
- const std::string& event_name,
- int64_t service_worker_version_id,
- int32_t worker_thread_id,
- base::Value filter,
- bool add_lazy_listener) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto* process = RenderProcessHost::FromID(receivers_.current_context());
- if (!process)
- return;
- ServiceWorkerIdentifier sw_identifier;
- sw_identifier.scope = worker_scope_url;
- sw_identifier.thread_id = worker_thread_id;
- sw_identifier.version_id = service_worker_version_id;
- AddFilteredEventListener(
- event_name, process,
- mojom::EventListenerParam::NewExtensionId(extension_id), sw_identifier,
- base::Value::AsDictionaryValue(filter), add_lazy_listener);
- }
- void EventRouter::RemoveListenerForMainThread(
- mojom::EventListenerParamPtr param,
- const std::string& event_name) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto* process = RenderProcessHost::FromID(receivers_.current_context());
- if (!process)
- return;
- if (param->is_extension_id() &&
- crx_file::id_util::IdIsValid(param->get_extension_id())) {
- RemoveEventListener(event_name, process, param->get_extension_id());
- } else if (param->is_listener_url() && param->get_listener_url().is_valid()) {
- RemoveEventListenerForURL(event_name, process, param->get_listener_url());
- } else {
- mojo::ReportBadMessage(kRemoveEventListenerWithInvalidParam);
- }
- }
- void EventRouter::RemoveListenerForServiceWorker(
- const std::string& extension_id,
- const GURL& worker_scope_url,
- const std::string& event_name,
- int64_t service_worker_version_id,
- int worker_thread_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto* process = RenderProcessHost::FromID(receivers_.current_context());
- if (!process)
- return;
- if (crx_file::id_util::IdIsValid(extension_id)) {
- if (!worker_scope_url.is_valid()) {
- mojo::ReportBadMessage(kRemoveEventListenerWithInvalidWorkerScopeURL);
- return;
- }
- RemoveServiceWorkerEventListener(
- event_name, process, extension_id, worker_scope_url,
- service_worker_version_id, worker_thread_id);
- } else {
- mojo::ReportBadMessage(kRemoveEventListenerWithInvalidExtensionID);
- }
- }
- void EventRouter::RemoveLazyListenerForMainThread(
- const std::string& extension_id,
- const std::string& event_name) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RemoveLazyEventListener(event_name, extension_id);
- }
- void EventRouter::RemoveLazyListenerForServiceWorker(
- const std::string& extension_id,
- const GURL& worker_scope_url,
- const std::string& event_name) {
- std::unique_ptr<EventListener> listener =
- EventListener::ForExtensionServiceWorker(
- event_name, extension_id, nullptr, worker_scope_url,
- // Lazy listener, without worker version id and thread id.
- blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId, nullptr);
- RemoveLazyEventListenerImpl(std::move(listener),
- RegisteredEventType::kServiceWorker);
- }
- void EventRouter::RemoveFilteredListenerForMainThread(
- mojom::EventListenerParamPtr param,
- const std::string& event_name,
- base::Value filter,
- bool remove_lazy_listener) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto* process = RenderProcessHost::FromID(receivers_.current_context());
- if (!process)
- return;
- RemoveFilteredEventListener(
- event_name, process, std::move(param), absl::nullopt,
- base::Value::AsDictionaryValue(filter), remove_lazy_listener);
- }
- void EventRouter::RemoveFilteredListenerForServiceWorker(
- const std::string& extension_id,
- const GURL& worker_scope_url,
- const std::string& event_name,
- int64_t service_worker_version_id,
- int32_t worker_thread_id,
- base::Value filter,
- bool remove_lazy_listener) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- auto* process = RenderProcessHost::FromID(receivers_.current_context());
- if (!process)
- return;
- ServiceWorkerIdentifier sw_identifier;
- sw_identifier.scope = worker_scope_url;
- sw_identifier.thread_id = worker_thread_id;
- sw_identifier.version_id = service_worker_version_id;
- RemoveFilteredEventListener(
- event_name, process,
- mojom::EventListenerParam::NewExtensionId(extension_id), sw_identifier,
- base::Value::AsDictionaryValue(filter), remove_lazy_listener);
- }
- void EventRouter::AddEventListener(const std::string& event_name,
- RenderProcessHost* process,
- const std::string& extension_id) {
- listeners_.AddListener(
- EventListener::ForExtension(event_name, extension_id, process, nullptr));
- }
- void EventRouter::AddServiceWorkerEventListener(
- const std::string& event_name,
- RenderProcessHost* process,
- const ExtensionId& extension_id,
- const GURL& service_worker_scope,
- int64_t service_worker_version_id,
- int worker_thread_id) {
- listeners_.AddListener(EventListener::ForExtensionServiceWorker(
- event_name, extension_id, process, service_worker_scope,
- service_worker_version_id, worker_thread_id, nullptr));
- }
- void EventRouter::RemoveEventListener(const std::string& event_name,
- RenderProcessHost* process,
- const std::string& extension_id) {
- std::unique_ptr<EventListener> listener =
- EventListener::ForExtension(event_name, extension_id, process, nullptr);
- listeners_.RemoveListener(listener.get());
- }
- void EventRouter::RemoveServiceWorkerEventListener(
- const std::string& event_name,
- RenderProcessHost* process,
- const ExtensionId& extension_id,
- const GURL& service_worker_scope,
- int64_t service_worker_version_id,
- int worker_thread_id) {
- std::unique_ptr<EventListener> listener =
- EventListener::ForExtensionServiceWorker(
- event_name, extension_id, process, service_worker_scope,
- service_worker_version_id, worker_thread_id, nullptr);
- listeners_.RemoveListener(listener.get());
- }
- void EventRouter::AddEventListenerForURL(const std::string& event_name,
- RenderProcessHost* process,
- const GURL& listener_url) {
- listeners_.AddListener(
- EventListener::ForURL(event_name, listener_url, process, nullptr));
- }
- void EventRouter::RemoveEventListenerForURL(const std::string& event_name,
- RenderProcessHost* process,
- const GURL& listener_url) {
- std::unique_ptr<EventListener> listener =
- EventListener::ForURL(event_name, listener_url, process, nullptr);
- listeners_.RemoveListener(listener.get());
- }
- void EventRouter::RegisterObserver(Observer* observer,
- const std::string& event_name) {
- // Observing sub-event names like "foo.onBar/123" is not allowed.
- DCHECK(event_name.find('/') == std::string::npos);
- auto& observers = observer_map_[event_name];
- if (!observers) {
- observers = std::make_unique<Observers>();
- }
- observers->AddObserver(observer);
- }
- void EventRouter::UnregisterObserver(Observer* observer) {
- for (auto& it : observer_map_) {
- it.second->RemoveObserver(observer);
- }
- }
- void EventRouter::AddObserverForTesting(TestObserver* observer) {
- test_observers_.AddObserver(observer);
- }
- void EventRouter::RemoveObserverForTesting(TestObserver* observer) {
- test_observers_.RemoveObserver(observer);
- }
- void EventRouter::OnListenerAdded(const EventListener* listener) {
- const EventListenerInfo details(
- listener->event_name(), listener->extension_id(),
- listener->listener_url(), listener->GetBrowserContext(),
- listener->worker_thread_id(), listener->service_worker_version_id());
- std::string base_event_name = GetBaseEventName(listener->event_name());
- auto it = observer_map_.find(base_event_name);
- if (it != observer_map_.end()) {
- for (auto& observer : *it->second) {
- observer.OnListenerAdded(details);
- }
- }
- RenderProcessHost* process = listener->process();
- if (process) {
- bool inserted = observed_process_set_.insert(process).second;
- if (inserted)
- process->AddObserver(this);
- }
- }
- void EventRouter::OnListenerRemoved(const EventListener* listener) {
- const EventListenerInfo details(
- listener->event_name(), listener->extension_id(),
- listener->listener_url(), listener->GetBrowserContext(),
- listener->worker_thread_id(), listener->service_worker_version_id());
- std::string base_event_name = GetBaseEventName(listener->event_name());
- auto it = observer_map_.find(base_event_name);
- if (it != observer_map_.end()) {
- for (auto& observer : *it->second) {
- observer.OnListenerRemoved(details);
- }
- }
- }
- void EventRouter::RenderProcessExited(
- RenderProcessHost* host,
- const content::ChildProcessTerminationInfo& info) {
- listeners_.RemoveListenersForProcess(host);
- observed_process_set_.erase(host);
- rph_dispatcher_map_.erase(host);
- host->RemoveObserver(this);
- }
- void EventRouter::RenderProcessHostDestroyed(RenderProcessHost* host) {
- listeners_.RemoveListenersForProcess(host);
- observed_process_set_.erase(host);
- host->RemoveObserver(this);
- }
- void EventRouter::AddLazyEventListener(const std::string& event_name,
- const ExtensionId& extension_id) {
- AddLazyEventListenerImpl(
- EventListener::ForExtension(event_name, extension_id, nullptr, nullptr),
- RegisteredEventType::kLazy);
- }
- void EventRouter::RemoveLazyEventListener(const std::string& event_name,
- const ExtensionId& extension_id) {
- RemoveLazyEventListenerImpl(
- EventListener::ForExtension(event_name, extension_id, nullptr, nullptr),
- RegisteredEventType::kLazy);
- }
- void EventRouter::AddFilteredEventListener(
- const std::string& event_name,
- RenderProcessHost* process,
- mojom::EventListenerParamPtr param,
- absl::optional<ServiceWorkerIdentifier> sw_identifier,
- const base::DictionaryValue& filter,
- bool add_lazy_listener) {
- const bool is_for_service_worker = sw_identifier.has_value();
- std::unique_ptr<EventListener> regular_listener;
- std::unique_ptr<EventListener> lazy_listener;
- if (is_for_service_worker && param->is_extension_id()) {
- regular_listener = EventListener::ForExtensionServiceWorker(
- event_name, param->get_extension_id(), process, sw_identifier->scope,
- sw_identifier->version_id, sw_identifier->thread_id,
- filter.CreateDeepCopy());
- if (add_lazy_listener) {
- lazy_listener = EventListener::ForExtensionServiceWorker(
- event_name, param->get_extension_id(), nullptr, sw_identifier->scope,
- // Lazy listener, without worker version id and thread id.
- blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId,
- filter.CreateDeepCopy());
- }
- } else if (param->is_extension_id()) {
- regular_listener =
- EventListener::ForExtension(event_name, param->get_extension_id(),
- process, filter.CreateDeepCopy());
- if (add_lazy_listener) {
- lazy_listener =
- EventListener::ForExtension(event_name, param->get_extension_id(),
- nullptr, // Lazy, without process.
- filter.CreateDeepCopy());
- }
- } else if (param->is_listener_url() && !add_lazy_listener) {
- regular_listener =
- EventListener::ForURL(event_name, param->get_listener_url(), process,
- filter.CreateDeepCopy());
- } else {
- mojo::ReportBadMessage(kAddEventListenerWithInvalidParam);
- return;
- }
- listeners_.AddListener(std::move(regular_listener));
- DCHECK_EQ(add_lazy_listener, !!lazy_listener);
- if (lazy_listener) {
- bool added = listeners_.AddListener(std::move(lazy_listener));
- if (added) {
- AddFilterToEvent(event_name, param->get_extension_id(),
- is_for_service_worker, &filter);
- }
- }
- }
- void EventRouter::RemoveFilteredEventListener(
- const std::string& event_name,
- RenderProcessHost* process,
- mojom::EventListenerParamPtr param,
- absl::optional<ServiceWorkerIdentifier> sw_identifier,
- const base::DictionaryValue& filter,
- bool remove_lazy_listener) {
- const bool is_for_service_worker = sw_identifier.has_value();
- std::unique_ptr<EventListener> listener;
- if (is_for_service_worker && param->is_extension_id()) {
- listener = EventListener::ForExtensionServiceWorker(
- event_name, param->get_extension_id(), process, sw_identifier->scope,
- sw_identifier->version_id, sw_identifier->thread_id,
- filter.CreateDeepCopy());
- } else if (param->is_extension_id()) {
- listener =
- EventListener::ForExtension(event_name, param->get_extension_id(),
- process, filter.CreateDeepCopy());
- } else if (param->is_listener_url() && !remove_lazy_listener) {
- listener = EventListener::ForURL(event_name, param->get_listener_url(),
- process, filter.CreateDeepCopy());
- } else {
- mojo::ReportBadMessage(kRemoveEventListenerWithInvalidParam);
- return;
- }
- listeners_.RemoveListener(listener.get());
- if (remove_lazy_listener) {
- listener->MakeLazy();
- bool removed = listeners_.RemoveListener(listener.get());
- if (removed) {
- RemoveFilterFromEvent(event_name, param->get_extension_id(),
- is_for_service_worker, &filter);
- }
- }
- }
- bool EventRouter::HasEventListener(const std::string& event_name) const {
- return listeners_.HasListenerForEvent(event_name);
- }
- bool EventRouter::ExtensionHasEventListener(
- const std::string& extension_id,
- const std::string& event_name) const {
- return listeners_.HasListenerForExtension(extension_id, event_name);
- }
- std::set<std::string> EventRouter::GetRegisteredEvents(
- const std::string& extension_id,
- RegisteredEventType type) const {
- std::set<std::string> events;
- const ListValue* events_value = NULL;
- const char* pref_key = type == RegisteredEventType::kLazy
- ? kRegisteredLazyEvents
- : kRegisteredServiceWorkerEvents;
- if (!extension_prefs_ || !extension_prefs_->ReadPrefAsList(
- extension_id, pref_key, &events_value)) {
- return events;
- }
- for (const base::Value& event_val : events_value->GetListDeprecated()) {
- const std::string* event = event_val.GetIfString();
- if (event)
- events.insert(*event);
- }
- return events;
- }
- void EventRouter::ClearRegisteredEventsForTest(
- const ExtensionId& extension_id) {
- SetRegisteredEvents(extension_id, std::set<std::string>(),
- RegisteredEventType::kLazy);
- SetRegisteredEvents(extension_id, std::set<std::string>(),
- RegisteredEventType::kServiceWorker);
- }
- bool EventRouter::HasLazyEventListenerForTesting(
- const std::string& event_name) {
- const EventListenerMap::ListenerList& listeners =
- listeners_.GetEventListenersByName(event_name);
- return std::any_of(listeners.begin(), listeners.end(),
- [](const std::unique_ptr<EventListener>& listener) {
- return listener->IsLazy();
- });
- }
- bool EventRouter::HasNonLazyEventListenerForTesting(
- const std::string& event_name) {
- const EventListenerMap::ListenerList& listeners =
- listeners_.GetEventListenersByName(event_name);
- return std::any_of(listeners.begin(), listeners.end(),
- [](const std::unique_ptr<EventListener>& listener) {
- return !listener->IsLazy();
- });
- }
- void EventRouter::RemoveFilterFromEvent(const std::string& event_name,
- const std::string& extension_id,
- bool is_for_service_worker,
- const DictionaryValue* filter) {
- ExtensionPrefs::ScopedDictionaryUpdate update(
- extension_prefs_, extension_id,
- is_for_service_worker ? kFilteredServiceWorkerEvents : kFilteredEvents);
- auto filtered_events = update.Create();
- base::Value::List* filter_list = nullptr;
- if (!filtered_events ||
- !filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
- return;
- }
- filter_list->erase(base::ranges::find(*filter_list, *filter));
- }
- const DictionaryValue* EventRouter::GetFilteredEvents(
- const std::string& extension_id,
- RegisteredEventType type) {
- const DictionaryValue* events = nullptr;
- const char* pref_key = type == RegisteredEventType::kLazy
- ? kFilteredEvents
- : kFilteredServiceWorkerEvents;
- extension_prefs_->ReadPrefAsDictionary(extension_id, pref_key, &events);
- return events;
- }
- void EventRouter::BroadcastEvent(std::unique_ptr<Event> event) {
- DispatchEventImpl(std::string(), std::move(event));
- }
- void EventRouter::DispatchEventToExtension(const std::string& extension_id,
- std::unique_ptr<Event> event) {
- DCHECK(!extension_id.empty());
- DispatchEventImpl(extension_id, std::move(event));
- }
- void EventRouter::DispatchEventWithLazyListener(const std::string& extension_id,
- std::unique_ptr<Event> event) {
- DCHECK(!extension_id.empty());
- const Extension* extension = ExtensionRegistry::Get(browser_context_)
- ->enabled_extensions()
- .GetByID(extension_id);
- if (!extension)
- return;
- const bool is_service_worker_based_background =
- BackgroundInfo::IsServiceWorkerBased(extension);
- std::string event_name = event->event_name;
- const bool has_listener = ExtensionHasEventListener(extension_id, event_name);
- if (!has_listener) {
- if (is_service_worker_based_background) {
- AddLazyListenerForServiceWorker(
- extension_id, Extension::GetBaseURLFromExtensionId(extension_id),
- event_name);
- } else {
- AddLazyEventListener(event_name, extension_id);
- }
- }
- DispatchEventToExtension(extension_id, std::move(event));
- if (!has_listener) {
- if (is_service_worker_based_background) {
- RemoveLazyListenerForServiceWorker(
- extension_id, Extension::GetBaseURLFromExtensionId(extension_id),
- event_name);
- } else {
- RemoveLazyEventListener(event_name, extension_id);
- }
- }
- }
- void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
- std::unique_ptr<Event> event) {
- DCHECK(event);
- // We don't expect to get events from a completely different browser context.
- DCHECK(!event->restrict_to_browser_context ||
- ExtensionsBrowserClient::Get()->IsSameContext(
- browser_context_, event->restrict_to_browser_context));
- // Don't dispatch events to observers if the browser is shutting down.
- if (browser_context_->ShutdownStarted())
- return;
- for (TestObserver& observer : test_observers_)
- observer.OnWillDispatchEvent(*event);
- std::set<const EventListener*> listeners(
- listeners_.GetEventListeners(*event));
- LazyEventDispatcher lazy_event_dispatcher(
- browser_context_, base::BindRepeating(&EventRouter::DispatchPendingEvent,
- weak_factory_.GetWeakPtr()));
- // We dispatch events for lazy background pages first because attempting to do
- // so will cause those that are being suspended to cancel that suspension.
- // As canceling a suspension entails sending an event to the affected
- // background page, and as that event needs to be delivered before we dispatch
- // the event we are dispatching here, we dispatch to the lazy listeners here
- // first.
- for (const EventListener* listener : listeners) {
- if (!restrict_to_extension_id.empty() &&
- restrict_to_extension_id != listener->extension_id()) {
- continue;
- }
- if (!listener->IsLazy())
- continue;
- lazy_event_dispatcher.Dispatch(
- *event, LazyContextIdForBrowserContext(browser_context_, listener),
- listener->filter());
- }
- for (const EventListener* listener : listeners) {
- if (!restrict_to_extension_id.empty() &&
- restrict_to_extension_id != listener->extension_id()) {
- continue;
- }
- if (listener->IsLazy())
- continue;
- if (lazy_event_dispatcher.HasAlreadyDispatched(
- LazyContextIdForListener(listener))) {
- continue;
- }
- DispatchEventToProcess(
- listener->extension_id(), listener->listener_url(), listener->process(),
- listener->service_worker_version_id(), listener->worker_thread_id(),
- *event, listener->filter(), false /* did_enqueue */);
- }
- }
- void EventRouter::DispatchEventToProcess(
- const std::string& extension_id,
- const GURL& listener_url,
- RenderProcessHost* process,
- int64_t service_worker_version_id,
- int worker_thread_id,
- const Event& event,
- const base::DictionaryValue* listener_filter,
- bool did_enqueue) {
- BrowserContext* listener_context = process->GetBrowserContext();
- ProcessMap* process_map = ProcessMap::Get(listener_context);
- // NOTE: |extension| being NULL does not necessarily imply that this event
- // shouldn't be dispatched. Events can be dispatched to WebUI and webviews as
- // well. It all depends on what GetMostLikelyContextType returns.
- const Extension* extension =
- ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
- extension_id);
- if (!extension && !extension_id.empty()) {
- // Trying to dispatch an event to an extension that doesn't exist. The
- // extension could have been removed, but we do not unregister it until the
- // extension process is unloaded.
- return;
- }
- if (extension) {
- // Extension-specific checks.
- // Firstly, if the event is for a URL, the Extension must have permission
- // to access that URL.
- if (!event.event_url.is_empty() &&
- event.event_url.host() != extension->id() && // event for self is ok
- !extension->permissions_data()
- ->active_permissions()
- .HasEffectiveAccessToURL(event.event_url)) {
- return;
- }
- // Secondly, if the event is for incognito mode, the Extension must be
- // enabled in incognito mode.
- if (!CanDispatchEventToBrowserContext(listener_context, extension, event)) {
- return;
- }
- }
- // TODO(ortuno): |listener_url| is passed in from the renderer so it can't
- // fully be trusted. We should retrieve the URL from the browser process.
- const GURL* url =
- service_worker_version_id == blink::mojom::kInvalidServiceWorkerVersionId
- ? &listener_url
- : nullptr;
- Feature::Context target_context =
- process_map->GetMostLikelyContextType(extension, process->GetID(), url);
- // We shouldn't be dispatching an event to a webpage, since all such events
- // (e.g. messaging) don't go through EventRouter.
- DCHECK_NE(Feature::WEB_PAGE_CONTEXT, target_context)
- << "Trying to dispatch event " << event.event_name << " to a webpage,"
- << " but this shouldn't be possible";
- Feature::Availability availability =
- ExtensionAPI::GetSharedInstance()->IsAvailable(
- event.event_name, extension, target_context, listener_url,
- CheckAliasStatus::ALLOWED,
- util::GetBrowserContextId(browser_context_));
- if (!availability.is_available()) {
- // It shouldn't be possible to reach here, because access is checked on
- // registration. However, for paranoia, check on dispatch as well.
- NOTREACHED() << "Trying to dispatch event " << event.event_name
- << " which the target does not have access to: "
- << availability.message();
- return;
- }
- std::unique_ptr<base::Value::List> modified_event_args;
- mojom::EventFilteringInfoPtr modified_event_filter_info;
- if (!event.will_dispatch_callback.is_null() &&
- !event.will_dispatch_callback.Run(
- listener_context, target_context, extension, listener_filter,
- &modified_event_args, &modified_event_filter_info)) {
- return;
- }
- base::Value::List event_args_to_use = modified_event_args
- ? std::move(*modified_event_args)
- : event.event_args.Clone();
- mojom::EventFilteringInfoPtr filter_info =
- modified_event_filter_info ? std::move(modified_event_filter_info)
- : event.filter_info.Clone();
- int event_id = g_extension_event_id.GetNext();
- DispatchExtensionMessage(process, worker_thread_id, listener_context,
- extension_id, event_id, event.event_name,
- std::move(event_args_to_use), event.user_gesture,
- std::move(filter_info));
- for (TestObserver& observer : test_observers_)
- observer.OnDidDispatchEventToProcess(event);
- // TODO(lazyboy): This is wrong for extensions SW events. We need to:
- // 1. Increment worker ref count
- // 2. Add EventAck IPC to decrement that ref count.
- if (extension) {
- ReportEvent(event.histogram_value, extension, did_enqueue);
- IncrementInFlightEvents(listener_context, process, extension, event_id,
- event.event_name, service_worker_version_id);
- }
- }
- // static
- void EventRouter::DoDispatchEventToSenderBookkeeping(
- content::BrowserContext* browser_context,
- const std::string& extension_id,
- int event_id,
- int render_process_id,
- int64_t service_worker_version_id,
- events::HistogramValue histogram_value,
- const std::string& event_name) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
- return;
- auto* registry = ExtensionRegistry::Get(browser_context);
- DCHECK(registry);
- const Extension* extension =
- registry->enabled_extensions().GetByID(extension_id);
- if (!extension)
- return;
- EventRouter* event_router = EventRouter::Get(browser_context);
- DCHECK(event_router);
- event_router->IncrementInFlightEvents(
- browser_context, RenderProcessHost::FromID(render_process_id), extension,
- event_id, event_name, service_worker_version_id);
- event_router->ReportEvent(histogram_value, extension, /*did_enqueue=*/false);
- }
- void EventRouter::IncrementInFlightEvents(BrowserContext* context,
- RenderProcessHost* process,
- const Extension* extension,
- int event_id,
- const std::string& event_name,
- int64_t service_worker_version_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // Only increment in-flight events if the lazy background page is active,
- // because that's the only time we'll get an ACK.
- if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
- ProcessManager* pm = ProcessManager::Get(context);
- ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
- if (host) {
- pm->IncrementLazyKeepaliveCount(extension, Activity::EVENT, event_name);
- host->OnBackgroundEventDispatched(event_name, event_id);
- }
- } else if (service_worker_version_id !=
- blink::mojom::kInvalidServiceWorkerVersionId) {
- // Check to make sure the rendered process hasn't gone away by the time
- // we've gotten here. (It's possible it has crashed, etc.) If that's
- // happened, we don't want to track the expected ACK, since we'll never
- // get it.
- if (process) {
- content::ServiceWorkerContext* service_worker_context =
- process->GetStoragePartition()->GetServiceWorkerContext();
- event_ack_data_.IncrementInflightEvent(
- service_worker_context, process->GetID(), service_worker_version_id,
- event_id);
- }
- }
- }
- void EventRouter::OnEventAck(BrowserContext* context,
- const std::string& extension_id,
- const std::string& event_name) {
- ProcessManager* pm = ProcessManager::Get(context);
- ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
- // The event ACK is routed to the background host, so this should never be
- // NULL.
- CHECK(host);
- // TODO(mpcomplete): We should never get this message unless
- // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
- if (host->extension() &&
- BackgroundInfo::HasLazyBackgroundPage(host->extension()))
- pm->DecrementLazyKeepaliveCount(host->extension(), Activity::EVENT,
- event_name);
- }
- bool EventRouter::HasRegisteredEvents(const ExtensionId& extension_id) const {
- return !GetRegisteredEvents(extension_id, RegisteredEventType::kLazy)
- .empty() ||
- !GetRegisteredEvents(extension_id, RegisteredEventType::kServiceWorker)
- .empty();
- }
- void EventRouter::ReportEvent(events::HistogramValue histogram_value,
- const Extension* extension,
- bool did_enqueue) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- // Record every event fired.
- UMA_HISTOGRAM_ENUMERATION("Extensions.Events.Dispatch", histogram_value,
- events::ENUM_BOUNDARY);
- bool is_component = Manifest::IsComponentLocation(extension->location());
- // Record events for component extensions. These should be kept to a minimum,
- // especially if they wake its event page. Component extensions should use
- // declarative APIs as much as possible.
- if (is_component) {
- UMA_HISTOGRAM_ENUMERATION("Extensions.Events.DispatchToComponent",
- histogram_value, events::ENUM_BOUNDARY);
- }
- // Record events for background pages, if any. The most important statistic
- // is DispatchWithSuspendedEventPage. Events reported there woke an event
- // page. Implementing either filtered or declarative versions of these events
- // should be prioritised.
- //
- // Note: all we know is that the extension *has* a persistent or event page,
- // not that the event is being dispatched *to* such a page. However, this is
- // academic, since extensions with any background page have that background
- // page running (or in the case of suspended event pages, must be started)
- // regardless of where the event is being dispatched. Events are dispatched
- // to a *process* not a *frame*.
- if (BackgroundInfo::HasPersistentBackgroundPage(extension)) {
- UMA_HISTOGRAM_ENUMERATION(
- "Extensions.Events.DispatchWithPersistentBackgroundPage",
- histogram_value, events::ENUM_BOUNDARY);
- } else if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
- if (did_enqueue) {
- UMA_HISTOGRAM_ENUMERATION(
- "Extensions.Events.DispatchWithSuspendedEventPage", histogram_value,
- events::ENUM_BOUNDARY);
- } else {
- UMA_HISTOGRAM_ENUMERATION(
- "Extensions.Events.DispatchWithRunningEventPage", histogram_value,
- events::ENUM_BOUNDARY);
- }
- } else if (BackgroundInfo::IsServiceWorkerBased(extension)) {
- base::UmaHistogramEnumeration(
- "Extensions.Events.DispatchWithServiceWorkerBackground",
- histogram_value, events::ENUM_BOUNDARY);
- }
- }
- void EventRouter::DispatchPendingEvent(
- std::unique_ptr<Event> event,
- std::unique_ptr<LazyContextTaskQueue::ContextInfo> params) {
- if (!params)
- return;
- DCHECK(event);
- if (listeners_.HasProcessListener(params->render_process_host,
- params->worker_thread_id,
- params->extension_id)) {
- DispatchEventToProcess(
- params->extension_id, params->url, params->render_process_host,
- params->service_worker_version_id, params->worker_thread_id, *event,
- nullptr, true /* did_enqueue */);
- }
- }
- void EventRouter::SetRegisteredEvents(const std::string& extension_id,
- const std::set<std::string>& events,
- RegisteredEventType type) {
- base::Value events_value(base::Value::Type::LIST);
- for (auto iter = events.cbegin(); iter != events.cend(); ++iter) {
- events_value.Append(*iter);
- }
- const char* pref_key = type == RegisteredEventType::kLazy
- ? kRegisteredLazyEvents
- : kRegisteredServiceWorkerEvents;
- extension_prefs_->UpdateExtensionPref(
- extension_id, pref_key,
- base::Value::ToUniquePtrValue(std::move(events_value)));
- }
- void EventRouter::AddFilterToEvent(const std::string& event_name,
- const std::string& extension_id,
- bool is_for_service_worker,
- const DictionaryValue* filter) {
- ExtensionPrefs::ScopedDictionaryUpdate update(
- extension_prefs_, extension_id,
- is_for_service_worker ? kFilteredServiceWorkerEvents : kFilteredEvents);
- auto filtered_events = update.Create();
- base::Value::List* filter_list = nullptr;
- if (!filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
- filtered_events->SetKey(event_name, base::Value(base::Value::List()));
- filtered_events->GetListWithoutPathExpansion(event_name, &filter_list);
- }
- filter_list->Append(filter->Clone());
- }
- void EventRouter::OnExtensionLoaded(content::BrowserContext* browser_context,
- const Extension* extension) {
- // Add all registered lazy listeners to our cache.
- std::set<std::string> registered_events =
- GetRegisteredEvents(extension->id(), RegisteredEventType::kLazy);
- listeners_.LoadUnfilteredLazyListeners(extension->id(), registered_events);
- std::set<std::string> registered_worker_events =
- GetRegisteredEvents(extension->id(), RegisteredEventType::kServiceWorker);
- listeners_.LoadUnfilteredWorkerListeners(extension->id(),
- registered_worker_events);
- const DictionaryValue* filtered_events =
- GetFilteredEvents(extension->id(), RegisteredEventType::kLazy);
- if (filtered_events)
- listeners_.LoadFilteredLazyListeners(
- extension->id(), false /* is_for_service_worker */, *filtered_events);
- const DictionaryValue* filtered_worker_events =
- GetFilteredEvents(extension->id(), RegisteredEventType::kServiceWorker);
- if (filtered_worker_events)
- listeners_.LoadFilteredLazyListeners(extension->id(),
- true /* is_for_service_worker */,
- *filtered_worker_events);
- }
- void EventRouter::OnExtensionUnloaded(content::BrowserContext* browser_context,
- const Extension* extension,
- UnloadedExtensionReason reason) {
- // Remove all registered listeners from our cache.
- listeners_.RemoveListenersForExtension(extension->id());
- }
- void EventRouter::AddLazyEventListenerImpl(
- std::unique_ptr<EventListener> listener,
- RegisteredEventType type) {
- const ExtensionId extension_id = listener->extension_id();
- const std::string event_name = listener->event_name();
- bool is_new = listeners_.AddListener(std::move(listener));
- if (is_new) {
- std::set<std::string> events = GetRegisteredEvents(extension_id, type);
- bool prefs_is_new = events.insert(event_name).second;
- if (prefs_is_new)
- SetRegisteredEvents(extension_id, events, type);
- }
- }
- void EventRouter::RemoveLazyEventListenerImpl(
- std::unique_ptr<EventListener> listener,
- RegisteredEventType type) {
- const ExtensionId extension_id = listener->extension_id();
- const std::string event_name = listener->event_name();
- bool did_exist = listeners_.RemoveListener(listener.get());
- if (did_exist) {
- std::set<std::string> events = GetRegisteredEvents(extension_id, type);
- bool prefs_did_exist = events.erase(event_name) > 0;
- DCHECK(prefs_did_exist);
- SetRegisteredEvents(extension_id, events, type);
- }
- }
- Event::Event(events::HistogramValue histogram_value,
- const std::string& event_name,
- base::Value::List event_args)
- : Event(histogram_value, event_name, std::move(event_args), nullptr) {}
- Event::Event(events::HistogramValue histogram_value,
- const std::string& event_name,
- base::Value::List event_args,
- content::BrowserContext* restrict_to_browser_context)
- : Event(histogram_value,
- event_name,
- std::move(event_args),
- restrict_to_browser_context,
- GURL(),
- EventRouter::USER_GESTURE_UNKNOWN,
- mojom::EventFilteringInfo::New()) {}
- Event::Event(events::HistogramValue histogram_value,
- const std::string& event_name,
- base::Value::List event_args_tmp,
- content::BrowserContext* restrict_to_browser_context,
- const GURL& event_url,
- EventRouter::UserGestureState user_gesture,
- mojom::EventFilteringInfoPtr info)
- : histogram_value(histogram_value),
- event_name(event_name),
- event_args(std::move(event_args_tmp)),
- restrict_to_browser_context(restrict_to_browser_context),
- event_url(event_url),
- user_gesture(user_gesture),
- filter_info(std::move(info)) {
- DCHECK_NE(events::UNKNOWN, histogram_value)
- << "events::UNKNOWN cannot be used as a histogram value.\n"
- << "If this is a test, use events::FOR_TEST.\n"
- << "If this is production code, it is important that you use a realistic "
- << "value so that we can accurately track event usage. "
- << "See extension_event_histogram_value.h for inspiration.";
- }
- Event::~Event() = default;
- std::unique_ptr<Event> Event::DeepCopy() const {
- auto copy =
- std::make_unique<Event>(histogram_value, event_name, event_args.Clone(),
- restrict_to_browser_context, event_url,
- user_gesture, filter_info.Clone());
- copy->will_dispatch_callback = will_dispatch_callback;
- return copy;
- }
- EventListenerInfo::EventListenerInfo(const std::string& event_name,
- const std::string& extension_id,
- const GURL& listener_url,
- content::BrowserContext* browser_context)
- : event_name(event_name),
- extension_id(extension_id),
- listener_url(listener_url),
- browser_context(browser_context),
- worker_thread_id(kMainThreadId),
- service_worker_version_id(blink::mojom::kInvalidServiceWorkerVersionId) {}
- EventListenerInfo::EventListenerInfo(const std::string& event_name,
- const std::string& extension_id,
- const GURL& listener_url,
- content::BrowserContext* browser_context,
- int worker_thread_id,
- int64_t service_worker_version_id)
- : event_name(event_name),
- extension_id(extension_id),
- listener_url(listener_url),
- browser_context(browser_context),
- worker_thread_id(worker_thread_id),
- service_worker_version_id(service_worker_version_id) {}
- } // namespace extensions
|