Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: chrome/browser/extensions/extension_event_router.cc

Issue 10514013: Filtered events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: split out event_filter changes Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_event_router.h" 5 #include "chrome/browser/extensions/extension_event_router.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/values.h" 10 #include "base/values.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 58
59 bool operator<(const ListenerProcess& that) const { 59 bool operator<(const ListenerProcess& that) const {
60 if (process < that.process) 60 if (process < that.process)
61 return true; 61 return true;
62 if (process == that.process && extension_id < that.extension_id) 62 if (process == that.process && extension_id < that.extension_id)
63 return true; 63 return true;
64 return false; 64 return false;
65 } 65 }
66 }; 66 };
67 67
68 struct ExtensionEventRouter::ExtensionEvent {
69 std::string event_name;
70 std::string event_args;
71 GURL event_url;
72 Profile* restrict_to_profile;
73 std::string cross_incognito_args;
74 UserGestureState user_gesture;
75
76 ExtensionEvent(const std::string& event_name,
77 const std::string& event_args,
78 const GURL& event_url,
79 Profile* restrict_to_profile,
80 const std::string& cross_incognito_args,
81 UserGestureState user_gesture)
82 : event_name(event_name),
83 event_args(event_args),
84 event_url(event_url),
85 restrict_to_profile(restrict_to_profile),
86 cross_incognito_args(cross_incognito_args),
87 user_gesture(user_gesture) {}
88 };
89
90 // static 68 // static
91 void ExtensionEventRouter::DispatchEvent(IPC::Message::Sender* ipc_sender, 69 void ExtensionEventRouter::DispatchEvent(IPC::Message::Sender* ipc_sender,
92 const std::string& extension_id, 70 const std::string& extension_id,
93 const std::string& event_name, 71 const std::string& event_name,
94 const std::string& event_args, 72 const std::string& event_args,
95 const GURL& event_url, 73 const GURL& event_url,
96 UserGestureState user_gesture) { 74 UserGestureState user_gesture,
75 extensions::EventFilteringInfo info) {
97 ListValue args; 76 ListValue args;
98 args.Set(0, Value::CreateStringValue(event_name)); 77 args.Set(0, Value::CreateStringValue(event_name));
99 args.Set(1, Value::CreateStringValue(event_args)); 78 args.Set(1, Value::CreateStringValue(event_args));
79 args.Set(2, Value::CreateStringValue(info.AsJSONString()));
100 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, 80 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL,
101 extension_id, kDispatchEvent, args, event_url, 81 extension_id, kDispatchEvent, args, event_url,
102 user_gesture == USER_GESTURE_ENABLED)); 82 user_gesture == USER_GESTURE_ENABLED));
103 } 83 }
104 84
105 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) 85 ExtensionEventRouter::ExtensionEventRouter(Profile* profile)
106 : profile_(profile), 86 : profile_(profile),
107 extension_devtools_manager_( 87 extension_devtools_manager_(
108 ExtensionSystem::Get(profile)->devtools_manager()) { 88 ExtensionSystem::Get(profile)->devtools_manager()) {
109 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 89 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
110 content::NotificationService::AllSources()); 90 content::NotificationService::AllSources());
111 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, 91 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
112 content::NotificationService::AllSources()); 92 content::NotificationService::AllSources());
113 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 93 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
114 content::Source<Profile>(profile_)); 94 content::Source<Profile>(profile_));
115 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 95 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
116 content::Source<Profile>(profile_)); 96 content::Source<Profile>(profile_));
117 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, 97 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
118 content::Source<Profile>(profile_)); 98 content::Source<Profile>(profile_));
119 } 99 }
120 100
121 ExtensionEventRouter::~ExtensionEventRouter() {} 101 ExtensionEventRouter::~ExtensionEventRouter() {}
122 102
123 void ExtensionEventRouter::AddEventListener( 103 void ExtensionEventRouter::AddEventListener(
124 const std::string& event_name, 104 const std::string& event_name,
125 content::RenderProcessHost* process, 105 content::RenderProcessHost* process,
126 const std::string& extension_id) { 106 const std::string& extension_id) {
127 ListenerProcess listener(process, extension_id); 107 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
128 DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name; 108 event_name, extension_id, process, scoped_ptr<DictionaryValue>())));
129 listeners_[event_name].insert(listener);
130 109
131 if (extension_devtools_manager_.get()) 110 if (extension_devtools_manager_.get())
132 extension_devtools_manager_->AddEventListener(event_name, 111 extension_devtools_manager_->AddEventListener(event_name,
133 process->GetID()); 112 process->GetID());
134 113
135 // We lazily tell the TaskManager to start updating when listeners to the 114 // We lazily tell the TaskManager to start updating when listeners to the
136 // processes.onUpdated or processes.onUpdatedWithMemory events arrive. 115 // processes.onUpdated or processes.onUpdatedWithMemory events arrive.
137 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || 116 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 ||
138 event_name.compare( 117 event_name.compare(
139 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) 118 extension_processes_api_constants::kOnUpdatedWithMemory) == 0)
140 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded(); 119 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded();
141 } 120 }
142 121
143 void ExtensionEventRouter::RemoveEventListener( 122 void ExtensionEventRouter::RemoveEventListener(
144 const std::string& event_name, 123 const std::string& event_name,
145 content::RenderProcessHost* process, 124 content::RenderProcessHost* process,
146 const std::string& extension_id) { 125 const std::string& extension_id) {
147 ListenerProcess listener(process, extension_id); 126 scoped_ptr<EventListener> listener(new EventListener(
148 DCHECK_EQ(listeners_[event_name].count(listener), 1u) << 127 event_name, extension_id, process, scoped_ptr<DictionaryValue>()));
149 " PID=" << process->GetID() << " extension=" << extension_id << 128 std::string id = extension_id;
Matt Perry 2012/06/13 01:24:27 unused
koz (OOO until 15th September) 2012/06/14 02:15:55 Done.
150 " event=" << event_name; 129 OnListenerRemoved(listener.get());
151 listeners_[event_name].erase(listener); 130 listeners_.RemoveListener(listener.Pass());
152 // Note: extension_id may point to data in the now-deleted listeners_ object. 131 }
153 // Do not use.
154 132
133 void ExtensionEventRouter::OnListenerRemoved(const EventListener* listener) {
134 // We don't care about lazy events being removed.
135 if (!listener->process)
136 return;
137
138 const std::string& event_name = listener->event_name;
155 if (extension_devtools_manager_.get()) 139 if (extension_devtools_manager_.get())
156 extension_devtools_manager_->RemoveEventListener(event_name, 140 extension_devtools_manager_->RemoveEventListener(
157 process->GetID()); 141 event_name, listener->process->GetID());
158 142
159 // If a processes.onUpdated or processes.onUpdatedWithMemory event listener 143 // If a processes.onUpdated or processes.onUpdatedWithMemory event listener
160 // is removed (or a process with one exits), then we let the extension API 144 // is removed (or a process with one exits), then we let the extension API
161 // know that it has one fewer listener. 145 // know that it has one fewer listener.
162 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || 146 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 ||
163 event_name.compare( 147 event_name.compare(
164 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) 148 extension_processes_api_constants::kOnUpdatedWithMemory) == 0)
165 ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved(); 149 ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved();
166 150
167 BrowserThread::PostTask( 151 BrowserThread::PostTask(
168 BrowserThread::IO, FROM_HERE, 152 BrowserThread::IO, FROM_HERE,
169 base::Bind( 153 base::Bind(
170 &NotifyEventListenerRemovedOnIOThread, 154 &NotifyEventListenerRemovedOnIOThread,
171 profile_, listener.extension_id, event_name)); 155 profile_, listener->extension_id, listener->event_name));
172 } 156 }
173 157
174 void ExtensionEventRouter::AddLazyEventListener( 158 void ExtensionEventRouter::AddLazyEventListener(
175 const std::string& event_name, 159 const std::string& event_name,
176 const std::string& extension_id) { 160 const std::string& extension_id) {
177 ListenerProcess lazy_listener(NULL, extension_id); 161 scoped_ptr<EventListener> listener(new EventListener(
178 bool is_new = lazy_listeners_[event_name].insert(lazy_listener).second; 162 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>()));
163 bool is_new = listeners_.AddListener(listener.Pass());
164
179 if (is_new) { 165 if (is_new) {
180 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); 166 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs();
181 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); 167 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id);
182 bool prefs_is_new = events.insert(event_name).second; 168 bool prefs_is_new = events.insert(event_name).second;
183 if (prefs_is_new) 169 if (prefs_is_new)
184 prefs->SetRegisteredEvents(extension_id, events); 170 prefs->SetRegisteredEvents(extension_id, events);
185 } 171 }
186 } 172 }
187 173
188 void ExtensionEventRouter::RemoveLazyEventListener( 174 void ExtensionEventRouter::RemoveLazyEventListener(
189 const std::string& event_name, 175 const std::string& event_name,
190 const std::string& extension_id) { 176 const std::string& extension_id) {
191 ListenerProcess lazy_listener(NULL, extension_id); 177 scoped_ptr<EventListener> listener(new EventListener(
192 bool did_exist = lazy_listeners_[event_name].erase(lazy_listener) > 0; 178 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>()));
179 bool did_exist = listeners_.RemoveListener(listener.Pass());
180
193 if (did_exist) { 181 if (did_exist) {
194 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); 182 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs();
195 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); 183 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id);
196 bool prefs_did_exist = events.erase(event_name) > 0; 184 bool prefs_did_exist = events.erase(event_name) > 0;
197 DCHECK(prefs_did_exist); 185 DCHECK(prefs_did_exist);
198 prefs->SetRegisteredEvents(extension_id, events); 186 prefs->SetRegisteredEvents(extension_id, events);
199 } 187 }
200 } 188 }
201 189
190 void ExtensionEventRouter::AddFilteredEventListener(
191 const std::string& event_name,
192 content::RenderProcessHost* process,
193 const std::string& extension_id,
194 const base::DictionaryValue& filter,
195 bool lazy) {
196 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
197 event_name, extension_id, process,
198 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
199
200 if (lazy) {
201 bool added = listeners_.AddListener(scoped_ptr<EventListener>(
202 new EventListener(event_name, extension_id, NULL,
203 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
204
205 if (added) {
206 ExtensionPrefs* prefs =
207 profile_->GetExtensionService()->extension_prefs();
208 prefs->AddFilterToEvent(event_name, extension_id, &filter);
209 }
210 }
211 }
212
213 void ExtensionEventRouter::RemoveFilteredEventListener(
214 const std::string& event_name,
215 content::RenderProcessHost* process,
216 const std::string& extension_id,
217 const base::DictionaryValue& filter,
218 bool lazy) {
219 listeners_.RemoveListener(scoped_ptr<EventListener>(new EventListener(
220 event_name, extension_id, process,
221 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
222
223 if (lazy) {
224 bool removed = listeners_.RemoveListener(scoped_ptr<EventListener>(
225 new EventListener(event_name, extension_id, NULL,
226 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
227
228 if (removed) {
229 ExtensionPrefs* prefs =
230 profile_->GetExtensionService()->extension_prefs();
231 prefs->RemoveFilterFromEvent(event_name, extension_id, &filter);
232 }
233 }
234 }
235
202 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) { 236 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) {
203 return (HasEventListenerImpl(listeners_, "", event_name) || 237 return listeners_.AnyListenersForEvent(event_name);
204 HasEventListenerImpl(lazy_listeners_, "", event_name));
205 } 238 }
206 239
207 bool ExtensionEventRouter::ExtensionHasEventListener( 240 bool ExtensionEventRouter::ExtensionHasEventListener(
208 const std::string& extension_id, const std::string& event_name) { 241 const std::string& extension_id, const std::string& event_name) {
209 return (HasEventListenerImpl(listeners_, extension_id, event_name) || 242 return listeners_.AnyListenersForExtension(extension_id, event_name);
210 HasEventListenerImpl(lazy_listeners_, extension_id, event_name));
211 } 243 }
212 244
213 bool ExtensionEventRouter::HasEventListenerImpl( 245 bool ExtensionEventRouter::HasEventListenerImpl(
214 const ListenerMap& listener_map, 246 const ListenerMap& listener_map,
215 const std::string& extension_id, 247 const std::string& extension_id,
216 const std::string& event_name) { 248 const std::string& event_name) {
217 ListenerMap::const_iterator it = listener_map.find(event_name); 249 ListenerMap::const_iterator it = listener_map.find(event_name);
218 if (it == listener_map.end()) 250 if (it == listener_map.end())
219 return false; 251 return false;
220 252
221 const std::set<ListenerProcess>& listeners = it->second; 253 const std::set<ListenerProcess>& listeners = it->second;
222 if (extension_id.empty()) 254 if (extension_id.empty())
223 return !listeners.empty(); 255 return !listeners.empty();
224 256
225 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); 257 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin();
226 listener != listeners.end(); ++listener) { 258 listener != listeners.end(); ++listener) {
227 if (listener->extension_id == extension_id) 259 if (listener->extension_id == extension_id)
228 return true; 260 return true;
229 } 261 }
230 return false; 262 return false;
231 } 263 }
232 264
233 void ExtensionEventRouter::DispatchEventToRenderers( 265 void ExtensionEventRouter::DispatchEventToRenderers(
234 const std::string& event_name, 266 const std::string& event_name,
235 const std::string& event_args, 267 const std::string& event_args,
236 Profile* restrict_to_profile, 268 Profile* restrict_to_profile,
237 const GURL& event_url) { 269 const GURL& event_url,
270 extensions::EventFilteringInfo info) {
238 linked_ptr<ExtensionEvent> event( 271 linked_ptr<ExtensionEvent> event(
239 new ExtensionEvent(event_name, event_args, event_url, 272 new ExtensionEvent(event_name, event_args, event_url,
240 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); 273 restrict_to_profile, "", USER_GESTURE_UNKNOWN, info));
241 DispatchEventImpl("", event); 274 DispatchEventImpl("", event);
242 } 275 }
243 276
244 void ExtensionEventRouter::DispatchEventToExtension( 277 void ExtensionEventRouter::DispatchEventToExtension(
245 const std::string& extension_id, 278 const std::string& extension_id,
246 const std::string& event_name, 279 const std::string& event_name,
247 const std::string& event_args, 280 const std::string& event_args,
248 Profile* restrict_to_profile, 281 Profile* restrict_to_profile,
249 const GURL& event_url) { 282 const GURL& event_url) {
250 DCHECK(!extension_id.empty()); 283 DCHECK(!extension_id.empty());
251 linked_ptr<ExtensionEvent> event( 284 linked_ptr<ExtensionEvent> event(
252 new ExtensionEvent(event_name, event_args, event_url, 285 new ExtensionEvent(event_name, event_args, event_url,
253 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); 286 restrict_to_profile, "", USER_GESTURE_UNKNOWN,
287 EventFilteringInfo()));
254 DispatchEventImpl(extension_id, event); 288 DispatchEventImpl(extension_id, event);
255 } 289 }
256 290
257 void ExtensionEventRouter::DispatchEventToExtension( 291 void ExtensionEventRouter::DispatchEventToExtension(
258 const std::string& extension_id, 292 const std::string& extension_id,
259 const std::string& event_name, 293 const std::string& event_name,
260 const std::string& event_args, 294 const std::string& event_args,
261 Profile* restrict_to_profile, 295 Profile* restrict_to_profile,
262 const GURL& event_url, 296 const GURL& event_url,
263 UserGestureState user_gesture) { 297 UserGestureState user_gesture) {
264 DCHECK(!extension_id.empty()); 298 DCHECK(!extension_id.empty());
265 linked_ptr<ExtensionEvent> event( 299 linked_ptr<ExtensionEvent> event(
266 new ExtensionEvent(event_name, event_args, event_url, 300 new ExtensionEvent(event_name, event_args, event_url,
267 restrict_to_profile, "", user_gesture)); 301 restrict_to_profile, "", user_gesture,
302 EventFilteringInfo()));
268 DispatchEventImpl(extension_id, event); 303 DispatchEventImpl(extension_id, event);
269 } 304 }
270 305
271 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( 306 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito(
272 const std::string& event_name, 307 const std::string& event_name,
273 const std::string& event_args, 308 const std::string& event_args,
274 Profile* restrict_to_profile, 309 Profile* restrict_to_profile,
275 const std::string& cross_incognito_args, 310 const std::string& cross_incognito_args,
276 const GURL& event_url) { 311 const GURL& event_url) {
277 linked_ptr<ExtensionEvent> event( 312 linked_ptr<ExtensionEvent> event(
278 new ExtensionEvent(event_name, event_args, event_url, 313 new ExtensionEvent(event_name, event_args, event_url,
279 restrict_to_profile, cross_incognito_args, 314 restrict_to_profile, cross_incognito_args,
280 USER_GESTURE_UNKNOWN)); 315 USER_GESTURE_UNKNOWN, EventFilteringInfo()));
281 DispatchEventImpl("", event); 316 DispatchEventImpl("", event);
282 } 317 }
283 318
284 void ExtensionEventRouter::DispatchEventImpl( 319 void ExtensionEventRouter::DispatchEventImpl(
285 const std::string& extension_id, 320 const std::string& extension_id,
286 const linked_ptr<ExtensionEvent>& event) { 321 const linked_ptr<ExtensionEvent>& event) {
287 // We don't expect to get events from a completely different profile. 322 // We don't expect to get events from a completely different profile.
288 DCHECK(!event->restrict_to_profile || 323 DCHECK(!event->restrict_to_profile ||
289 profile_->IsSameProfile(event->restrict_to_profile)); 324 profile_->IsSameProfile(event->restrict_to_profile));
290 325
291 LoadLazyBackgroundPagesForEvent(extension_id, event); 326 scoped_ptr<std::set<const EventListener*> > listeners(
292 327 listeners_.GetEventTargets(*event));
293 ListenerMap::iterator it = listeners_.find(event->event_name); 328 for (std::set<const EventListener*>::iterator it = listeners->begin();
294 if (it == listeners_.end()) 329 it != listeners->end(); it++) {
295 return; 330 const EventListener* listener = *it;
296 331 if (listener->process) {
297 std::set<ListenerProcess>& listeners = it->second; 332 if (extension_id.empty() || extension_id == listener->extension_id)
298 for (std::set<ListenerProcess>::iterator listener = listeners.begin(); 333 DispatchEventToExtension(listener->extension_id, listener->process,
299 listener != listeners.end(); ++listener) { 334 event);
300 if (!extension_id.empty() && extension_id != listener->extension_id) 335 } else {
301 continue; 336 DispatchLazyEvent(linked_ptr<EventListener>(listener->Copy().release()),
302 337 event);
303 DispatchEventToListener(*listener, event); 338 }
304 } 339 }
305 } 340 }
306 341
307 void ExtensionEventRouter::DispatchEventToListener( 342 void ExtensionEventRouter::DispatchLazyEvent(
308 const ListenerProcess& listener, 343 const linked_ptr<EventListener>& listener,
344 const linked_ptr<ExtensionEvent>& event) {
345 ExtensionService* service = profile_->GetExtensionService();
346 // Check both the original and the incognito profile to see if we
347 // should load a lazy bg page to handle the event. The latter case
348 // occurs in the case of split-mode extensions.
349 const Extension* extension = service->extensions()->GetByID(
350 listener->extension_id);
351 if (extension) {
352 MaybeLoadLazyBackgroundPage(profile_, extension, event, listener);
353 if (profile_->HasOffTheRecordProfile() &&
354 extension->incognito_split_mode()) {
355 MaybeLoadLazyBackgroundPage(
356 profile_->GetOffTheRecordProfile(), extension, event, listener);
357 }
358 }
359 }
360
361 void ExtensionEventRouter::DispatchEventToExtension(
362 const std::string& extension_id,
363 content::RenderProcessHost* process,
309 const linked_ptr<ExtensionEvent>& event) { 364 const linked_ptr<ExtensionEvent>& event) {
310 ExtensionService* service = profile_->GetExtensionService(); 365 ExtensionService* service = profile_->GetExtensionService();
311 const Extension* extension = service->extensions()->GetByID( 366 const Extension* extension = service->extensions()->GetByID(
312 listener.extension_id); 367 extension_id);
313 368
314 // The extension could have been removed, but we do not unregister it until 369 // The extension could have been removed, but we do not unregister it until
315 // the extension process is unloaded. 370 // the extension process is unloaded.
316 if (!extension) 371 if (!extension)
317 return; 372 return;
318 373
319 Profile* listener_profile = Profile::FromBrowserContext( 374 Profile* listener_profile = Profile::FromBrowserContext(
320 listener.process->GetBrowserContext()); 375 process->GetBrowserContext());
321 extensions::ProcessMap* process_map = 376 extensions::ProcessMap* process_map =
322 listener_profile->GetExtensionService()->process_map(); 377 listener_profile->GetExtensionService()->process_map();
323 // If the event is privileged, only send to extension processes. Otherwise, 378 // If the event is privileged, only send to extension processes. Otherwise,
324 // it's OK to send to normal renderers (e.g., for content scripts). 379 // it's OK to send to normal renderers (e.g., for content scripts).
325 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && 380 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) &&
326 !process_map->Contains(extension->id(), listener.process->GetID())) { 381 !process_map->Contains(extension->id(), process->GetID())) {
327 return; 382 return;
328 } 383 }
329 384
330 const std::string* event_args; 385 const std::string* event_args;
331 if (!CanDispatchEventToProfile(listener_profile, extension, 386 if (!CanDispatchEventToProfile(listener_profile, extension,
332 event, &event_args)) 387 event, &event_args))
333 return; 388 return;
334 389
335 DispatchEvent(listener.process, listener.extension_id, 390 DispatchEvent(process, extension_id,
336 event->event_name, *event_args, 391 event->event_name, *event_args,
337 event->event_url, event->user_gesture); 392 event->event_url, event->user_gesture,
393 event->info);
338 IncrementInFlightEvents(listener_profile, extension); 394 IncrementInFlightEvents(listener_profile, extension);
339 } 395 }
340 396
341 bool ExtensionEventRouter::CanDispatchEventToProfile( 397 bool ExtensionEventRouter::CanDispatchEventToProfile(
342 Profile* profile, 398 Profile* profile,
343 const Extension* extension, 399 const Extension* extension,
344 const linked_ptr<ExtensionEvent>& event, 400 const linked_ptr<ExtensionEvent>& event,
345 const std::string** event_args) { 401 const std::string** event_args) {
346 *event_args = &event->event_args; 402 *event_args = &event->event_args;
347 403
348 // Is this event from a different profile than the renderer (ie, an 404 // Is this event from a different profile than the renderer (ie, an
349 // incognito tab event sent to a normal process, or vice versa). 405 // incognito tab event sent to a normal process, or vice versa).
350 bool cross_incognito = event->restrict_to_profile && 406 bool cross_incognito = event->restrict_to_profile &&
351 profile != event->restrict_to_profile; 407 profile != event->restrict_to_profile;
352 if (cross_incognito && 408 if (cross_incognito &&
353 !profile->GetExtensionService()->CanCrossIncognito(extension)) { 409 !profile->GetExtensionService()->CanCrossIncognito(extension)) {
354 if (event->cross_incognito_args.empty()) 410 if (event->cross_incognito_args.empty())
355 return false; 411 return false;
356 // Send the event with different arguments to extensions that can't 412 // Send the event with different arguments to extensions that can't
357 // cross incognito. 413 // cross incognito.
358 *event_args = &event->cross_incognito_args; 414 *event_args = &event->cross_incognito_args;
359 } 415 }
360 416
361 return true; 417 return true;
362 } 418 }
363 419
364 void ExtensionEventRouter::LoadLazyBackgroundPagesForEvent(
365 const std::string& extension_id,
366 const linked_ptr<ExtensionEvent>& event) {
367 ExtensionService* service = profile_->GetExtensionService();
368
369 ListenerMap::iterator it = lazy_listeners_.find(event->event_name);
370 if (it == lazy_listeners_.end())
371 return;
372
373 std::set<ListenerProcess>& listeners = it->second;
374 for (std::set<ListenerProcess>::iterator listener = listeners.begin();
375 listener != listeners.end(); ++listener) {
376 if (!extension_id.empty() && extension_id != listener->extension_id)
377 continue;
378
379 // Check both the original and the incognito profile to see if we
380 // should load a lazy bg page to handle the event. The latter case
381 // occurs in the case of split-mode extensions.
382 const Extension* extension = service->extensions()->GetByID(
383 listener->extension_id);
384 if (extension) {
385 MaybeLoadLazyBackgroundPage(profile_, extension, event);
386 if (profile_->HasOffTheRecordProfile() &&
387 extension->incognito_split_mode()) {
388 MaybeLoadLazyBackgroundPage(
389 profile_->GetOffTheRecordProfile(), extension, event);
390 }
391 }
392 }
393 }
394
395 void ExtensionEventRouter::MaybeLoadLazyBackgroundPage( 420 void ExtensionEventRouter::MaybeLoadLazyBackgroundPage(
396 Profile* profile, 421 Profile* profile,
397 const Extension* extension, 422 const Extension* extension,
398 const linked_ptr<ExtensionEvent>& event) { 423 const linked_ptr<ExtensionEvent>& event,
424 const linked_ptr<EventListener>& listener) {
399 const std::string* event_args; 425 const std::string* event_args;
400 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) 426 if (!CanDispatchEventToProfile(profile, extension, event, &event_args))
401 return; 427 return;
402 428
403 extensions::LazyBackgroundTaskQueue* queue = 429 extensions::LazyBackgroundTaskQueue* queue =
404 ExtensionSystem::Get(profile)->lazy_background_task_queue(); 430 ExtensionSystem::Get(profile)->lazy_background_task_queue();
405 if (queue->ShouldEnqueueTask(profile, extension)) { 431 if (queue->ShouldEnqueueTask(profile, extension)) {
406 queue->AddPendingTask( 432 queue->AddPendingTask(
407 profile, extension->id(), 433 profile, extension->id(),
408 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, 434 base::Bind(&ExtensionEventRouter::DispatchPendingEvent,
409 base::Unretained(this), event)); 435 base::Unretained(this), event, listener));
410 } 436 }
411 } 437 }
412 438
413 void ExtensionEventRouter::IncrementInFlightEvents( 439 void ExtensionEventRouter::IncrementInFlightEvents(
414 Profile* profile, const Extension* extension) { 440 Profile* profile, const Extension* extension) {
415 // Only increment in-flight events if the lazy background page is active, 441 // Only increment in-flight events if the lazy background page is active,
416 // because that's the only time we'll get an ACK. 442 // because that's the only time we'll get an ACK.
417 if (extension->has_lazy_background_page()) { 443 if (extension->has_lazy_background_page()) {
418 ExtensionProcessManager* pm = 444 ExtensionProcessManager* pm =
419 ExtensionSystem::Get(profile)->process_manager(); 445 ExtensionSystem::Get(profile)->process_manager();
420 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id()); 446 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension->id());
421 if (host) 447 if (host)
422 pm->IncrementLazyKeepaliveCount(extension); 448 pm->IncrementLazyKeepaliveCount(extension);
423 } 449 }
424 } 450 }
425 451
426 void ExtensionEventRouter::OnEventAck( 452 void ExtensionEventRouter::OnEventAck(
427 Profile* profile, const std::string& extension_id) { 453 Profile* profile, const std::string& extension_id) {
428 ExtensionProcessManager* pm = 454 ExtensionProcessManager* pm =
429 ExtensionSystem::Get(profile)->process_manager(); 455 ExtensionSystem::Get(profile)->process_manager();
430 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id); 456 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id);
431 // The event ACK is routed to the background host, so this should never be 457 // The event ACK is routed to the background host, so this should never be
432 // NULL. 458 // NULL.
433 CHECK(host); 459 CHECK(host);
434 CHECK(host->extension()->has_lazy_background_page()); 460 CHECK(host->extension()->has_lazy_background_page());
435 pm->DecrementLazyKeepaliveCount(host->extension()); 461 pm->DecrementLazyKeepaliveCount(host->extension());
436 } 462 }
437 463
438 void ExtensionEventRouter::DispatchPendingEvent( 464 void ExtensionEventRouter::DispatchPendingEvent(
439 const linked_ptr<ExtensionEvent>& event, ExtensionHost* host) { 465 const linked_ptr<ExtensionEvent>& event,
466 const linked_ptr<EventListener>& listener,
467 ExtensionHost* host) {
440 if (!host) 468 if (!host)
441 return; 469 return;
442 470
443 ListenerProcess listener(host->render_process_host(), 471 if (listeners_.HasListener(listener.get()))
Matt Perry 2012/06/13 01:24:27 This is not quite right. IIUC, here |listener| is
koz (OOO until 15th September) 2012/06/14 02:15:55 Done.
444 host->extension()->id()); 472 DispatchEventToExtension(host->extension()->id(),
445 if (listeners_[event->event_name].count(listener) > 0u) 473 host->render_process_host(), event);
446 DispatchEventToListener(listener, event);
447 } 474 }
448 475
449 void ExtensionEventRouter::Observe( 476 void ExtensionEventRouter::Observe(
450 int type, 477 int type,
451 const content::NotificationSource& source, 478 const content::NotificationSource& source,
452 const content::NotificationDetails& details) { 479 const content::NotificationDetails& details) {
453 switch (type) { 480 switch (type) {
454 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 481 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
455 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 482 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
456 content::RenderProcessHost* renderer = 483 content::RenderProcessHost* renderer =
457 content::Source<content::RenderProcessHost>(source).ptr(); 484 content::Source<content::RenderProcessHost>(source).ptr();
458 // Remove all event listeners associated with this renderer. 485 // Remove all event listeners associated with this renderer.
459 for (ListenerMap::iterator it = listeners_.begin(); 486 EventListenerMap::ListenerList removed =
460 it != listeners_.end(); ) { 487 listeners_.RemoveListenersForProcess(renderer);
461 ListenerMap::iterator current_it = it++; 488 for (EventListenerMap::ListenerList::iterator it = removed.begin();
462 for (std::set<ListenerProcess>::iterator jt = 489 it != removed.end(); it++) {
463 current_it->second.begin(); 490 OnListenerRemoved(it->get());
464 jt != current_it->second.end(); ) {
465 std::set<ListenerProcess>::iterator current_jt = jt++;
466 if (current_jt->process == renderer) {
467 RemoveEventListener(current_it->first,
468 current_jt->process,
469 current_jt->extension_id);
470 }
471 }
472 } 491 }
473 break; 492 break;
474 } 493 }
475 case chrome::NOTIFICATION_EXTENSION_LOADED: { 494 case chrome::NOTIFICATION_EXTENSION_LOADED: {
476 // Add all registered lazy listeners to our cache. 495 // Add all registered lazy listeners to our cache.
477 const Extension* extension = 496 const Extension* extension =
478 content::Details<const Extension>(details).ptr(); 497 content::Details<const Extension>(details).ptr();
498 ExtensionPrefs* prefs =
499 profile_->GetExtensionService()->extension_prefs();
479 std::set<std::string> registered_events = 500 std::set<std::string> registered_events =
480 profile_->GetExtensionService()->extension_prefs()-> 501 prefs->GetRegisteredEvents(extension->id());
481 GetRegisteredEvents(extension->id()); 502 const DictionaryValue* filtered_events =
482 ListenerProcess lazy_listener(NULL, extension->id()); 503 prefs->GetFilteredEvents(extension->id());
483 for (std::set<std::string>::iterator it = registered_events.begin(); 504 if (filtered_events)
484 it != registered_events.end(); ++it) { 505 listeners_.AddLazyListenersFromPreferences(extension->id(),
485 lazy_listeners_[*it].insert(lazy_listener); 506 registered_events,
Matt Perry 2012/06/13 01:24:27 indent
koz (OOO until 15th September) 2012/06/14 02:15:55 Done.
486 } 507 *filtered_events);
487 break; 508 break;
488 } 509 }
489 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 510 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
Matt Perry 2012/06/13 01:24:27 These top 4 notifications should be handled direct
koz (OOO until 15th September) 2012/06/14 02:15:55 I've added the callback for OnListenerRemoved(), b
490 // Remove all registered lazy listeners from our cache. 511 // Remove all registered lazy listeners from our cache.
491 extensions::UnloadedExtensionInfo* unloaded = 512 extensions::UnloadedExtensionInfo* unloaded =
492 content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); 513 content::Details<extensions::UnloadedExtensionInfo>(details).ptr();
493 ListenerProcess lazy_listener(NULL, unloaded->extension->id()); 514 listeners_.RemoveLazyListenersFor(unloaded->extension->id());
494 for (ListenerMap::iterator it = lazy_listeners_.begin();
495 it != lazy_listeners_.end(); ++it) {
496 it->second.erase(lazy_listener);
497 }
498 break; 515 break;
499 } 516 }
500 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { 517 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
501 // Dispatch the onInstalled event. 518 // Dispatch the onInstalled event.
502 const Extension* extension = 519 const Extension* extension =
503 content::Details<const Extension>(details).ptr(); 520 content::Details<const Extension>(details).ptr();
504 MessageLoop::current()->PostTask(FROM_HERE, 521 MessageLoop::current()->PostTask(FROM_HERE,
505 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, 522 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent,
506 profile_, extension->id())); 523 profile_, extension->id()));
507 break; 524 break;
508 } 525 }
509 default: 526 default:
510 NOTREACHED(); 527 NOTREACHED();
511 return; 528 return;
512 } 529 }
513 } 530 }
531
532 ExtensionEvent::ExtensionEvent(
533 const std::string& event_name,
534 const std::string& event_args,
535 const GURL& event_url,
536 Profile* restrict_to_profile,
537 const std::string& cross_incognito_args,
538 ExtensionEventRouter::UserGestureState user_gesture,
539 const extensions::EventFilteringInfo& info)
540 : event_name(event_name),
541 event_args(event_args),
542 event_url(event_url),
543 restrict_to_profile(restrict_to_profile),
544 cross_incognito_args(cross_incognito_args),
545 user_gesture(user_gesture),
546 info(info) {
547 }
548
549 ExtensionEvent::~ExtensionEvent() {
550 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698