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

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: fix 80 char 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 scoped_ptr<Value> event_args;
71 GURL event_url;
72 Profile* restrict_to_profile;
73 scoped_ptr<Value> cross_incognito_args;
74 UserGestureState user_gesture;
75
76 ExtensionEvent(const std::string& event_name,
77 const Value& event_args,
78 const GURL& event_url,
79 Profile* restrict_to_profile,
80 const Value& cross_incognito_args,
81 UserGestureState user_gesture)
82 : event_name(event_name),
83 event_args(event_args.DeepCopy()),
84 event_url(event_url),
85 restrict_to_profile(restrict_to_profile),
86 cross_incognito_args(cross_incognito_args.DeepCopy()),
87 user_gesture(user_gesture) {}
88
89 ExtensionEvent(const std::string& event_name,
90 const Value& event_args,
91 const GURL& event_url,
92 Profile* restrict_to_profile,
93 UserGestureState user_gesture)
94 : event_name(event_name),
95 event_args(event_args.DeepCopy()),
96 event_url(event_url),
97 restrict_to_profile(restrict_to_profile),
98 cross_incognito_args(NULL),
99 user_gesture(user_gesture) {}
100
101 // TODO(gdk): This variant should be retired once the callers are switched to
102 // providing Values instead of just strings.
103 ExtensionEvent(const std::string& event_name,
104 const std::string& event_args,
105 const GURL& event_url,
106 Profile* restrict_to_profile,
107 const std::string& cross_incognito_args,
108 UserGestureState user_gesture)
109 : event_name(event_name),
110 event_args(Value::CreateStringValue(event_args)),
111 event_url(event_url),
112 restrict_to_profile(restrict_to_profile),
113 cross_incognito_args(Value::CreateStringValue(cross_incognito_args)),
114 user_gesture(user_gesture) {}
115 };
116
117 // static 68 // static
118 void ExtensionEventRouter::DispatchEvent(IPC::Sender* ipc_sender, 69 void ExtensionEventRouter::DispatchEvent(
119 const std::string& extension_id, 70 IPC::Message::Sender* ipc_sender,
120 const std::string& event_name, 71 const std::string& extension_id,
121 const Value& event_args, 72 const std::string& event_name,
122 const GURL& event_url, 73 const Value& event_args,
123 UserGestureState user_gesture) { 74 const GURL& event_url,
75 UserGestureState user_gesture,
76 const extensions::EventFilteringInfo& info) {
124 // TODO(gdk): Reduce number of DeepCopy() calls throughout the event dispatch 77 // TODO(gdk): Reduce number of DeepCopy() calls throughout the event dispatch
125 // chain, starting by replacing the event_args with a Value*. 78 // chain, starting by replacing the event_args with a Value*.
126 ListValue args; 79 ListValue args;
127 args.Set(0, Value::CreateStringValue(event_name)); 80 args.Set(0, Value::CreateStringValue(event_name));
128 args.Set(1, event_args.DeepCopy()); 81 args.Set(1, event_args.DeepCopy());
82 args.Set(2, info.AsValue().release());
83
129 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, 84 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL,
130 extension_id, kDispatchEvent, args, event_url, 85 extension_id, kDispatchEvent, args, event_url,
131 user_gesture == USER_GESTURE_ENABLED)); 86 user_gesture == USER_GESTURE_ENABLED));
132 } 87 }
133 88
134 // static 89 // static
135 void ExtensionEventRouter::DispatchEvent(IPC::Sender* ipc_sender, 90 void ExtensionEventRouter::DispatchEvent(
136 const std::string& extension_id, 91 IPC::Sender* ipc_sender,
137 const std::string& event_name, 92 const std::string& extension_id,
138 const std::string& event_args, 93 const std::string& event_name,
139 const GURL& event_url, 94 const std::string& event_args,
140 UserGestureState user_gesture) { 95 const GURL& event_url,
96 UserGestureState user_gesture,
97 const extensions::EventFilteringInfo& info) {
141 scoped_ptr<Value> event_args_value(Value::CreateStringValue(event_args)); 98 scoped_ptr<Value> event_args_value(Value::CreateStringValue(event_args));
142 DispatchEvent(ipc_sender, extension_id, event_name, *event_args_value.get(), 99 DispatchEvent(ipc_sender, extension_id, event_name, *event_args_value.get(),
143 event_url, user_gesture); 100 event_url, user_gesture, info);
144 } 101 }
145 102
146 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) 103 ExtensionEventRouter::ExtensionEventRouter(Profile* profile)
147 : profile_(profile), 104 : profile_(profile),
148 extension_devtools_manager_( 105 extension_devtools_manager_(
149 ExtensionSystem::Get(profile)->devtools_manager()) { 106 ExtensionSystem::Get(profile)->devtools_manager()),
107 listeners_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
150 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 108 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
151 content::NotificationService::AllSources()); 109 content::NotificationService::AllSources());
152 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, 110 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
153 content::NotificationService::AllSources()); 111 content::NotificationService::AllSources());
154 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 112 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
155 content::Source<Profile>(profile_)); 113 content::Source<Profile>(profile_));
156 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 114 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
157 content::Source<Profile>(profile_)); 115 content::Source<Profile>(profile_));
158 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, 116 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
159 content::Source<Profile>(profile_)); 117 content::Source<Profile>(profile_));
160 } 118 }
161 119
162 ExtensionEventRouter::~ExtensionEventRouter() {} 120 ExtensionEventRouter::~ExtensionEventRouter() {}
163 121
164 void ExtensionEventRouter::AddEventListener( 122 void ExtensionEventRouter::AddEventListener(
165 const std::string& event_name, 123 const std::string& event_name,
166 content::RenderProcessHost* process, 124 content::RenderProcessHost* process,
167 const std::string& extension_id) { 125 const std::string& extension_id) {
168 ListenerProcess listener(process, extension_id); 126 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
169 DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name; 127 event_name, extension_id, process, scoped_ptr<DictionaryValue>())));
170 listeners_[event_name].insert(listener); 128 }
129
130 void ExtensionEventRouter::RemoveEventListener(
131 const std::string& event_name,
132 content::RenderProcessHost* process,
133 const std::string& extension_id) {
134 EventListener listener(event_name, extension_id, process,
135 scoped_ptr<DictionaryValue>());
136 listeners_.RemoveListener(&listener);
137 }
138
139 void ExtensionEventRouter::OnListenerAdded(const EventListener* listener) {
140 // We don't care about lazy events being added.
141 if (!listener->process)
142 return;
171 143
172 if (extension_devtools_manager_.get()) 144 if (extension_devtools_manager_.get())
173 extension_devtools_manager_->AddEventListener(event_name, 145 extension_devtools_manager_->AddEventListener(listener->event_name,
174 process->GetID()); 146 listener->process->GetID());
175 147
176 // We lazily tell the TaskManager to start updating when listeners to the 148 // We lazily tell the TaskManager to start updating when listeners to the
177 // processes.onUpdated or processes.onUpdatedWithMemory events arrive. 149 // processes.onUpdated or processes.onUpdatedWithMemory events arrive.
150 const std::string& event_name = listener->event_name;
178 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || 151 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 ||
179 event_name.compare( 152 event_name.compare(
180 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) 153 extension_processes_api_constants::kOnUpdatedWithMemory) == 0)
181 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded(); 154 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded();
182 } 155 }
183 156
184 void ExtensionEventRouter::RemoveEventListener( 157 void ExtensionEventRouter::OnListenerRemoved(const EventListener* listener) {
185 const std::string& event_name, 158 // We don't care about lazy events being removed.
186 content::RenderProcessHost* process, 159 if (!listener->process)
187 const std::string& extension_id) { 160 return;
188 ListenerProcess listener(process, extension_id);
189 DCHECK_EQ(listeners_[event_name].count(listener), 1u) <<
190 " PID=" << process->GetID() << " extension=" << extension_id <<
191 " event=" << event_name;
192 listeners_[event_name].erase(listener);
193 // Note: extension_id may point to data in the now-deleted listeners_ object.
194 // Do not use.
195 161
162 const std::string& event_name = listener->event_name;
196 if (extension_devtools_manager_.get()) 163 if (extension_devtools_manager_.get())
197 extension_devtools_manager_->RemoveEventListener(event_name, 164 extension_devtools_manager_->RemoveEventListener(
198 process->GetID()); 165 event_name, listener->process->GetID());
199 166
200 // If a processes.onUpdated or processes.onUpdatedWithMemory event listener 167 // If a processes.onUpdated or processes.onUpdatedWithMemory event listener
201 // is removed (or a process with one exits), then we let the extension API 168 // is removed (or a process with one exits), then we let the extension API
202 // know that it has one fewer listener. 169 // know that it has one fewer listener.
203 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 || 170 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0 ||
204 event_name.compare( 171 event_name.compare(
205 extension_processes_api_constants::kOnUpdatedWithMemory) == 0) 172 extension_processes_api_constants::kOnUpdatedWithMemory) == 0)
206 ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved(); 173 ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved();
207 174
208 BrowserThread::PostTask( 175 BrowserThread::PostTask(
209 BrowserThread::IO, FROM_HERE, 176 BrowserThread::IO, FROM_HERE,
210 base::Bind( 177 base::Bind(
211 &NotifyEventListenerRemovedOnIOThread, 178 &NotifyEventListenerRemovedOnIOThread,
212 profile_, listener.extension_id, event_name)); 179 profile_, listener->extension_id, listener->event_name));
213 } 180 }
214 181
215 void ExtensionEventRouter::AddLazyEventListener( 182 void ExtensionEventRouter::AddLazyEventListener(
216 const std::string& event_name, 183 const std::string& event_name,
217 const std::string& extension_id) { 184 const std::string& extension_id) {
218 ListenerProcess lazy_listener(NULL, extension_id); 185 scoped_ptr<EventListener> listener(new EventListener(
219 bool is_new = lazy_listeners_[event_name].insert(lazy_listener).second; 186 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>()));
187 bool is_new = listeners_.AddListener(listener.Pass());
188
220 if (is_new) { 189 if (is_new) {
221 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); 190 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs();
222 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); 191 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id);
223 bool prefs_is_new = events.insert(event_name).second; 192 bool prefs_is_new = events.insert(event_name).second;
224 if (prefs_is_new) 193 if (prefs_is_new)
225 prefs->SetRegisteredEvents(extension_id, events); 194 prefs->SetRegisteredEvents(extension_id, events);
226 } 195 }
227 } 196 }
228 197
229 void ExtensionEventRouter::RemoveLazyEventListener( 198 void ExtensionEventRouter::RemoveLazyEventListener(
230 const std::string& event_name, 199 const std::string& event_name,
231 const std::string& extension_id) { 200 const std::string& extension_id) {
232 ListenerProcess lazy_listener(NULL, extension_id); 201 EventListener listener(event_name, extension_id, NULL,
233 bool did_exist = lazy_listeners_[event_name].erase(lazy_listener) > 0; 202 scoped_ptr<DictionaryValue>());
203 bool did_exist = listeners_.RemoveListener(&listener);
204
234 if (did_exist) { 205 if (did_exist) {
235 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); 206 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs();
236 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); 207 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id);
237 bool prefs_did_exist = events.erase(event_name) > 0; 208 bool prefs_did_exist = events.erase(event_name) > 0;
238 DCHECK(prefs_did_exist); 209 DCHECK(prefs_did_exist);
239 prefs->SetRegisteredEvents(extension_id, events); 210 prefs->SetRegisteredEvents(extension_id, events);
240 } 211 }
241 } 212 }
242 213
214 void ExtensionEventRouter::AddFilteredEventListener(
215 const std::string& event_name,
216 content::RenderProcessHost* process,
217 const std::string& extension_id,
218 const base::DictionaryValue& filter,
219 bool add_lazy_listener) {
220 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener(
221 event_name, extension_id, process,
222 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
223
224 if (add_lazy_listener) {
225 bool added = listeners_.AddListener(scoped_ptr<EventListener>(
226 new EventListener(event_name, extension_id, NULL,
227 scoped_ptr<DictionaryValue>(filter.DeepCopy()))));
228
229 if (added) {
230 ExtensionPrefs* prefs =
231 profile_->GetExtensionService()->extension_prefs();
232 prefs->AddFilterToEvent(event_name, extension_id, &filter);
233 }
234 }
235 }
236
237 void ExtensionEventRouter::RemoveFilteredEventListener(
238 const std::string& event_name,
239 content::RenderProcessHost* process,
240 const std::string& extension_id,
241 const base::DictionaryValue& filter,
242 bool remove_lazy_listener) {
243 EventListener listener(event_name, extension_id, process,
244 scoped_ptr<DictionaryValue>(filter.DeepCopy()));
245
246 listeners_.RemoveListener(&listener);
247
248 if (remove_lazy_listener) {
249 listener.process = NULL;
250 bool removed = listeners_.RemoveListener(&listener);
251
252 if (removed) {
253 ExtensionPrefs* prefs =
254 profile_->GetExtensionService()->extension_prefs();
255 prefs->RemoveFilterFromEvent(event_name, extension_id, &filter);
256 }
257 }
258 }
259
243 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) { 260 bool ExtensionEventRouter::HasEventListener(const std::string& event_name) {
244 return (HasEventListenerImpl(listeners_, "", event_name) || 261 return listeners_.HasListenerForEvent(event_name);
245 HasEventListenerImpl(lazy_listeners_, "", event_name));
246 } 262 }
247 263
248 bool ExtensionEventRouter::ExtensionHasEventListener( 264 bool ExtensionEventRouter::ExtensionHasEventListener(
249 const std::string& extension_id, const std::string& event_name) { 265 const std::string& extension_id, const std::string& event_name) {
250 return (HasEventListenerImpl(listeners_, extension_id, event_name) || 266 return listeners_.HasListenerForExtension(extension_id, event_name);
251 HasEventListenerImpl(lazy_listeners_, extension_id, event_name));
252 } 267 }
253 268
254 bool ExtensionEventRouter::HasEventListenerImpl( 269 bool ExtensionEventRouter::HasEventListenerImpl(
255 const ListenerMap& listener_map, 270 const ListenerMap& listener_map,
256 const std::string& extension_id, 271 const std::string& extension_id,
257 const std::string& event_name) { 272 const std::string& event_name) {
258 ListenerMap::const_iterator it = listener_map.find(event_name); 273 ListenerMap::const_iterator it = listener_map.find(event_name);
259 if (it == listener_map.end()) 274 if (it == listener_map.end())
260 return false; 275 return false;
261 276
262 const std::set<ListenerProcess>& listeners = it->second; 277 const std::set<ListenerProcess>& listeners = it->second;
263 if (extension_id.empty()) 278 if (extension_id.empty())
264 return !listeners.empty(); 279 return !listeners.empty();
265 280
266 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); 281 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin();
267 listener != listeners.end(); ++listener) { 282 listener != listeners.end(); ++listener) {
268 if (listener->extension_id == extension_id) 283 if (listener->extension_id == extension_id)
269 return true; 284 return true;
270 } 285 }
271 return false; 286 return false;
272 } 287 }
273 288
274 void ExtensionEventRouter::DispatchEventToRenderers( 289 void ExtensionEventRouter::DispatchEventToRenderers(
275 const std::string& event_name, 290 const std::string& event_name,
276 const std::string& event_args, 291 const std::string& event_args,
277 Profile* restrict_to_profile, 292 Profile* restrict_to_profile,
278 const GURL& event_url) { 293 const GURL& event_url,
294 extensions::EventFilteringInfo info) {
295 DCHECK(!event_args.empty());
296 StringValue event_args_value(event_args);
279 linked_ptr<ExtensionEvent> event( 297 linked_ptr<ExtensionEvent> event(
280 new ExtensionEvent(event_name, event_args, event_url, 298 new ExtensionEvent(event_name, event_args_value, event_url,
281 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); 299 restrict_to_profile, USER_GESTURE_UNKNOWN, info));
282 DispatchEventImpl("", event); 300 DispatchEventImpl("", event);
283 } 301 }
284 302
285 void ExtensionEventRouter::DispatchEventToExtension( 303 void ExtensionEventRouter::DispatchEventToExtension(
286 const std::string& extension_id, 304 const std::string& extension_id,
287 const std::string& event_name, 305 const std::string& event_name,
288 const Value& event_args, 306 const Value& event_args,
289 Profile* restrict_to_profile, 307 Profile* restrict_to_profile,
290 const GURL& event_url) { 308 const GURL& event_url) {
291 DCHECK(!extension_id.empty()); 309 DCHECK(!extension_id.empty());
292 linked_ptr<ExtensionEvent> event( 310 linked_ptr<ExtensionEvent> event(
293 new ExtensionEvent(event_name, event_args, event_url, 311 new ExtensionEvent(event_name, event_args, event_url,
294 restrict_to_profile, USER_GESTURE_UNKNOWN)); 312 restrict_to_profile, USER_GESTURE_UNKNOWN,
313 EventFilteringInfo()));
295 DispatchEventImpl(extension_id, event); 314 DispatchEventImpl(extension_id, event);
296 } 315 }
297 316
298 void ExtensionEventRouter::DispatchEventToExtension( 317 void ExtensionEventRouter::DispatchEventToExtension(
299 const std::string& extension_id, 318 const std::string& extension_id,
300 const std::string& event_name, 319 const std::string& event_name,
301 const std::string& event_args, 320 const std::string& event_args,
302 Profile* restrict_to_profile, 321 Profile* restrict_to_profile,
303 const GURL& event_url) { 322 const GURL& event_url) {
304 scoped_ptr<Value> event_args_value(Value::CreateStringValue(event_args)); 323 StringValue event_args_value(event_args);
305 DispatchEventToExtension(extension_id, event_name, *event_args_value.get(), 324 DispatchEventToExtension(extension_id, event_name, event_args_value,
306 restrict_to_profile, event_url); 325 restrict_to_profile, event_url);
307 } 326 }
308 327
309 void ExtensionEventRouter::DispatchEventToExtension( 328 void ExtensionEventRouter::DispatchEventToExtension(
310 const std::string& extension_id, 329 const std::string& extension_id,
311 const std::string& event_name, 330 const std::string& event_name,
312 const std::string& event_args, 331 const std::string& event_args,
313 Profile* restrict_to_profile, 332 Profile* restrict_to_profile,
314 const GURL& event_url, 333 const GURL& event_url,
315 UserGestureState user_gesture) { 334 UserGestureState user_gesture) {
316 DCHECK(!extension_id.empty()); 335 DCHECK(!extension_id.empty());
336 StringValue event_args_value(event_args);
317 linked_ptr<ExtensionEvent> event( 337 linked_ptr<ExtensionEvent> event(
318 new ExtensionEvent(event_name, event_args, event_url, 338 new ExtensionEvent(event_name, event_args_value, event_url,
319 restrict_to_profile, "", user_gesture)); 339 restrict_to_profile, user_gesture,
340 EventFilteringInfo()));
320 DispatchEventImpl(extension_id, event); 341 DispatchEventImpl(extension_id, event);
321 } 342 }
322 343
323 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( 344 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito(
324 const std::string& event_name, 345 const std::string& event_name,
325 const std::string& event_args, 346 const std::string& event_args,
326 Profile* restrict_to_profile, 347 Profile* restrict_to_profile,
327 const std::string& cross_incognito_args, 348 const std::string& cross_incognito_args,
328 const GURL& event_url) { 349 const GURL& event_url) {
329 linked_ptr<ExtensionEvent> event( 350 linked_ptr<ExtensionEvent> event(
330 new ExtensionEvent(event_name, event_args, event_url, 351 new ExtensionEvent(event_name, event_args, event_url,
331 restrict_to_profile, cross_incognito_args, 352 restrict_to_profile, cross_incognito_args,
332 USER_GESTURE_UNKNOWN)); 353 USER_GESTURE_UNKNOWN, EventFilteringInfo()));
333 DispatchEventImpl("", event); 354 DispatchEventImpl("", event);
334 } 355 }
335 356
336 void ExtensionEventRouter::DispatchEventImpl( 357 void ExtensionEventRouter::DispatchEventImpl(
337 const std::string& extension_id, 358 const std::string& restrict_to_extension_id,
338 const linked_ptr<ExtensionEvent>& event) { 359 const linked_ptr<ExtensionEvent>& event) {
339 // We don't expect to get events from a completely different profile. 360 // We don't expect to get events from a completely different profile.
340 DCHECK(!event->restrict_to_profile || 361 DCHECK(!event->restrict_to_profile ||
341 profile_->IsSameProfile(event->restrict_to_profile)); 362 profile_->IsSameProfile(event->restrict_to_profile));
342 363
343 LoadLazyBackgroundPagesForEvent(extension_id, event); 364 std::set<const EventListener*> listeners(
344 365 listeners_.GetEventListeners(*event));
345 ListenerMap::iterator it = listeners_.find(event->event_name); 366 for (std::set<const EventListener*>::iterator it = listeners.begin();
346 if (it == listeners_.end()) 367 it != listeners.end(); it++) {
347 return; 368 const EventListener* listener = *it;
348 369 if (listener->process) {
349 std::set<ListenerProcess>& listeners = it->second; 370 if (restrict_to_extension_id.empty() ||
350 for (std::set<ListenerProcess>::iterator listener = listeners.begin(); 371 restrict_to_extension_id == listener->extension_id)
351 listener != listeners.end(); ++listener) { 372 DispatchEventToProcess(listener->extension_id, listener->process,
352 if (!extension_id.empty() && extension_id != listener->extension_id) 373 event);
353 continue; 374 } else {
354 375 DispatchLazyEvent(listener->extension_id, event);
355 DispatchEventToListener(*listener, event); 376 }
356 } 377 }
357 } 378 }
358 379
359 void ExtensionEventRouter::DispatchEventToListener( 380 void ExtensionEventRouter::DispatchLazyEvent(
360 const ListenerProcess& listener, 381 const std::string& extension_id,
361 const linked_ptr<ExtensionEvent>& event) { 382 const linked_ptr<ExtensionEvent>& event) {
362 ExtensionService* service = profile_->GetExtensionService(); 383 ExtensionService* service = profile_->GetExtensionService();
363 const Extension* extension = service->extensions()->GetByID( 384 // Check both the original and the incognito profile to see if we
364 listener.extension_id); 385 // should load a lazy bg page to handle the event. The latter case
386 // occurs in the case of split-mode extensions.
387 const Extension* extension = service->extensions()->GetByID(extension_id);
388 if (extension) {
389 MaybeLoadLazyBackgroundPageToDispatchEvent(profile_, extension, event);
390 if (profile_->HasOffTheRecordProfile() &&
391 extension->incognito_split_mode()) {
392 MaybeLoadLazyBackgroundPageToDispatchEvent(
393 profile_->GetOffTheRecordProfile(), extension, event);
394 }
395 }
396 }
397
398 void ExtensionEventRouter::DispatchEventToProcess(
399 const std::string& extension_id,
400 content::RenderProcessHost* process,
401 const linked_ptr<ExtensionEvent>& event) {
402 ExtensionService* service = profile_->GetExtensionService();
403 const Extension* extension = service->extensions()->GetByID(extension_id);
365 404
366 // The extension could have been removed, but we do not unregister it until 405 // The extension could have been removed, but we do not unregister it until
367 // the extension process is unloaded. 406 // the extension process is unloaded.
368 if (!extension) 407 if (!extension)
369 return; 408 return;
370 409
371 Profile* listener_profile = Profile::FromBrowserContext( 410 Profile* listener_profile = Profile::FromBrowserContext(
372 listener.process->GetBrowserContext()); 411 process->GetBrowserContext());
373 extensions::ProcessMap* process_map = 412 extensions::ProcessMap* process_map =
374 listener_profile->GetExtensionService()->process_map(); 413 listener_profile->GetExtensionService()->process_map();
375 // If the event is privileged, only send to extension processes. Otherwise, 414 // If the event is privileged, only send to extension processes. Otherwise,
376 // it's OK to send to normal renderers (e.g., for content scripts). 415 // it's OK to send to normal renderers (e.g., for content scripts).
377 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && 416 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) &&
378 !process_map->Contains(extension->id(), listener.process->GetID())) { 417 !process_map->Contains(extension->id(), process->GetID())) {
379 return; 418 return;
380 } 419 }
381 420
382 const Value* event_args = NULL; 421 const Value* event_args = NULL;
383 if (!CanDispatchEventToProfile(listener_profile, extension, 422 if (!CanDispatchEventToProfile(listener_profile, extension,
384 event, &event_args)) 423 event, &event_args))
385 return; 424 return;
386 425
387 DispatchEvent(listener.process, listener.extension_id, 426 DispatchEvent(process, extension_id,
388 event->event_name, *event_args, 427 event->event_name, *event_args,
389 event->event_url, event->user_gesture); 428 event->event_url, event->user_gesture,
429 event->info);
390 IncrementInFlightEvents(listener_profile, extension); 430 IncrementInFlightEvents(listener_profile, extension);
391 } 431 }
392 432
393 bool ExtensionEventRouter::CanDispatchEventToProfile( 433 bool ExtensionEventRouter::CanDispatchEventToProfile(
394 Profile* profile, 434 Profile* profile,
395 const Extension* extension, 435 const Extension* extension,
396 const linked_ptr<ExtensionEvent>& event, 436 const linked_ptr<ExtensionEvent>& event,
397 const Value** event_args) { 437 const Value** event_args) {
398 *event_args = event->event_args.get(); 438 *event_args = event->event_args.get();
399 439
400 // Is this event from a different profile than the renderer (ie, an 440 // Is this event from a different profile than the renderer (ie, an
401 // incognito tab event sent to a normal process, or vice versa). 441 // incognito tab event sent to a normal process, or vice versa).
402 bool cross_incognito = event->restrict_to_profile && 442 bool cross_incognito = event->restrict_to_profile &&
403 profile != event->restrict_to_profile; 443 profile != event->restrict_to_profile;
404 if (cross_incognito && 444 if (cross_incognito &&
405 !profile->GetExtensionService()->CanCrossIncognito(extension)) { 445 !profile->GetExtensionService()->CanCrossIncognito(extension)) {
406 if (!event->cross_incognito_args.get()) 446 if (!event->cross_incognito_args.get())
407 return false; 447 return false;
408 // Send the event with different arguments to extensions that can't 448 // Send the event with different arguments to extensions that can't
409 // cross incognito. 449 // cross incognito.
410 *event_args = event->cross_incognito_args.get(); 450 *event_args = event->cross_incognito_args.get();
411 } 451 }
412 452
413 return true; 453 return true;
414 } 454 }
415 455
416 void ExtensionEventRouter::LoadLazyBackgroundPagesForEvent( 456 void ExtensionEventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
417 const std::string& extension_id,
418 const linked_ptr<ExtensionEvent>& event) {
419 ExtensionService* service = profile_->GetExtensionService();
420
421 ListenerMap::iterator it = lazy_listeners_.find(event->event_name);
422 if (it == lazy_listeners_.end())
423 return;
424
425 std::set<ListenerProcess>& listeners = it->second;
426 for (std::set<ListenerProcess>::iterator listener = listeners.begin();
427 listener != listeners.end(); ++listener) {
428 if (!extension_id.empty() && extension_id != listener->extension_id)
429 continue;
430
431 // Check both the original and the incognito profile to see if we
432 // should load a lazy bg page to handle the event. The latter case
433 // occurs in the case of split-mode extensions.
434 const Extension* extension = service->extensions()->GetByID(
435 listener->extension_id);
436 if (extension) {
437 MaybeLoadLazyBackgroundPage(profile_, extension, event);
438 if (profile_->HasOffTheRecordProfile() &&
439 extension->incognito_split_mode()) {
440 MaybeLoadLazyBackgroundPage(
441 profile_->GetOffTheRecordProfile(), extension, event);
442 }
443 }
444 }
445 }
446
447 void ExtensionEventRouter::MaybeLoadLazyBackgroundPage(
448 Profile* profile, 457 Profile* profile,
449 const Extension* extension, 458 const Extension* extension,
450 const linked_ptr<ExtensionEvent>& event) { 459 const linked_ptr<ExtensionEvent>& event) {
451 const Value* event_args = NULL; 460 const Value* event_args = NULL;
452 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) 461 if (!CanDispatchEventToProfile(profile, extension, event, &event_args))
453 return; 462 return;
454 463
455 extensions::LazyBackgroundTaskQueue* queue = 464 extensions::LazyBackgroundTaskQueue* queue =
456 ExtensionSystem::Get(profile)->lazy_background_task_queue(); 465 ExtensionSystem::Get(profile)->lazy_background_task_queue();
457 if (queue->ShouldEnqueueTask(profile, extension)) { 466 if (queue->ShouldEnqueueTask(profile, extension)) {
(...skipping 25 matching lines...) Expand all
483 // The event ACK is routed to the background host, so this should never be 492 // The event ACK is routed to the background host, so this should never be
484 // NULL. 493 // NULL.
485 CHECK(host); 494 CHECK(host);
486 // TODO(mpcomplete): We should never get this message unless 495 // TODO(mpcomplete): We should never get this message unless
487 // has_lazy_background_page is true. Find out why we're getting it anyway. 496 // has_lazy_background_page is true. Find out why we're getting it anyway.
488 if (host->extension() && host->extension()->has_lazy_background_page()) 497 if (host->extension() && host->extension()->has_lazy_background_page())
489 pm->DecrementLazyKeepaliveCount(host->extension()); 498 pm->DecrementLazyKeepaliveCount(host->extension());
490 } 499 }
491 500
492 void ExtensionEventRouter::DispatchPendingEvent( 501 void ExtensionEventRouter::DispatchPendingEvent(
493 const linked_ptr<ExtensionEvent>& event, ExtensionHost* host) { 502 const linked_ptr<ExtensionEvent>& event,
503 ExtensionHost* host) {
494 if (!host) 504 if (!host)
495 return; 505 return;
496 506
497 ListenerProcess listener(host->render_process_host(), 507 if (listeners_.HasProcessListener(host->render_process_host(),
498 host->extension()->id()); 508 host->extension()->id()))
499 if (listeners_[event->event_name].count(listener) > 0u) 509 DispatchEventToProcess(host->extension()->id(),
500 DispatchEventToListener(listener, event); 510 host->render_process_host(), event);
501 } 511 }
502 512
503 void ExtensionEventRouter::Observe( 513 void ExtensionEventRouter::Observe(
504 int type, 514 int type,
505 const content::NotificationSource& source, 515 const content::NotificationSource& source,
506 const content::NotificationDetails& details) { 516 const content::NotificationDetails& details) {
507 switch (type) { 517 switch (type) {
508 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 518 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
509 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 519 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
510 content::RenderProcessHost* renderer = 520 content::RenderProcessHost* renderer =
511 content::Source<content::RenderProcessHost>(source).ptr(); 521 content::Source<content::RenderProcessHost>(source).ptr();
512 // Remove all event listeners associated with this renderer. 522 // Remove all event listeners associated with this renderer.
513 for (ListenerMap::iterator it = listeners_.begin(); 523 listeners_.RemoveListenersForProcess(renderer);
514 it != listeners_.end(); ) {
515 ListenerMap::iterator current_it = it++;
516 for (std::set<ListenerProcess>::iterator jt =
517 current_it->second.begin();
518 jt != current_it->second.end(); ) {
519 std::set<ListenerProcess>::iterator current_jt = jt++;
520 if (current_jt->process == renderer) {
521 RemoveEventListener(current_it->first,
522 current_jt->process,
523 current_jt->extension_id);
524 }
525 }
526 }
527 break; 524 break;
528 } 525 }
529 case chrome::NOTIFICATION_EXTENSION_LOADED: { 526 case chrome::NOTIFICATION_EXTENSION_LOADED: {
530 // Add all registered lazy listeners to our cache. 527 // Add all registered lazy listeners to our cache.
531 const Extension* extension = 528 const Extension* extension =
532 content::Details<const Extension>(details).ptr(); 529 content::Details<const Extension>(details).ptr();
530 ExtensionPrefs* prefs =
531 profile_->GetExtensionService()->extension_prefs();
533 std::set<std::string> registered_events = 532 std::set<std::string> registered_events =
534 profile_->GetExtensionService()->extension_prefs()-> 533 prefs->GetRegisteredEvents(extension->id());
535 GetRegisteredEvents(extension->id()); 534 const DictionaryValue* filtered_events =
536 ListenerProcess lazy_listener(NULL, extension->id()); 535 prefs->GetFilteredEvents(extension->id());
537 for (std::set<std::string>::iterator it = registered_events.begin(); 536 if (filtered_events)
538 it != registered_events.end(); ++it) { 537 listeners_.AddLazyListenersFromPreferences(extension->id(),
539 lazy_listeners_[*it].insert(lazy_listener); 538 registered_events,
540 } 539 *filtered_events);
541 break; 540 break;
542 } 541 }
543 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 542 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
544 // Remove all registered lazy listeners from our cache. 543 // Remove all registered lazy listeners from our cache.
545 extensions::UnloadedExtensionInfo* unloaded = 544 extensions::UnloadedExtensionInfo* unloaded =
546 content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); 545 content::Details<extensions::UnloadedExtensionInfo>(details).ptr();
547 ListenerProcess lazy_listener(NULL, unloaded->extension->id()); 546 listeners_.RemoveLazyListenersForExtension(unloaded->extension->id());
548 for (ListenerMap::iterator it = lazy_listeners_.begin();
549 it != lazy_listeners_.end(); ++it) {
550 it->second.erase(lazy_listener);
551 }
552 break; 547 break;
553 } 548 }
554 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { 549 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
555 // Dispatch the onInstalled event. 550 // Dispatch the onInstalled event.
556 const Extension* extension = 551 const Extension* extension =
557 content::Details<const Extension>(details).ptr(); 552 content::Details<const Extension>(details).ptr();
558 MessageLoop::current()->PostTask(FROM_HERE, 553 MessageLoop::current()->PostTask(FROM_HERE,
559 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, 554 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent,
560 profile_, extension->id())); 555 profile_, extension->id()));
561 break; 556 break;
562 } 557 }
563 default: 558 default:
564 NOTREACHED(); 559 NOTREACHED();
565 return; 560 return;
566 } 561 }
567 } 562 }
563
564 ExtensionEvent::ExtensionEvent(
565 const std::string& event_name,
566 const Value& event_args,
567 const GURL& event_url,
568 Profile* restrict_to_profile,
569 const Value& cross_incognito_args,
570 ExtensionEventRouter::UserGestureState user_gesture,
571 const extensions::EventFilteringInfo& info)
572 : event_name(event_name),
573 event_args(event_args.DeepCopy()),
574 event_url(event_url),
575 restrict_to_profile(restrict_to_profile),
576 cross_incognito_args(cross_incognito_args.DeepCopy()),
577 user_gesture(user_gesture),
578 info(info) {
579 }
580
581 ExtensionEvent::ExtensionEvent(
582 const std::string& event_name,
583 const std::string& event_args,
584 const GURL& event_url,
585 Profile* restrict_to_profile,
586 const std::string& cross_incognito_args,
587 ExtensionEventRouter::UserGestureState user_gesture,
588 const extensions::EventFilteringInfo& info)
589 : event_name(event_name),
590 event_args(Value::CreateStringValue(event_args)),
591 event_url(event_url),
592 restrict_to_profile(restrict_to_profile),
593 cross_incognito_args(Value::CreateStringValue(cross_incognito_args)),
594 user_gesture(user_gesture),
595 info(info) {
596 }
597
598 ExtensionEvent::ExtensionEvent(
599 const std::string& event_name,
600 const Value& event_args,
601 const GURL& event_url,
602 Profile* restrict_to_profile,
603 ExtensionEventRouter::UserGestureState user_gesture,
604 const extensions::EventFilteringInfo& info)
605 : event_name(event_name),
606 event_args(event_args.DeepCopy()),
607 event_url(event_url),
608 restrict_to_profile(restrict_to_profile),
609 cross_incognito_args(NULL),
610 user_gesture(user_gesture),
611 info(info) {
612 }
613
614 ExtensionEvent::~ExtensionEvent() {
615 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698