event_router.cc revision 010d83a9304c5a91596085d917d248abff47903a
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/api_activity_monitor.h" 1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/extensions_browser_client.h" 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/browser/lazy_background_task_queue.h" 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/process_manager.h" 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/process_map.h" 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "extensions/common/extension_api.h" 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/extension_messages.h" 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/extension_urls.h" 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/background_info.h" 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/incognito_info.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using base::DictionaryValue; 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using base::ListValue; 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using content::BrowserContext; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void DoNothing(ExtensionHost* host) {} 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// A dictionary of event names to lists of filters that this extension has 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// registered from its lazy background page. 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kFilteredEvents[] = "filtered_events"; 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Sends a notification about an event to the API activity monitor on the 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// UI thread. Can be called from any thread. 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotifyApiEventDispatched(void* browser_context_id, 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extension_id, 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& event_name, 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ListValue> args) { 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The ApiActivityMonitor can only be accessed from the UI thread. 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::PostTask( 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserThread::UI, 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&NotifyApiEventDispatched, 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) browser_context_id, 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_id, 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) event_name, 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&args))); 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Notify the ApiActivityMonitor about the event dispatch. 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BrowserContext* context = static_cast<BrowserContext*>(browser_context_id); 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ExtensionsBrowserClient::Get()->IsValidContext(context)) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ApiActivityMonitor* monitor = 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionsBrowserClient::Get()->GetApiActivityMonitor(context); 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (monitor) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) monitor->OnApiEventDispatched(extension_id, event_name, args.Pass()); 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char EventRouter::kRegisteredEvents[] = "events"; 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct EventRouter::ListenerProcess { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* process; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extension_id; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListenerProcess(content::RenderProcessHost* process, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : process(process), extension_id(extension_id) {} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operator<(const ListenerProcess& that) const { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process < that.process) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process == that.process && extension_id < that.extension_id) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender, 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void* browser_context_id, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListValue* event_args, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserGestureState user_gesture, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EventFilteringInfo& info) { 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotifyApiEventDispatched(browser_context_id, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_id, 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) event_name, 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) make_scoped_ptr(event_args->DeepCopy())); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListValue args; 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) args.Set(0, new base::StringValue(event_name)); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.Set(1, event_args); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.Set(2, info.AsValue().release()); 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ipc_sender->Send(new ExtensionMsg_MessageInvoke( 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MSG_ROUTING_CONTROL, 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_id, 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) kEventBindings, 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "dispatchEvent", 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) args, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_gesture == USER_GESTURE_ENABLED)); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DispatchExtensionMessage does _not_ take ownership of event_args, so we 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must ensure that the destruction of args does not attempt to free it. 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::Value> removed_event_args; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.Remove(1, &removed_event_args); 1273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch ignore_result(removed_event_args.release()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 131effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochEventRouter* EventRouter::Get(content::BrowserContext* browser_context) { 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return ExtensionSystem::Get(browser_context)->event_router(); 133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string EventRouter::GetBaseEventName(const std::string& full_event_name) { 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t slash_sep = full_event_name.find('/'); 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return full_event_name.substr(0, slash_sep); 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchEvent(IPC::Sender* ipc_sender, 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void* browser_context_id, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> event_args, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserGestureState user_gesture, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EventFilteringInfo& info) { 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DispatchExtensionMessage(ipc_sender, 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_context_id, 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_id, 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event_name, 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event_args.get(), 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) user_gesture, 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) info); 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BrowserThread::PostTask( 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BrowserThread::UI, 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FROM_HERE, 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&EventRouter::IncrementInFlightEventsOnUI, 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_context_id, 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension_id)); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)EventRouter::EventRouter(BrowserContext* browser_context, 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ExtensionPrefs* extension_prefs) 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : browser_context_(browser_context), 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_(extension_prefs), 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) listeners_(this) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::AllSources()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::AllSources()); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED, 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::Source<BrowserContext>(browser_context_)); 1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch registrar_.Add(this, 1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::Source<BrowserContext>(browser_context_)); 17923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::Source<BrowserContext>(browser_context_)); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventRouter::~EventRouter() {} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::AddEventListener(const std::string& event_name, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* process, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_name, extension_id, process, scoped_ptr<DictionaryValue>()))); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::RemoveEventListener(const std::string& event_name, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* process, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventListener listener(event_name, extension_id, process, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<DictionaryValue>()); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.RemoveListener(&listener); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::RegisterObserver(Observer* observer, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name) { 202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Observing sub-event names like "foo.onBar/123" is not allowed. 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(event_name.find('/') == std::string::npos); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_[event_name] = observer; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::UnregisterObserver(Observer* observer) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ObserverMap::iterator> iters_to_remove; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ObserverMap::iterator iter = observers_.begin(); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != observers_.end(); ++iter) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->second == observer) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iters_to_remove.push_back(iter); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < iters_to_remove.size(); ++i) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.erase(iters_to_remove[i]); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::OnListenerAdded(const EventListener* listener) { 219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const EventListenerInfo details(listener->event_name(), 220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) listener->extension_id(), 221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) listener->GetBrowserContext()); 222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::string base_event_name = GetBaseEventName(listener->event_name()); 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ObserverMap::iterator observer = observers_.find(base_event_name); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer != observers_.end()) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer->second->OnListenerAdded(details); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::OnListenerRemoved(const EventListener* listener) { 229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const EventListenerInfo details(listener->event_name(), 230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) listener->extension_id(), 231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) listener->GetBrowserContext()); 232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::string base_event_name = GetBaseEventName(listener->event_name()); 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ObserverMap::iterator observer = observers_.find(base_event_name); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (observer != observers_.end()) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer->second->OnListenerRemoved(details); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::AddLazyEventListener(const std::string& event_name, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<EventListener> listener(new EventListener( 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_name, extension_id, NULL, scoped_ptr<DictionaryValue>())); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_new = listeners_.AddListener(listener.Pass()); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_new) { 24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::set<std::string> events = GetRegisteredEvents(extension_id); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool prefs_is_new = events.insert(event_name).second; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prefs_is_new) 24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetRegisteredEvents(extension_id, events); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::RemoveLazyEventListener(const std::string& event_name, 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventListener listener(event_name, extension_id, NULL, 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<DictionaryValue>()); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool did_exist = listeners_.RemoveListener(&listener); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (did_exist) { 25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::set<std::string> events = GetRegisteredEvents(extension_id); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool prefs_did_exist = events.erase(event_name) > 0; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(prefs_did_exist); 26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SetRegisteredEvents(extension_id, events); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::AddFilteredEventListener(const std::string& event_name, 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* process, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue& filter, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool add_lazy_listener) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_name, extension_id, process, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<DictionaryValue>(filter.DeepCopy())))); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (add_lazy_listener) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool added = listeners_.AddListener(scoped_ptr<EventListener>( 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new EventListener(event_name, extension_id, NULL, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<DictionaryValue>(filter.DeepCopy())))); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (added) 28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AddFilterToEvent(event_name, extension_id, &filter); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::RemoveFilteredEventListener( 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* process, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue& filter, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool remove_lazy_listener) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventListener listener(event_name, extension_id, process, 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<DictionaryValue>(filter.DeepCopy())); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.RemoveListener(&listener); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (remove_lazy_listener) { 297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) listener.MakeLazy(); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool removed = listeners_.RemoveListener(&listener); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (removed) 30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) RemoveFilterFromEvent(event_name, extension_id, &filter); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EventRouter::HasEventListener(const std::string& event_name) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return listeners_.HasListenerForEvent(event_name); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EventRouter::ExtensionHasEventListener(const std::string& extension_id, 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return listeners_.HasListenerForExtension(extension_id, event_name); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EventRouter::HasEventListenerImpl(const ListenerMap& listener_map, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& event_name) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListenerMap::const_iterator it = listener_map.find(event_name); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == listener_map.end()) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<ListenerProcess>& listeners = it->second; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension_id.empty()) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !listeners.empty(); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener != listeners.end(); ++listener) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (listener->extension_id == extension_id) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::set<std::string> EventRouter::GetRegisteredEvents( 33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id) { 33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::set<std::string> events; 33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const ListValue* events_value = NULL; 33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!extension_prefs_ || 339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) !extension_prefs_->ReadPrefAsList( 340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_id, kRegisteredEvents, &events_value)) { 34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return events; 34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 0; i < events_value->GetSize(); ++i) { 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string event; 34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (events_value->GetString(i, &event)) 34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) events.insert(event); 34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return events; 35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EventRouter::SetRegisteredEvents(const std::string& extension_id, 35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::set<std::string>& events) { 35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ListValue* events_value = new ListValue; 35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (std::set<std::string>::const_iterator iter = events.begin(); 35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) iter != events.end(); ++iter) { 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) events_value->Append(new base::StringValue(*iter)); 35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_->UpdateExtensionPref( 360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_id, kRegisteredEvents, events_value); 36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EventRouter::AddFilterToEvent(const std::string& event_name, 36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id, 36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DictionaryValue* filter) { 36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionPrefs::ScopedDictionaryUpdate update( 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_, extension_id, kFilteredEvents); 36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DictionaryValue* filtered_events = update.Get(); 36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!filtered_events) 37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) filtered_events = update.Create(); 37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ListValue* filter_list = NULL; 37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!filtered_events->GetList(event_name, &filter_list)) { 37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) filter_list = new ListValue; 37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) filtered_events->SetWithoutPathExpansion(event_name, filter_list); 37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) filter_list->Append(filter->DeepCopy()); 37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EventRouter::RemoveFilterFromEvent(const std::string& event_name, 38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id, 38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DictionaryValue* filter) { 38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionPrefs::ScopedDictionaryUpdate update( 385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_, extension_id, kFilteredEvents); 38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DictionaryValue* filtered_events = update.Get(); 38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ListValue* filter_list = NULL; 38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!filtered_events || 38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !filtered_events->GetListWithoutPathExpansion(event_name, &filter_list)) { 39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 0; i < filter_list->GetSize(); i++) { 39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DictionaryValue* filter = NULL; 39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CHECK(filter_list->GetDictionary(i, &filter)); 39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (filter->Equals(filter)) { 39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) filter_list->Remove(i, NULL); 39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const DictionaryValue* EventRouter::GetFilteredEvents( 40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id) { 40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DictionaryValue* events = NULL; 406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_prefs_->ReadPrefAsDictionary( 40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extension_id, kFilteredEvents, &events); 40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return events; 40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EventRouter::BroadcastEvent(scoped_ptr<Event> event) { 412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DispatchEventImpl(std::string(), linked_ptr<Event>(event.release())); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchEventToExtension(const std::string& extension_id, 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<Event> event) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!extension_id.empty()); 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchEventImpl(extension_id, linked_ptr<Event>(event.release())); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 421ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid EventRouter::DispatchEventWithLazyListener(const std::string& extension_id, 422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<Event> event) { 423ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(!extension_id.empty()); 424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch std::string event_name = event->event_name; 425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool has_listener = ExtensionHasEventListener(extension_id, event_name); 426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!has_listener) 427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AddLazyEventListener(event_name, extension_id); 428ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DispatchEventToExtension(extension_id, event.Pass()); 429ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!has_listener) 430ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch RemoveLazyEventListener(event_name, extension_id); 431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 432ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id, 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const linked_ptr<Event>& event) { 435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We don't expect to get events from a completely different browser context. 436f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!event->restrict_to_browser_context || 437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ExtensionsBrowserClient::Get()->IsSameContext( 438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_context_, event->restrict_to_browser_context)); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<const EventListener*> listeners( 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.GetEventListeners(*event)); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<EventDispatchIdentifier> already_dispatched; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We dispatch events for lazy background pages first because attempting to do 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so will cause those that are being suspended to cancel that suspension. 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As canceling a suspension entails sending an event to the affected 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // background page, and as that event needs to be delivered before we dispatch 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the event we are dispatching here, we dispatch to the lazy listeners here 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<const EventListener*>::iterator it = listeners.begin(); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != listeners.end(); it++) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EventListener* listener = *it; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (restrict_to_extension_id.empty() || 455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) restrict_to_extension_id == listener->extension_id()) { 456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (listener->IsLazy()) { 457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DispatchLazyEvent(listener->extension_id(), event, &already_dispatched); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<const EventListener*>::iterator it = listeners.begin(); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != listeners.end(); it++) { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EventListener* listener = *it; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (restrict_to_extension_id.empty() || 466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) restrict_to_extension_id == listener->extension_id()) { 467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (listener->process()) { 468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(), 469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) listener->extension_id()); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ContainsKey(already_dispatched, dispatch_id)) { 471010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DispatchEventToProcess( 472010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) listener->extension_id(), listener->process(), event); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchLazyEvent( 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const linked_ptr<Event>& event, 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<EventDispatchIdentifier>* already_dispatched) { 483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Check both the original and the incognito browser context to see if we 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should load a lazy bg page to handle the event. The latter case 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // occurs in the case of split-mode extensions. 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Extension* extension = 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID( 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_id); 489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!extension) 490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (MaybeLoadLazyBackgroundPageToDispatchEvent( 493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_context_, extension, event)) { 494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) already_dispatched->insert(std::make_pair(browser_context_, extension_id)); 495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get(); 498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (browser_client->HasOffTheRecordContext(browser_context_) && 499f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) IncognitoInfo::IsSplitMode(extension)) { 500f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserContext* incognito_context = 501f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_client->GetOffTheRecordContext(browser_context_); 502f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (MaybeLoadLazyBackgroundPageToDispatchEvent( 503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) incognito_context, extension, event)) { 504f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) already_dispatched->insert( 505f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::make_pair(incognito_context, extension_id)); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchEventToProcess(const std::string& extension_id, 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* process, 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const linked_ptr<Event>& event) { 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Extension* extension = 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID( 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_id); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The extension could have been removed, but we do not unregister it until 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the extension process is unloaded. 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 522f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserContext* listener_context = process->GetBrowserContext(); 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProcessMap* process_map = ProcessMap::Get(listener_context); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the event is privileged, only send to extension processes. Otherwise, 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it's OK to send to normal renderers (e.g., for content scripts). 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !process_map->Contains(extension->id(), process->GetID())) { 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // If the event is restricted to a URL, only dispatch if the extension has 532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // permission for it (or if the event originated from itself). 533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!event->event_url.is_empty() && 534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) event->event_url.host() != extension->id() && 535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) !extension->GetActivePermissions()->HasEffectiveAccessToURL( 536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) event->event_url)) { 537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 540f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!CanDispatchEventToBrowserContext(listener_context, extension, event)) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event->will_dispatch_callback.is_null()) { 544f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event->will_dispatch_callback.Run(listener_context, extension, 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->event_args.get()); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 548f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DispatchExtensionMessage(process, listener_context, extension->id(), 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->event_name, event->event_args.get(), 550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) event->user_gesture, event->filter_info); 551f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) IncrementInFlightEvents(listener_context, extension); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 554f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool EventRouter::CanDispatchEventToBrowserContext( 555f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserContext* context, 556f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const Extension* extension, 557f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const linked_ptr<Event>& event) { 558f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Is this event from a different browser context than the renderer (ie, an 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // incognito tab event sent to a normal process, or vice versa). 560f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool cross_incognito = event->restrict_to_browser_context && 561f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) context != event->restrict_to_browser_context; 562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!cross_incognito) 563f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito( 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension, context); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent( 569f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserContext* context, 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const linked_ptr<Event>& event) { 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extension->is_ephemeral() && !event->can_load_ephemeral_apps) { 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Most events can only be dispatched to ephemeral apps that are already 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // running. 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProcessManager* pm = ExtensionSystem::Get(context)->process_manager(); 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!pm->GetBackgroundHostForExtension(extension->id())) 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!CanDispatchEventToBrowserContext(context, extension, event)) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LazyBackgroundTaskQueue* queue = ExtensionSystem::Get( 584f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) context)->lazy_background_task_queue(); 585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (queue->ShouldEnqueueTask(context, extension)) { 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) linked_ptr<Event> dispatched_event(event); 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there's a dispatch callback, call it now (rather than dispatch time) 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to avoid lifetime issues. Use a separate copy of the event args, so they 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // last until the event is dispatched. 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event->will_dispatch_callback.is_null()) { 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatched_event.reset(event->DeepCopy()); 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatched_event->will_dispatch_callback.Run( 594f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) context, extension, dispatched_event->event_args.get()); 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ensure we don't call it again at dispatch time. 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatched_event->will_dispatch_callback.Reset(); 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 599f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) queue->AddPendingTask(context, extension->id(), 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&EventRouter::DispatchPendingEvent, 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this), dispatched_event)); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 60890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static 60990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EventRouter::IncrementInFlightEventsOnUI( 610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void* browser_context_id, 61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& extension_id) { 612effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserContext* browser_context = 614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) reinterpret_cast<BrowserContext*>(browser_context_id); 615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context)) 6167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 6170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EventRouter* event_router = EventRouter::Get(browser_context); 61890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!event_router) 61990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 62090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const Extension* extension = 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID( 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_id); 62390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!extension) 62490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event_router->IncrementInFlightEvents(browser_context, extension); 62690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 62790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void EventRouter::IncrementInFlightEvents(BrowserContext* context, 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only increment in-flight events if the lazy background page is active, 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because that's the only time we'll get an ACK. 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (BackgroundInfo::HasLazyBackgroundPage(extension)) { 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProcessManager* pm = ExtensionSystem::Get(context)->process_manager(); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id()); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pm->IncrementLazyKeepaliveCount(extension); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void EventRouter::OnEventAck(BrowserContext* context, 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& extension_id) { 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProcessManager* pm = ExtensionSystem::Get(context)->process_manager(); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The event ACK is routed to the background host, so this should never be 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NULL. 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(host); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mpcomplete): We should never get this message unless 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HasLazyBackgroundPage is true. Find out why we're getting it anyway. 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (host->extension() && 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BackgroundInfo::HasLazyBackgroundPage(host->extension())) 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pm->DecrementLazyKeepaliveCount(host->extension()); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event, 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionHost* host) { 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!host) 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (listeners_.HasProcessListener(host->render_process_host(), 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->extension()->id())) { 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DispatchEventToProcess(host->extension()->id(), 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->render_process_host(), event); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EventRouter::Observe(int type, 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* renderer = 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<content::RenderProcessHost>(source).ptr(); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove all event listeners associated with this renderer. 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.RemoveListenersForProcess(renderer); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case chrome::NOTIFICATION_EXTENSION_ENABLED: { 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the extension has a lazy background page, make sure it gets loaded 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to register the events the extension is interested in. 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension = 6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Details<const Extension>(details).ptr(); 6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (BackgroundInfo::HasLazyBackgroundPage(extension)) { 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LazyBackgroundTaskQueue* queue = ExtensionSystem::Get( 685f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_context_)->lazy_background_task_queue(); 686f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) queue->AddPendingTask(browser_context_, extension->id(), 6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&DoNothing)); 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: { 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add all registered lazy listeners to our cache. 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Details<const Extension>(details).ptr(); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> registered_events = 69690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GetRegisteredEvents(extension->id()); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.LoadUnfilteredLazyListeners(extension->id(), 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registered_events); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryValue* filtered_events = 70090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GetFilteredEvents(extension->id()); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filtered_events) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.LoadFilteredLazyListeners(extension->id(), *filtered_events); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 70523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove all registered lazy listeners from our cache. 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnloadedExtensionInfo* unloaded = 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Details<UnloadedExtensionInfo>(details).ptr(); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listeners_.RemoveLazyListenersForExtension(unloaded->extension->id()); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Event::Event(const std::string& event_name, 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::ListValue> event_args) 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : event_name(event_name), 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_args(event_args.Pass()), 722f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) restrict_to_browser_context(NULL), 7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_gesture(EventRouter::USER_GESTURE_UNKNOWN), 7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) can_load_ephemeral_apps(false) { 7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(this->event_args.get()); 7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Event::Event(const std::string& event_name, 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::ListValue> event_args, 730f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserContext* restrict_to_browser_context) 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : event_name(event_name), 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_args(event_args.Pass()), 733f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) restrict_to_browser_context(restrict_to_browser_context), 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_gesture(EventRouter::USER_GESTURE_UNKNOWN), 7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) can_load_ephemeral_apps(false) { 7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(this->event_args.get()); 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Event::Event(const std::string& event_name, 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> event_args, 741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserContext* restrict_to_browser_context, 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& event_url, 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EventRouter::UserGestureState user_gesture, 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const EventFilteringInfo& filter_info) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : event_name(event_name), 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_args(event_args.Pass()), 747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) restrict_to_browser_context(restrict_to_browser_context), 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_url(event_url), 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_gesture(user_gesture), 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) filter_info(filter_info), 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) can_load_ephemeral_apps(false) { 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(this->event_args.get()); 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Event::~Event() {} 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Event* Event::DeepCopy() { 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Event* copy = new Event(event_name, 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::ListValue>(event_args->DeepCopy()), 760f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) restrict_to_browser_context, 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_url, 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_gesture, 7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) filter_info); 7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) copy->will_dispatch_callback = will_dispatch_callback; 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return copy; 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)EventListenerInfo::EventListenerInfo(const std::string& event_name, 769f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& extension_id, 770f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::BrowserContext* browser_context) 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : event_name(event_name), 772f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) extension_id(extension_id), 773f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) browser_context(browser_context) {} 774f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 776