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

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

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

Powered by Google App Engine
This is Rietveld 408576698