event_router.cc 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331
  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
  3. // found in the LICENSE file.
  4. #include "extensions/browser/event_router.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include <utility>
  8. #include "base/atomic_sequence_num.h"
  9. #include "base/bind.h"
  10. #include "base/metrics/histogram_functions.h"
  11. #include "base/metrics/histogram_macros.h"
  12. #include "base/observer_list.h"
  13. #include "base/ranges/algorithm.h"
  14. #include "base/values.h"
  15. #include "components/crx_file/id_util.h"
  16. #include "content/public/browser/browser_context.h"
  17. #include "content/public/browser/browser_task_traits.h"
  18. #include "content/public/browser/browser_thread.h"
  19. #include "content/public/browser/render_process_host.h"
  20. #include "content/public/browser/service_worker_context.h"
  21. #include "content/public/browser/storage_partition.h"
  22. #include "extensions/browser/api_activity_monitor.h"
  23. #include "extensions/browser/event_router_factory.h"
  24. #include "extensions/browser/events/lazy_event_dispatcher.h"
  25. #include "extensions/browser/extension_host.h"
  26. #include "extensions/browser/extension_prefs.h"
  27. #include "extensions/browser/extension_system.h"
  28. #include "extensions/browser/extension_util.h"
  29. #include "extensions/browser/extensions_browser_client.h"
  30. #include "extensions/browser/process_manager.h"
  31. #include "extensions/browser/process_map.h"
  32. #include "extensions/common/constants.h"
  33. #include "extensions/common/extension.h"
  34. #include "extensions/common/extension_api.h"
  35. #include "extensions/common/extension_messages.h"
  36. #include "extensions/common/extension_urls.h"
  37. #include "extensions/common/features/feature.h"
  38. #include "extensions/common/features/feature_provider.h"
  39. #include "extensions/common/manifest_handlers/background_info.h"
  40. #include "extensions/common/manifest_handlers/incognito_info.h"
  41. #include "extensions/common/mojom/event_dispatcher.mojom.h"
  42. #include "extensions/common/permissions/permissions_data.h"
  43. #include "ipc/ipc_channel_proxy.h"
  44. using base::DictionaryValue;
  45. using base::ListValue;
  46. using content::BrowserContext;
  47. using content::BrowserThread;
  48. using content::RenderProcessHost;
  49. namespace extensions {
  50. namespace {
  51. // A dictionary of event names to lists of filters that this extension has
  52. // registered from its lazy background page.
  53. const char kFilteredEvents[] = "filtered_events";
  54. // Similar to |kFilteredEvents|, but applies to extension service worker events.
  55. const char kFilteredServiceWorkerEvents[] = "filtered_service_worker_events";
  56. // A message when mojom::EventRouter::AddListenerForMainThread() is called with
  57. // an invalid param.
  58. constexpr char kAddEventListenerWithInvalidParam[] =
  59. "Tried to add an event listener without a valid extension ID nor listener "
  60. "URL";
  61. // A message when mojom::EventRouter::AddListenerForServiceWorker() is called
  62. // with an invalid worker scope URL.
  63. constexpr char kAddEventListenerWithInvalidWorkerScopeURL[] =
  64. "Tried to add an event listener for a service worker without a valid "
  65. "worker scope URL.";
  66. // A message when mojom::EventRouter::AddListenerForServiceWorker() is called
  67. // with an invalid extension ID.
  68. constexpr char kAddEventListenerWithInvalidExtensionID[] =
  69. "Tried to add an event listener for a service worker without a valid "
  70. "extension ID.";
  71. // A message when mojom::EventRouter::RemoveListenerForMainThread() is called
  72. // with an invalid param.
  73. constexpr char kRemoveEventListenerWithInvalidParam[] =
  74. "Tried to remove an event listener without a valid extension ID nor "
  75. "listener URL";
  76. // A message when mojom::EventRouter::RemoveListenerForServiceWorker() is called
  77. // with an invalid worker scope URL.
  78. constexpr char kRemoveEventListenerWithInvalidWorkerScopeURL[] =
  79. "Tried to remove an event listener for a service worker without a valid "
  80. "worker scope URL.";
  81. // A message when mojom::EventRouter::RemoveListenerForServiceWorker() is called
  82. // with an invalid extension ID.
  83. constexpr char kRemoveEventListenerWithInvalidExtensionID[] =
  84. "Tried to remove an event listener for a service worker without a valid "
  85. "extension ID.";
  86. // Sends a notification about an event to the API activity monitor and the
  87. // ExtensionHost for |extension_id| on the UI thread. Can be called from any
  88. // thread.
  89. void NotifyEventDispatched(content::BrowserContext* browser_context,
  90. const std::string& extension_id,
  91. const std::string& event_name,
  92. const base::Value::List& args) {
  93. // Notify the ApiActivityMonitor about the event dispatch.
  94. activity_monitor::OnApiEventDispatched(browser_context, extension_id,
  95. event_name, args);
  96. }
  97. LazyContextId LazyContextIdForBrowserContext(BrowserContext* browser_context,
  98. const EventListener* listener) {
  99. auto* registry = ExtensionRegistry::Get(browser_context);
  100. DCHECK(registry);
  101. const Extension* extension =
  102. registry->enabled_extensions().GetByID(listener->extension_id());
  103. const bool is_service_worker_based_extension =
  104. extension && BackgroundInfo::IsServiceWorkerBased(extension);
  105. // Note: It is possible that the prefs' listener->is_for_service_worker() and
  106. // its extension background type do not agree. This happens when one changes
  107. // extension's manifest, typically during unpacked extension development.
  108. // Fallback to non-Service worker based LazyContextId to avoid surprising
  109. // ServiceWorkerTaskQueue (and crashing), see https://crbug.com/1239752 for
  110. // details.
  111. // TODO(lazyboy): Clean these inconsistencies across different types of event
  112. // listener and their corresponding background types.
  113. if (is_service_worker_based_extension && listener->is_for_service_worker()) {
  114. return LazyContextId(browser_context, listener->extension_id(),
  115. listener->listener_url());
  116. }
  117. return LazyContextId(browser_context, listener->extension_id());
  118. }
  119. LazyContextId LazyContextIdForListener(const EventListener* listener) {
  120. return LazyContextIdForBrowserContext(
  121. listener->process()->GetBrowserContext(), listener);
  122. }
  123. // A global identifier used to distinguish extension events.
  124. base::AtomicSequenceNumber g_extension_event_id;
  125. } // namespace
  126. const char EventRouter::kRegisteredLazyEvents[] = "events";
  127. const char EventRouter::kRegisteredServiceWorkerEvents[] =
  128. "serviceworkerevents";
  129. // static
  130. void EventRouter::DispatchExtensionMessage(
  131. content::RenderProcessHost* rph,
  132. int worker_thread_id,
  133. content::BrowserContext* browser_context,
  134. const std::string& extension_id,
  135. int event_id,
  136. const std::string& event_name,
  137. base::Value::List event_args,
  138. UserGestureState user_gesture,
  139. mojom::EventFilteringInfoPtr info) {
  140. NotifyEventDispatched(browser_context, extension_id, event_name, event_args);
  141. auto params = mojom::DispatchEventParams::New();
  142. params->worker_thread_id = worker_thread_id;
  143. params->extension_id = extension_id;
  144. params->event_name = event_name;
  145. params->event_id = event_id;
  146. params->is_user_gesture = user_gesture == USER_GESTURE_ENABLED;
  147. params->filtering_info = std::move(info);
  148. Get(browser_context)
  149. ->RouteDispatchEvent(rph, std::move(params), std::move(event_args));
  150. }
  151. void EventRouter::RouteDispatchEvent(content::RenderProcessHost* rph,
  152. mojom::DispatchEventParamsPtr params,
  153. base::Value::List event_args) {
  154. // TODO(crbug.com/1302000) Add bindings for worker threads to be directly
  155. // channel-associated.
  156. mojo::AssociatedRemote<mojom::EventDispatcher>& dispatcher =
  157. rph_dispatcher_map_[rph];
  158. if (!dispatcher.is_bound()) {
  159. IPC::ChannelProxy* channel = rph->GetChannel();
  160. if (!channel) {
  161. return;
  162. }
  163. channel->GetRemoteAssociatedInterface(
  164. dispatcher.BindNewEndpointAndPassReceiver());
  165. }
  166. dispatcher->DispatchEvent(std::move(params), std::move(event_args));
  167. }
  168. // static
  169. EventRouter* EventRouter::Get(content::BrowserContext* browser_context) {
  170. return EventRouterFactory::GetForBrowserContext(browser_context);
  171. }
  172. // static
  173. std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
  174. size_t slash_sep = full_event_name.find('/');
  175. return full_event_name.substr(0, slash_sep);
  176. }
  177. // static
  178. void EventRouter::DispatchEventToSender(
  179. content::RenderProcessHost* rph,
  180. content::BrowserContext* browser_context,
  181. const std::string& extension_id,
  182. events::HistogramValue histogram_value,
  183. const std::string& event_name,
  184. int render_process_id,
  185. int worker_thread_id,
  186. int64_t service_worker_version_id,
  187. base::Value::List event_args,
  188. mojom::EventFilteringInfoPtr info) {
  189. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  190. int event_id = g_extension_event_id.GetNext();
  191. DoDispatchEventToSenderBookkeeping(
  192. browser_context, extension_id, event_id, render_process_id,
  193. service_worker_version_id, histogram_value, event_name);
  194. DispatchExtensionMessage(rph, worker_thread_id, browser_context, extension_id,
  195. event_id, event_name, std::move(event_args),
  196. UserGestureState::USER_GESTURE_UNKNOWN,
  197. std::move(info));
  198. }
  199. // static.
  200. bool EventRouter::CanDispatchEventToBrowserContext(BrowserContext* context,
  201. const Extension* extension,
  202. const Event& event) {
  203. // Is this event from a different browser context than the renderer (ie, an
  204. // incognito tab event sent to a normal process, or vice versa).
  205. bool crosses_incognito = event.restrict_to_browser_context &&
  206. context != event.restrict_to_browser_context;
  207. if (!crosses_incognito)
  208. return true;
  209. return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(extension,
  210. context);
  211. }
  212. // static
  213. void EventRouter::BindForRenderer(
  214. int render_process_id,
  215. mojo::PendingAssociatedReceiver<mojom::EventRouter> receiver) {
  216. auto* host = RenderProcessHost::FromID(render_process_id);
  217. if (!host)
  218. return;
  219. EventRouter* event_router = EventRouter::Get(host->GetBrowserContext());
  220. event_router->receivers_.Add(event_router, std::move(receiver),
  221. render_process_id);
  222. }
  223. EventRouter::EventRouter(BrowserContext* browser_context,
  224. ExtensionPrefs* extension_prefs)
  225. : browser_context_(browser_context),
  226. extension_prefs_(extension_prefs),
  227. lazy_event_dispatch_util_(browser_context_) {
  228. extension_registry_observation_.Observe(
  229. ExtensionRegistry::Get(browser_context_));
  230. }
  231. EventRouter::~EventRouter() {
  232. for (auto* process : observed_process_set_)
  233. process->RemoveObserver(this);
  234. }
  235. void EventRouter::AddListenerForMainThread(mojom::EventListenerParamPtr param,
  236. const std::string& event_name) {
  237. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  238. auto* process = RenderProcessHost::FromID(receivers_.current_context());
  239. if (!process)
  240. return;
  241. if (param->is_extension_id() &&
  242. crx_file::id_util::IdIsValid(param->get_extension_id())) {
  243. AddEventListener(event_name, process, param->get_extension_id());
  244. } else if (param->is_listener_url() && param->get_listener_url().is_valid()) {
  245. AddEventListenerForURL(event_name, process, param->get_listener_url());
  246. } else {
  247. mojo::ReportBadMessage(kAddEventListenerWithInvalidParam);
  248. }
  249. }
  250. void EventRouter::AddListenerForServiceWorker(const std::string& extension_id,
  251. const GURL& worker_scope_url,
  252. const std::string& event_name,
  253. int64_t service_worker_version_id,
  254. int32_t worker_thread_id) {
  255. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  256. auto* process = RenderProcessHost::FromID(receivers_.current_context());
  257. if (!process)
  258. return;
  259. if (crx_file::id_util::IdIsValid(extension_id)) {
  260. if (!worker_scope_url.is_valid()) {
  261. mojo::ReportBadMessage(kAddEventListenerWithInvalidWorkerScopeURL);
  262. return;
  263. }
  264. AddServiceWorkerEventListener(event_name, process, extension_id,
  265. worker_scope_url, service_worker_version_id,
  266. worker_thread_id);
  267. } else {
  268. mojo::ReportBadMessage(kAddEventListenerWithInvalidExtensionID);
  269. }
  270. }
  271. void EventRouter::AddLazyListenerForMainThread(const std::string& extension_id,
  272. const std::string& event_name) {
  273. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  274. AddLazyEventListener(event_name, extension_id);
  275. }
  276. void EventRouter::AddLazyListenerForServiceWorker(
  277. const std::string& extension_id,
  278. const GURL& worker_scope_url,
  279. const std::string& event_name) {
  280. std::unique_ptr<EventListener> listener =
  281. EventListener::ForExtensionServiceWorker(
  282. event_name, extension_id, nullptr, worker_scope_url,
  283. // Lazy listener, without worker version id and thread id.
  284. blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId, nullptr);
  285. AddLazyEventListenerImpl(std::move(listener),
  286. RegisteredEventType::kServiceWorker);
  287. }
  288. void EventRouter::AddFilteredListenerForMainThread(
  289. mojom::EventListenerParamPtr param,
  290. const std::string& event_name,
  291. base::Value filter,
  292. bool add_lazy_listener) {
  293. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  294. auto* process = RenderProcessHost::FromID(receivers_.current_context());
  295. if (!process)
  296. return;
  297. AddFilteredEventListener(event_name, process, std::move(param), absl::nullopt,
  298. base::Value::AsDictionaryValue(filter),
  299. add_lazy_listener);
  300. }
  301. void EventRouter::AddFilteredListenerForServiceWorker(
  302. const std::string& extension_id,
  303. const GURL& worker_scope_url,
  304. const std::string& event_name,
  305. int64_t service_worker_version_id,
  306. int32_t worker_thread_id,
  307. base::Value filter,
  308. bool add_lazy_listener) {
  309. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  310. auto* process = RenderProcessHost::FromID(receivers_.current_context());
  311. if (!process)
  312. return;
  313. ServiceWorkerIdentifier sw_identifier;
  314. sw_identifier.scope = worker_scope_url;
  315. sw_identifier.thread_id = worker_thread_id;
  316. sw_identifier.version_id = service_worker_version_id;
  317. AddFilteredEventListener(
  318. event_name, process,
  319. mojom::EventListenerParam::NewExtensionId(extension_id), sw_identifier,
  320. base::Value::AsDictionaryValue(filter), add_lazy_listener);
  321. }
  322. void EventRouter::RemoveListenerForMainThread(
  323. mojom::EventListenerParamPtr param,
  324. const std::string& event_name) {
  325. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  326. auto* process = RenderProcessHost::FromID(receivers_.current_context());
  327. if (!process)
  328. return;
  329. if (param->is_extension_id() &&
  330. crx_file::id_util::IdIsValid(param->get_extension_id())) {
  331. RemoveEventListener(event_name, process, param->get_extension_id());
  332. } else if (param->is_listener_url() && param->get_listener_url().is_valid()) {
  333. RemoveEventListenerForURL(event_name, process, param->get_listener_url());
  334. } else {
  335. mojo::ReportBadMessage(kRemoveEventListenerWithInvalidParam);
  336. }
  337. }
  338. void EventRouter::RemoveListenerForServiceWorker(
  339. const std::string& extension_id,
  340. const GURL& worker_scope_url,
  341. const std::string& event_name,
  342. int64_t service_worker_version_id,
  343. int worker_thread_id) {
  344. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  345. auto* process = RenderProcessHost::FromID(receivers_.current_context());
  346. if (!process)
  347. return;
  348. if (crx_file::id_util::IdIsValid(extension_id)) {
  349. if (!worker_scope_url.is_valid()) {
  350. mojo::ReportBadMessage(kRemoveEventListenerWithInvalidWorkerScopeURL);
  351. return;
  352. }
  353. RemoveServiceWorkerEventListener(
  354. event_name, process, extension_id, worker_scope_url,
  355. service_worker_version_id, worker_thread_id);
  356. } else {
  357. mojo::ReportBadMessage(kRemoveEventListenerWithInvalidExtensionID);
  358. }
  359. }
  360. void EventRouter::RemoveLazyListenerForMainThread(
  361. const std::string& extension_id,
  362. const std::string& event_name) {
  363. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  364. RemoveLazyEventListener(event_name, extension_id);
  365. }
  366. void EventRouter::RemoveLazyListenerForServiceWorker(
  367. const std::string& extension_id,
  368. const GURL& worker_scope_url,
  369. const std::string& event_name) {
  370. std::unique_ptr<EventListener> listener =
  371. EventListener::ForExtensionServiceWorker(
  372. event_name, extension_id, nullptr, worker_scope_url,
  373. // Lazy listener, without worker version id and thread id.
  374. blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId, nullptr);
  375. RemoveLazyEventListenerImpl(std::move(listener),
  376. RegisteredEventType::kServiceWorker);
  377. }
  378. void EventRouter::RemoveFilteredListenerForMainThread(
  379. mojom::EventListenerParamPtr param,
  380. const std::string& event_name,
  381. base::Value filter,
  382. bool remove_lazy_listener) {
  383. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  384. auto* process = RenderProcessHost::FromID(receivers_.current_context());
  385. if (!process)
  386. return;
  387. RemoveFilteredEventListener(
  388. event_name, process, std::move(param), absl::nullopt,
  389. base::Value::AsDictionaryValue(filter), remove_lazy_listener);
  390. }
  391. void EventRouter::RemoveFilteredListenerForServiceWorker(
  392. const std::string& extension_id,
  393. const GURL& worker_scope_url,
  394. const std::string& event_name,
  395. int64_t service_worker_version_id,
  396. int32_t worker_thread_id,
  397. base::Value filter,
  398. bool remove_lazy_listener) {
  399. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  400. auto* process = RenderProcessHost::FromID(receivers_.current_context());
  401. if (!process)
  402. return;
  403. ServiceWorkerIdentifier sw_identifier;
  404. sw_identifier.scope = worker_scope_url;
  405. sw_identifier.thread_id = worker_thread_id;
  406. sw_identifier.version_id = service_worker_version_id;
  407. RemoveFilteredEventListener(
  408. event_name, process,
  409. mojom::EventListenerParam::NewExtensionId(extension_id), sw_identifier,
  410. base::Value::AsDictionaryValue(filter), remove_lazy_listener);
  411. }
  412. void EventRouter::AddEventListener(const std::string& event_name,
  413. RenderProcessHost* process,
  414. const std::string& extension_id) {
  415. listeners_.AddListener(
  416. EventListener::ForExtension(event_name, extension_id, process, nullptr));
  417. }
  418. void EventRouter::AddServiceWorkerEventListener(
  419. const std::string& event_name,
  420. RenderProcessHost* process,
  421. const ExtensionId& extension_id,
  422. const GURL& service_worker_scope,
  423. int64_t service_worker_version_id,
  424. int worker_thread_id) {
  425. listeners_.AddListener(EventListener::ForExtensionServiceWorker(
  426. event_name, extension_id, process, service_worker_scope,
  427. service_worker_version_id, worker_thread_id, nullptr));
  428. }
  429. void EventRouter::RemoveEventListener(const std::string& event_name,
  430. RenderProcessHost* process,
  431. const std::string& extension_id) {
  432. std::unique_ptr<EventListener> listener =
  433. EventListener::ForExtension(event_name, extension_id, process, nullptr);
  434. listeners_.RemoveListener(listener.get());
  435. }
  436. void EventRouter::RemoveServiceWorkerEventListener(
  437. const std::string& event_name,
  438. RenderProcessHost* process,
  439. const ExtensionId& extension_id,
  440. const GURL& service_worker_scope,
  441. int64_t service_worker_version_id,
  442. int worker_thread_id) {
  443. std::unique_ptr<EventListener> listener =
  444. EventListener::ForExtensionServiceWorker(
  445. event_name, extension_id, process, service_worker_scope,
  446. service_worker_version_id, worker_thread_id, nullptr);
  447. listeners_.RemoveListener(listener.get());
  448. }
  449. void EventRouter::AddEventListenerForURL(const std::string& event_name,
  450. RenderProcessHost* process,
  451. const GURL& listener_url) {
  452. listeners_.AddListener(
  453. EventListener::ForURL(event_name, listener_url, process, nullptr));
  454. }
  455. void EventRouter::RemoveEventListenerForURL(const std::string& event_name,
  456. RenderProcessHost* process,
  457. const GURL& listener_url) {
  458. std::unique_ptr<EventListener> listener =
  459. EventListener::ForURL(event_name, listener_url, process, nullptr);
  460. listeners_.RemoveListener(listener.get());
  461. }
  462. void EventRouter::RegisterObserver(Observer* observer,
  463. const std::string& event_name) {
  464. // Observing sub-event names like "foo.onBar/123" is not allowed.
  465. DCHECK(event_name.find('/') == std::string::npos);
  466. auto& observers = observer_map_[event_name];
  467. if (!observers) {
  468. observers = std::make_unique<Observers>();
  469. }
  470. observers->AddObserver(observer);
  471. }
  472. void EventRouter::UnregisterObserver(Observer* observer) {
  473. for (auto& it : observer_map_) {
  474. it.second->RemoveObserver(observer);
  475. }
  476. }
  477. void EventRouter::AddObserverForTesting(TestObserver* observer) {
  478. test_observers_.AddObserver(observer);
  479. }
  480. void EventRouter::RemoveObserverForTesting(TestObserver* observer) {
  481. test_observers_.RemoveObserver(observer);
  482. }
  483. void EventRouter::OnListenerAdded(const EventListener* listener) {
  484. const EventListenerInfo details(
  485. listener->event_name(), listener->extension_id(),
  486. listener->listener_url(), listener->GetBrowserContext(),
  487. listener->worker_thread_id(), listener->service_worker_version_id());
  488. std::string base_event_name = GetBaseEventName(listener->event_name());
  489. auto it = observer_map_.find(base_event_name);
  490. if (it != observer_map_.end()) {
  491. for (auto& observer : *it->second) {
  492. observer.OnListenerAdded(details);
  493. }
  494. }
  495. RenderProcessHost* process = listener->process();
  496. if (process) {
  497. bool inserted = observed_process_set_.insert(process).second;
  498. if (inserted)
  499. process->AddObserver(this);
  500. }
  501. }
  502. void EventRouter::OnListenerRemoved(const EventListener* listener) {
  503. const EventListenerInfo details(
  504. listener->event_name(), listener->extension_id(),
  505. listener->listener_url(), listener->GetBrowserContext(),
  506. listener->worker_thread_id(), listener->service_worker_version_id());
  507. std::string base_event_name = GetBaseEventName(listener->event_name());
  508. auto it = observer_map_.find(base_event_name);
  509. if (it != observer_map_.end()) {
  510. for (auto& observer : *it->second) {
  511. observer.OnListenerRemoved(details);
  512. }
  513. }
  514. }
  515. void EventRouter::RenderProcessExited(
  516. RenderProcessHost* host,
  517. const content::ChildProcessTerminationInfo& info) {
  518. listeners_.RemoveListenersForProcess(host);
  519. observed_process_set_.erase(host);
  520. rph_dispatcher_map_.erase(host);
  521. host->RemoveObserver(this);
  522. }
  523. void EventRouter::RenderProcessHostDestroyed(RenderProcessHost* host) {
  524. listeners_.RemoveListenersForProcess(host);
  525. observed_process_set_.erase(host);
  526. host->RemoveObserver(this);
  527. }
  528. void EventRouter::AddLazyEventListener(const std::string& event_name,
  529. const ExtensionId& extension_id) {
  530. AddLazyEventListenerImpl(
  531. EventListener::ForExtension(event_name, extension_id, nullptr, nullptr),
  532. RegisteredEventType::kLazy);
  533. }
  534. void EventRouter::RemoveLazyEventListener(const std::string& event_name,
  535. const ExtensionId& extension_id) {
  536. RemoveLazyEventListenerImpl(
  537. EventListener::ForExtension(event_name, extension_id, nullptr, nullptr),
  538. RegisteredEventType::kLazy);
  539. }
  540. void EventRouter::AddFilteredEventListener(
  541. const std::string& event_name,
  542. RenderProcessHost* process,
  543. mojom::EventListenerParamPtr param,
  544. absl::optional<ServiceWorkerIdentifier> sw_identifier,
  545. const base::DictionaryValue& filter,
  546. bool add_lazy_listener) {
  547. const bool is_for_service_worker = sw_identifier.has_value();
  548. std::unique_ptr<EventListener> regular_listener;
  549. std::unique_ptr<EventListener> lazy_listener;
  550. if (is_for_service_worker && param->is_extension_id()) {
  551. regular_listener = EventListener::ForExtensionServiceWorker(
  552. event_name, param->get_extension_id(), process, sw_identifier->scope,
  553. sw_identifier->version_id, sw_identifier->thread_id,
  554. filter.CreateDeepCopy());
  555. if (add_lazy_listener) {
  556. lazy_listener = EventListener::ForExtensionServiceWorker(
  557. event_name, param->get_extension_id(), nullptr, sw_identifier->scope,
  558. // Lazy listener, without worker version id and thread id.
  559. blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId,
  560. filter.CreateDeepCopy());
  561. }
  562. } else if (param->is_extension_id()) {
  563. regular_listener =
  564. EventListener::ForExtension(event_name, param->get_extension_id(),
  565. process, filter.CreateDeepCopy());
  566. if (add_lazy_listener) {
  567. lazy_listener =
  568. EventListener::ForExtension(event_name, param->get_extension_id(),
  569. nullptr, // Lazy, without process.
  570. filter.CreateDeepCopy());
  571. }
  572. } else if (param->is_listener_url() && !add_lazy_listener) {
  573. regular_listener =
  574. EventListener::ForURL(event_name, param->get_listener_url(), process,
  575. filter.CreateDeepCopy());
  576. } else {
  577. mojo::ReportBadMessage(kAddEventListenerWithInvalidParam);
  578. return;
  579. }
  580. listeners_.AddListener(std::move(regular_listener));
  581. DCHECK_EQ(add_lazy_listener, !!lazy_listener);
  582. if (lazy_listener) {
  583. bool added = listeners_.AddListener(std::move(lazy_listener));
  584. if (added) {
  585. AddFilterToEvent(event_name, param->get_extension_id(),
  586. is_for_service_worker, &filter);
  587. }
  588. }
  589. }
  590. void EventRouter::RemoveFilteredEventListener(
  591. const std::string& event_name,
  592. RenderProcessHost* process,
  593. mojom::EventListenerParamPtr param,
  594. absl::optional<ServiceWorkerIdentifier> sw_identifier,
  595. const base::DictionaryValue& filter,
  596. bool remove_lazy_listener) {
  597. const bool is_for_service_worker = sw_identifier.has_value();
  598. std::unique_ptr<EventListener> listener;
  599. if (is_for_service_worker && param->is_extension_id()) {
  600. listener = EventListener::ForExtensionServiceWorker(
  601. event_name, param->get_extension_id(), process, sw_identifier->scope,
  602. sw_identifier->version_id, sw_identifier->thread_id,
  603. filter.CreateDeepCopy());
  604. } else if (param->is_extension_id()) {
  605. listener =
  606. EventListener::ForExtension(event_name, param->get_extension_id(),
  607. process, filter.CreateDeepCopy());
  608. } else if (param->is_listener_url() && !remove_lazy_listener) {
  609. listener = EventListener::ForURL(event_name, param->get_listener_url(),
  610. process, filter.CreateDeepCopy());
  611. } else {
  612. mojo::ReportBadMessage(kRemoveEventListenerWithInvalidParam);
  613. return;
  614. }
  615. listeners_.RemoveListener(listener.get());
  616. if (remove_lazy_listener) {
  617. listener->MakeLazy();
  618. bool removed = listeners_.RemoveListener(listener.get());
  619. if (removed) {
  620. RemoveFilterFromEvent(event_name, param->get_extension_id(),
  621. is_for_service_worker, &filter);
  622. }
  623. }
  624. }
  625. bool EventRouter::HasEventListener(const std::string& event_name) const {
  626. return listeners_.HasListenerForEvent(event_name);
  627. }
  628. bool EventRouter::ExtensionHasEventListener(
  629. const std::string& extension_id,
  630. const std::string& event_name) const {
  631. return listeners_.HasListenerForExtension(extension_id, event_name);
  632. }
  633. std::set<std::string> EventRouter::GetRegisteredEvents(
  634. const std::string& extension_id,
  635. RegisteredEventType type) const {
  636. std::set<std::string> events;
  637. const ListValue* events_value = NULL;
  638. const char* pref_key = type == RegisteredEventType::kLazy
  639. ? kRegisteredLazyEvents
  640. : kRegisteredServiceWorkerEvents;
  641. if (!extension_prefs_ || !extension_prefs_->ReadPrefAsList(
  642. extension_id, pref_key, &events_value)) {
  643. return events;
  644. }
  645. for (const base::Value& event_val : events_value->GetListDeprecated()) {
  646. const std::string* event = event_val.GetIfString();
  647. if (event)
  648. events.insert(*event);
  649. }
  650. return events;
  651. }
  652. void EventRouter::ClearRegisteredEventsForTest(
  653. const ExtensionId& extension_id) {
  654. SetRegisteredEvents(extension_id, std::set<std::string>(),
  655. RegisteredEventType::kLazy);
  656. SetRegisteredEvents(extension_id, std::set<std::string>(),
  657. RegisteredEventType::kServiceWorker);
  658. }
  659. bool EventRouter::HasLazyEventListenerForTesting(
  660. const std::string& event_name) {
  661. const EventListenerMap::ListenerList& listeners =
  662. listeners_.GetEventListenersByName(event_name);
  663. return std::any_of(listeners.begin(), listeners.end(),
  664. [](const std::unique_ptr<EventListener>& listener) {
  665. return listener->IsLazy();
  666. });
  667. }
  668. bool EventRouter::HasNonLazyEventListenerForTesting(
  669. const std::string& event_name) {
  670. const EventListenerMap::ListenerList& listeners =
  671. listeners_.GetEventListenersByName(event_name);
  672. return std::any_of(listeners.begin(), listeners.end(),
  673. [](const std::unique_ptr<EventListener>& listener) {
  674. return !listener->IsLazy();
  675. });
  676. }
  677. void EventRouter::RemoveFilterFromEvent(const std::string& event_name,
  678. const std::string& extension_id,
  679. bool is_for_service_worker,
  680. const DictionaryValue* filter) {
  681. ExtensionPrefs::ScopedDictionaryUpdate update(
  682. extension_prefs_, extension_id,
  683. is_for_service_worker ? kFilteredServiceWorkerEvents : kFilteredEvents);
  684. auto filtered_events = update.Create();
  685. base::Value::List* filter_list = nullptr;
  686. if (!filtered_events ||
  687. !filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
  688. return;
  689. }
  690. filter_list->erase(base::ranges::find(*filter_list, *filter));
  691. }
  692. const DictionaryValue* EventRouter::GetFilteredEvents(
  693. const std::string& extension_id,
  694. RegisteredEventType type) {
  695. const DictionaryValue* events = nullptr;
  696. const char* pref_key = type == RegisteredEventType::kLazy
  697. ? kFilteredEvents
  698. : kFilteredServiceWorkerEvents;
  699. extension_prefs_->ReadPrefAsDictionary(extension_id, pref_key, &events);
  700. return events;
  701. }
  702. void EventRouter::BroadcastEvent(std::unique_ptr<Event> event) {
  703. DispatchEventImpl(std::string(), std::move(event));
  704. }
  705. void EventRouter::DispatchEventToExtension(const std::string& extension_id,
  706. std::unique_ptr<Event> event) {
  707. DCHECK(!extension_id.empty());
  708. DispatchEventImpl(extension_id, std::move(event));
  709. }
  710. void EventRouter::DispatchEventWithLazyListener(const std::string& extension_id,
  711. std::unique_ptr<Event> event) {
  712. DCHECK(!extension_id.empty());
  713. const Extension* extension = ExtensionRegistry::Get(browser_context_)
  714. ->enabled_extensions()
  715. .GetByID(extension_id);
  716. if (!extension)
  717. return;
  718. const bool is_service_worker_based_background =
  719. BackgroundInfo::IsServiceWorkerBased(extension);
  720. std::string event_name = event->event_name;
  721. const bool has_listener = ExtensionHasEventListener(extension_id, event_name);
  722. if (!has_listener) {
  723. if (is_service_worker_based_background) {
  724. AddLazyListenerForServiceWorker(
  725. extension_id, Extension::GetBaseURLFromExtensionId(extension_id),
  726. event_name);
  727. } else {
  728. AddLazyEventListener(event_name, extension_id);
  729. }
  730. }
  731. DispatchEventToExtension(extension_id, std::move(event));
  732. if (!has_listener) {
  733. if (is_service_worker_based_background) {
  734. RemoveLazyListenerForServiceWorker(
  735. extension_id, Extension::GetBaseURLFromExtensionId(extension_id),
  736. event_name);
  737. } else {
  738. RemoveLazyEventListener(event_name, extension_id);
  739. }
  740. }
  741. }
  742. void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
  743. std::unique_ptr<Event> event) {
  744. DCHECK(event);
  745. // We don't expect to get events from a completely different browser context.
  746. DCHECK(!event->restrict_to_browser_context ||
  747. ExtensionsBrowserClient::Get()->IsSameContext(
  748. browser_context_, event->restrict_to_browser_context));
  749. // Don't dispatch events to observers if the browser is shutting down.
  750. if (browser_context_->ShutdownStarted())
  751. return;
  752. for (TestObserver& observer : test_observers_)
  753. observer.OnWillDispatchEvent(*event);
  754. std::set<const EventListener*> listeners(
  755. listeners_.GetEventListeners(*event));
  756. LazyEventDispatcher lazy_event_dispatcher(
  757. browser_context_, base::BindRepeating(&EventRouter::DispatchPendingEvent,
  758. weak_factory_.GetWeakPtr()));
  759. // We dispatch events for lazy background pages first because attempting to do
  760. // so will cause those that are being suspended to cancel that suspension.
  761. // As canceling a suspension entails sending an event to the affected
  762. // background page, and as that event needs to be delivered before we dispatch
  763. // the event we are dispatching here, we dispatch to the lazy listeners here
  764. // first.
  765. for (const EventListener* listener : listeners) {
  766. if (!restrict_to_extension_id.empty() &&
  767. restrict_to_extension_id != listener->extension_id()) {
  768. continue;
  769. }
  770. if (!listener->IsLazy())
  771. continue;
  772. lazy_event_dispatcher.Dispatch(
  773. *event, LazyContextIdForBrowserContext(browser_context_, listener),
  774. listener->filter());
  775. }
  776. for (const EventListener* listener : listeners) {
  777. if (!restrict_to_extension_id.empty() &&
  778. restrict_to_extension_id != listener->extension_id()) {
  779. continue;
  780. }
  781. if (listener->IsLazy())
  782. continue;
  783. if (lazy_event_dispatcher.HasAlreadyDispatched(
  784. LazyContextIdForListener(listener))) {
  785. continue;
  786. }
  787. DispatchEventToProcess(
  788. listener->extension_id(), listener->listener_url(), listener->process(),
  789. listener->service_worker_version_id(), listener->worker_thread_id(),
  790. *event, listener->filter(), false /* did_enqueue */);
  791. }
  792. }
  793. void EventRouter::DispatchEventToProcess(
  794. const std::string& extension_id,
  795. const GURL& listener_url,
  796. RenderProcessHost* process,
  797. int64_t service_worker_version_id,
  798. int worker_thread_id,
  799. const Event& event,
  800. const base::DictionaryValue* listener_filter,
  801. bool did_enqueue) {
  802. BrowserContext* listener_context = process->GetBrowserContext();
  803. ProcessMap* process_map = ProcessMap::Get(listener_context);
  804. // NOTE: |extension| being NULL does not necessarily imply that this event
  805. // shouldn't be dispatched. Events can be dispatched to WebUI and webviews as
  806. // well. It all depends on what GetMostLikelyContextType returns.
  807. const Extension* extension =
  808. ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
  809. extension_id);
  810. if (!extension && !extension_id.empty()) {
  811. // Trying to dispatch an event to an extension that doesn't exist. The
  812. // extension could have been removed, but we do not unregister it until the
  813. // extension process is unloaded.
  814. return;
  815. }
  816. if (extension) {
  817. // Extension-specific checks.
  818. // Firstly, if the event is for a URL, the Extension must have permission
  819. // to access that URL.
  820. if (!event.event_url.is_empty() &&
  821. event.event_url.host() != extension->id() && // event for self is ok
  822. !extension->permissions_data()
  823. ->active_permissions()
  824. .HasEffectiveAccessToURL(event.event_url)) {
  825. return;
  826. }
  827. // Secondly, if the event is for incognito mode, the Extension must be
  828. // enabled in incognito mode.
  829. if (!CanDispatchEventToBrowserContext(listener_context, extension, event)) {
  830. return;
  831. }
  832. }
  833. // TODO(ortuno): |listener_url| is passed in from the renderer so it can't
  834. // fully be trusted. We should retrieve the URL from the browser process.
  835. const GURL* url =
  836. service_worker_version_id == blink::mojom::kInvalidServiceWorkerVersionId
  837. ? &listener_url
  838. : nullptr;
  839. Feature::Context target_context =
  840. process_map->GetMostLikelyContextType(extension, process->GetID(), url);
  841. // We shouldn't be dispatching an event to a webpage, since all such events
  842. // (e.g. messaging) don't go through EventRouter.
  843. DCHECK_NE(Feature::WEB_PAGE_CONTEXT, target_context)
  844. << "Trying to dispatch event " << event.event_name << " to a webpage,"
  845. << " but this shouldn't be possible";
  846. Feature::Availability availability =
  847. ExtensionAPI::GetSharedInstance()->IsAvailable(
  848. event.event_name, extension, target_context, listener_url,
  849. CheckAliasStatus::ALLOWED,
  850. util::GetBrowserContextId(browser_context_));
  851. if (!availability.is_available()) {
  852. // It shouldn't be possible to reach here, because access is checked on
  853. // registration. However, for paranoia, check on dispatch as well.
  854. NOTREACHED() << "Trying to dispatch event " << event.event_name
  855. << " which the target does not have access to: "
  856. << availability.message();
  857. return;
  858. }
  859. std::unique_ptr<base::Value::List> modified_event_args;
  860. mojom::EventFilteringInfoPtr modified_event_filter_info;
  861. if (!event.will_dispatch_callback.is_null() &&
  862. !event.will_dispatch_callback.Run(
  863. listener_context, target_context, extension, listener_filter,
  864. &modified_event_args, &modified_event_filter_info)) {
  865. return;
  866. }
  867. base::Value::List event_args_to_use = modified_event_args
  868. ? std::move(*modified_event_args)
  869. : event.event_args.Clone();
  870. mojom::EventFilteringInfoPtr filter_info =
  871. modified_event_filter_info ? std::move(modified_event_filter_info)
  872. : event.filter_info.Clone();
  873. int event_id = g_extension_event_id.GetNext();
  874. DispatchExtensionMessage(process, worker_thread_id, listener_context,
  875. extension_id, event_id, event.event_name,
  876. std::move(event_args_to_use), event.user_gesture,
  877. std::move(filter_info));
  878. for (TestObserver& observer : test_observers_)
  879. observer.OnDidDispatchEventToProcess(event);
  880. // TODO(lazyboy): This is wrong for extensions SW events. We need to:
  881. // 1. Increment worker ref count
  882. // 2. Add EventAck IPC to decrement that ref count.
  883. if (extension) {
  884. ReportEvent(event.histogram_value, extension, did_enqueue);
  885. IncrementInFlightEvents(listener_context, process, extension, event_id,
  886. event.event_name, service_worker_version_id);
  887. }
  888. }
  889. // static
  890. void EventRouter::DoDispatchEventToSenderBookkeeping(
  891. content::BrowserContext* browser_context,
  892. const std::string& extension_id,
  893. int event_id,
  894. int render_process_id,
  895. int64_t service_worker_version_id,
  896. events::HistogramValue histogram_value,
  897. const std::string& event_name) {
  898. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  899. if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
  900. return;
  901. auto* registry = ExtensionRegistry::Get(browser_context);
  902. DCHECK(registry);
  903. const Extension* extension =
  904. registry->enabled_extensions().GetByID(extension_id);
  905. if (!extension)
  906. return;
  907. EventRouter* event_router = EventRouter::Get(browser_context);
  908. DCHECK(event_router);
  909. event_router->IncrementInFlightEvents(
  910. browser_context, RenderProcessHost::FromID(render_process_id), extension,
  911. event_id, event_name, service_worker_version_id);
  912. event_router->ReportEvent(histogram_value, extension, /*did_enqueue=*/false);
  913. }
  914. void EventRouter::IncrementInFlightEvents(BrowserContext* context,
  915. RenderProcessHost* process,
  916. const Extension* extension,
  917. int event_id,
  918. const std::string& event_name,
  919. int64_t service_worker_version_id) {
  920. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  921. // Only increment in-flight events if the lazy background page is active,
  922. // because that's the only time we'll get an ACK.
  923. if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
  924. ProcessManager* pm = ProcessManager::Get(context);
  925. ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
  926. if (host) {
  927. pm->IncrementLazyKeepaliveCount(extension, Activity::EVENT, event_name);
  928. host->OnBackgroundEventDispatched(event_name, event_id);
  929. }
  930. } else if (service_worker_version_id !=
  931. blink::mojom::kInvalidServiceWorkerVersionId) {
  932. // Check to make sure the rendered process hasn't gone away by the time
  933. // we've gotten here. (It's possible it has crashed, etc.) If that's
  934. // happened, we don't want to track the expected ACK, since we'll never
  935. // get it.
  936. if (process) {
  937. content::ServiceWorkerContext* service_worker_context =
  938. process->GetStoragePartition()->GetServiceWorkerContext();
  939. event_ack_data_.IncrementInflightEvent(
  940. service_worker_context, process->GetID(), service_worker_version_id,
  941. event_id);
  942. }
  943. }
  944. }
  945. void EventRouter::OnEventAck(BrowserContext* context,
  946. const std::string& extension_id,
  947. const std::string& event_name) {
  948. ProcessManager* pm = ProcessManager::Get(context);
  949. ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
  950. // The event ACK is routed to the background host, so this should never be
  951. // NULL.
  952. CHECK(host);
  953. // TODO(mpcomplete): We should never get this message unless
  954. // HasLazyBackgroundPage is true. Find out why we're getting it anyway.
  955. if (host->extension() &&
  956. BackgroundInfo::HasLazyBackgroundPage(host->extension()))
  957. pm->DecrementLazyKeepaliveCount(host->extension(), Activity::EVENT,
  958. event_name);
  959. }
  960. bool EventRouter::HasRegisteredEvents(const ExtensionId& extension_id) const {
  961. return !GetRegisteredEvents(extension_id, RegisteredEventType::kLazy)
  962. .empty() ||
  963. !GetRegisteredEvents(extension_id, RegisteredEventType::kServiceWorker)
  964. .empty();
  965. }
  966. void EventRouter::ReportEvent(events::HistogramValue histogram_value,
  967. const Extension* extension,
  968. bool did_enqueue) {
  969. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  970. // Record every event fired.
  971. UMA_HISTOGRAM_ENUMERATION("Extensions.Events.Dispatch", histogram_value,
  972. events::ENUM_BOUNDARY);
  973. bool is_component = Manifest::IsComponentLocation(extension->location());
  974. // Record events for component extensions. These should be kept to a minimum,
  975. // especially if they wake its event page. Component extensions should use
  976. // declarative APIs as much as possible.
  977. if (is_component) {
  978. UMA_HISTOGRAM_ENUMERATION("Extensions.Events.DispatchToComponent",
  979. histogram_value, events::ENUM_BOUNDARY);
  980. }
  981. // Record events for background pages, if any. The most important statistic
  982. // is DispatchWithSuspendedEventPage. Events reported there woke an event
  983. // page. Implementing either filtered or declarative versions of these events
  984. // should be prioritised.
  985. //
  986. // Note: all we know is that the extension *has* a persistent or event page,
  987. // not that the event is being dispatched *to* such a page. However, this is
  988. // academic, since extensions with any background page have that background
  989. // page running (or in the case of suspended event pages, must be started)
  990. // regardless of where the event is being dispatched. Events are dispatched
  991. // to a *process* not a *frame*.
  992. if (BackgroundInfo::HasPersistentBackgroundPage(extension)) {
  993. UMA_HISTOGRAM_ENUMERATION(
  994. "Extensions.Events.DispatchWithPersistentBackgroundPage",
  995. histogram_value, events::ENUM_BOUNDARY);
  996. } else if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
  997. if (did_enqueue) {
  998. UMA_HISTOGRAM_ENUMERATION(
  999. "Extensions.Events.DispatchWithSuspendedEventPage", histogram_value,
  1000. events::ENUM_BOUNDARY);
  1001. } else {
  1002. UMA_HISTOGRAM_ENUMERATION(
  1003. "Extensions.Events.DispatchWithRunningEventPage", histogram_value,
  1004. events::ENUM_BOUNDARY);
  1005. }
  1006. } else if (BackgroundInfo::IsServiceWorkerBased(extension)) {
  1007. base::UmaHistogramEnumeration(
  1008. "Extensions.Events.DispatchWithServiceWorkerBackground",
  1009. histogram_value, events::ENUM_BOUNDARY);
  1010. }
  1011. }
  1012. void EventRouter::DispatchPendingEvent(
  1013. std::unique_ptr<Event> event,
  1014. std::unique_ptr<LazyContextTaskQueue::ContextInfo> params) {
  1015. if (!params)
  1016. return;
  1017. DCHECK(event);
  1018. if (listeners_.HasProcessListener(params->render_process_host,
  1019. params->worker_thread_id,
  1020. params->extension_id)) {
  1021. DispatchEventToProcess(
  1022. params->extension_id, params->url, params->render_process_host,
  1023. params->service_worker_version_id, params->worker_thread_id, *event,
  1024. nullptr, true /* did_enqueue */);
  1025. }
  1026. }
  1027. void EventRouter::SetRegisteredEvents(const std::string& extension_id,
  1028. const std::set<std::string>& events,
  1029. RegisteredEventType type) {
  1030. base::Value events_value(base::Value::Type::LIST);
  1031. for (auto iter = events.cbegin(); iter != events.cend(); ++iter) {
  1032. events_value.Append(*iter);
  1033. }
  1034. const char* pref_key = type == RegisteredEventType::kLazy
  1035. ? kRegisteredLazyEvents
  1036. : kRegisteredServiceWorkerEvents;
  1037. extension_prefs_->UpdateExtensionPref(
  1038. extension_id, pref_key,
  1039. base::Value::ToUniquePtrValue(std::move(events_value)));
  1040. }
  1041. void EventRouter::AddFilterToEvent(const std::string& event_name,
  1042. const std::string& extension_id,
  1043. bool is_for_service_worker,
  1044. const DictionaryValue* filter) {
  1045. ExtensionPrefs::ScopedDictionaryUpdate update(
  1046. extension_prefs_, extension_id,
  1047. is_for_service_worker ? kFilteredServiceWorkerEvents : kFilteredEvents);
  1048. auto filtered_events = update.Create();
  1049. base::Value::List* filter_list = nullptr;
  1050. if (!filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) {
  1051. filtered_events->SetKey(event_name, base::Value(base::Value::List()));
  1052. filtered_events->GetListWithoutPathExpansion(event_name, &filter_list);
  1053. }
  1054. filter_list->Append(filter->Clone());
  1055. }
  1056. void EventRouter::OnExtensionLoaded(content::BrowserContext* browser_context,
  1057. const Extension* extension) {
  1058. // Add all registered lazy listeners to our cache.
  1059. std::set<std::string> registered_events =
  1060. GetRegisteredEvents(extension->id(), RegisteredEventType::kLazy);
  1061. listeners_.LoadUnfilteredLazyListeners(extension->id(), registered_events);
  1062. std::set<std::string> registered_worker_events =
  1063. GetRegisteredEvents(extension->id(), RegisteredEventType::kServiceWorker);
  1064. listeners_.LoadUnfilteredWorkerListeners(extension->id(),
  1065. registered_worker_events);
  1066. const DictionaryValue* filtered_events =
  1067. GetFilteredEvents(extension->id(), RegisteredEventType::kLazy);
  1068. if (filtered_events)
  1069. listeners_.LoadFilteredLazyListeners(
  1070. extension->id(), false /* is_for_service_worker */, *filtered_events);
  1071. const DictionaryValue* filtered_worker_events =
  1072. GetFilteredEvents(extension->id(), RegisteredEventType::kServiceWorker);
  1073. if (filtered_worker_events)
  1074. listeners_.LoadFilteredLazyListeners(extension->id(),
  1075. true /* is_for_service_worker */,
  1076. *filtered_worker_events);
  1077. }
  1078. void EventRouter::OnExtensionUnloaded(content::BrowserContext* browser_context,
  1079. const Extension* extension,
  1080. UnloadedExtensionReason reason) {
  1081. // Remove all registered listeners from our cache.
  1082. listeners_.RemoveListenersForExtension(extension->id());
  1083. }
  1084. void EventRouter::AddLazyEventListenerImpl(
  1085. std::unique_ptr<EventListener> listener,
  1086. RegisteredEventType type) {
  1087. const ExtensionId extension_id = listener->extension_id();
  1088. const std::string event_name = listener->event_name();
  1089. bool is_new = listeners_.AddListener(std::move(listener));
  1090. if (is_new) {
  1091. std::set<std::string> events = GetRegisteredEvents(extension_id, type);
  1092. bool prefs_is_new = events.insert(event_name).second;
  1093. if (prefs_is_new)
  1094. SetRegisteredEvents(extension_id, events, type);
  1095. }
  1096. }
  1097. void EventRouter::RemoveLazyEventListenerImpl(
  1098. std::unique_ptr<EventListener> listener,
  1099. RegisteredEventType type) {
  1100. const ExtensionId extension_id = listener->extension_id();
  1101. const std::string event_name = listener->event_name();
  1102. bool did_exist = listeners_.RemoveListener(listener.get());
  1103. if (did_exist) {
  1104. std::set<std::string> events = GetRegisteredEvents(extension_id, type);
  1105. bool prefs_did_exist = events.erase(event_name) > 0;
  1106. DCHECK(prefs_did_exist);
  1107. SetRegisteredEvents(extension_id, events, type);
  1108. }
  1109. }
  1110. Event::Event(events::HistogramValue histogram_value,
  1111. const std::string& event_name,
  1112. base::Value::List event_args)
  1113. : Event(histogram_value, event_name, std::move(event_args), nullptr) {}
  1114. Event::Event(events::HistogramValue histogram_value,
  1115. const std::string& event_name,
  1116. base::Value::List event_args,
  1117. content::BrowserContext* restrict_to_browser_context)
  1118. : Event(histogram_value,
  1119. event_name,
  1120. std::move(event_args),
  1121. restrict_to_browser_context,
  1122. GURL(),
  1123. EventRouter::USER_GESTURE_UNKNOWN,
  1124. mojom::EventFilteringInfo::New()) {}
  1125. Event::Event(events::HistogramValue histogram_value,
  1126. const std::string& event_name,
  1127. base::Value::List event_args_tmp,
  1128. content::BrowserContext* restrict_to_browser_context,
  1129. const GURL& event_url,
  1130. EventRouter::UserGestureState user_gesture,
  1131. mojom::EventFilteringInfoPtr info)
  1132. : histogram_value(histogram_value),
  1133. event_name(event_name),
  1134. event_args(std::move(event_args_tmp)),
  1135. restrict_to_browser_context(restrict_to_browser_context),
  1136. event_url(event_url),
  1137. user_gesture(user_gesture),
  1138. filter_info(std::move(info)) {
  1139. DCHECK_NE(events::UNKNOWN, histogram_value)
  1140. << "events::UNKNOWN cannot be used as a histogram value.\n"
  1141. << "If this is a test, use events::FOR_TEST.\n"
  1142. << "If this is production code, it is important that you use a realistic "
  1143. << "value so that we can accurately track event usage. "
  1144. << "See extension_event_histogram_value.h for inspiration.";
  1145. }
  1146. Event::~Event() = default;
  1147. std::unique_ptr<Event> Event::DeepCopy() const {
  1148. auto copy =
  1149. std::make_unique<Event>(histogram_value, event_name, event_args.Clone(),
  1150. restrict_to_browser_context, event_url,
  1151. user_gesture, filter_info.Clone());
  1152. copy->will_dispatch_callback = will_dispatch_callback;
  1153. return copy;
  1154. }
  1155. EventListenerInfo::EventListenerInfo(const std::string& event_name,
  1156. const std::string& extension_id,
  1157. const GURL& listener_url,
  1158. content::BrowserContext* browser_context)
  1159. : event_name(event_name),
  1160. extension_id(extension_id),
  1161. listener_url(listener_url),
  1162. browser_context(browser_context),
  1163. worker_thread_id(kMainThreadId),
  1164. service_worker_version_id(blink::mojom::kInvalidServiceWorkerVersionId) {}
  1165. EventListenerInfo::EventListenerInfo(const std::string& event_name,
  1166. const std::string& extension_id,
  1167. const GURL& listener_url,
  1168. content::BrowserContext* browser_context,
  1169. int worker_thread_id,
  1170. int64_t service_worker_version_id)
  1171. : event_name(event_name),
  1172. extension_id(extension_id),
  1173. listener_url(listener_url),
  1174. browser_context(browser_context),
  1175. worker_thread_id(worker_thread_id),
  1176. service_worker_version_id(service_worker_version_id) {}
  1177. } // namespace extensions