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

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: rebase, reland Created 8 years, 5 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::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,
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,
278 const GURL& event_url) { 307 const GURL& event_url) {
279 linked_ptr<ExtensionEvent> event( 308 DispatchEventToRenderers(event_name, event_args, restrict_to_profile,
280 new ExtensionEvent(event_name, event_args, event_url, 309 event_url, extensions::EventFilteringInfo());
281 restrict_to_profile, "", USER_GESTURE_UNKNOWN));
282 DispatchEventImpl("", event);
283 } 310 }
284 311
285 void ExtensionEventRouter::DispatchEventToExtension( 312 void ExtensionEventRouter::DispatchEventToExtension(
286 const std::string& extension_id, 313 const std::string& extension_id,
287 const std::string& event_name, 314 const std::string& event_name,
288 const Value& event_args, 315 const Value& event_args,
289 Profile* restrict_to_profile, 316 Profile* restrict_to_profile,
290 const GURL& event_url) { 317 const GURL& event_url) {
291 DCHECK(!extension_id.empty()); 318 DCHECK(!extension_id.empty());
292 linked_ptr<ExtensionEvent> event( 319 linked_ptr<ExtensionEvent> event(
293 new ExtensionEvent(event_name, event_args, event_url, 320 new ExtensionEvent(event_name, event_args, event_url,
294 restrict_to_profile, USER_GESTURE_UNKNOWN)); 321 restrict_to_profile, USER_GESTURE_UNKNOWN,
322 EventFilteringInfo()));
295 DispatchEventImpl(extension_id, event); 323 DispatchEventImpl(extension_id, event);
296 } 324 }
297 325
298 void ExtensionEventRouter::DispatchEventToExtension( 326 void ExtensionEventRouter::DispatchEventToExtension(
299 const std::string& extension_id, 327 const std::string& extension_id,
300 const std::string& event_name, 328 const std::string& event_name,
301 const std::string& event_args, 329 const std::string& event_args,
302 Profile* restrict_to_profile, 330 Profile* restrict_to_profile,
303 const GURL& event_url) { 331 const GURL& event_url) {
304 scoped_ptr<Value> event_args_value(Value::CreateStringValue(event_args)); 332 StringValue event_args_value(event_args);
305 DispatchEventToExtension(extension_id, event_name, *event_args_value.get(), 333 DispatchEventToExtension(extension_id, event_name, event_args_value,
306 restrict_to_profile, event_url); 334 restrict_to_profile, event_url);
307 } 335 }
308 336
309 void ExtensionEventRouter::DispatchEventToExtension( 337 void ExtensionEventRouter::DispatchEventToExtension(
310 const std::string& extension_id, 338 const std::string& extension_id,
311 const std::string& event_name, 339 const std::string& event_name,
312 const std::string& event_args, 340 const std::string& event_args,
313 Profile* restrict_to_profile, 341 Profile* restrict_to_profile,
314 const GURL& event_url, 342 const GURL& event_url,
315 UserGestureState user_gesture) { 343 UserGestureState user_gesture) {
316 DCHECK(!extension_id.empty()); 344 DCHECK(!extension_id.empty());
345 StringValue event_args_value(event_args);
317 linked_ptr<ExtensionEvent> event( 346 linked_ptr<ExtensionEvent> event(
318 new ExtensionEvent(event_name, event_args, event_url, 347 new ExtensionEvent(event_name, event_args_value, event_url,
319 restrict_to_profile, "", user_gesture)); 348 restrict_to_profile, user_gesture,
349 EventFilteringInfo()));
320 DispatchEventImpl(extension_id, event); 350 DispatchEventImpl(extension_id, event);
321 } 351 }
322 352
323 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( 353 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito(
324 const std::string& event_name, 354 const std::string& event_name,
325 const std::string& event_args, 355 const std::string& event_args,
326 Profile* restrict_to_profile, 356 Profile* restrict_to_profile,
327 const std::string& cross_incognito_args, 357 const std::string& cross_incognito_args,
328 const GURL& event_url) { 358 const GURL& event_url) {
329 linked_ptr<ExtensionEvent> event( 359 linked_ptr<ExtensionEvent> event(
330 new ExtensionEvent(event_name, event_args, event_url, 360 new ExtensionEvent(event_name, event_args, event_url,
331 restrict_to_profile, cross_incognito_args, 361 restrict_to_profile, cross_incognito_args,
332 USER_GESTURE_UNKNOWN)); 362 USER_GESTURE_UNKNOWN, EventFilteringInfo()));
333 DispatchEventImpl("", event); 363 DispatchEventImpl("", event);
334 } 364 }
335 365
336 void ExtensionEventRouter::DispatchEventImpl( 366 void ExtensionEventRouter::DispatchEventImpl(
337 const std::string& extension_id, 367 const std::string& restrict_to_extension_id,
338 const linked_ptr<ExtensionEvent>& event) { 368 const linked_ptr<ExtensionEvent>& event) {
339 // We don't expect to get events from a completely different profile. 369 // We don't expect to get events from a completely different profile.
340 DCHECK(!event->restrict_to_profile || 370 DCHECK(!event->restrict_to_profile ||
341 profile_->IsSameProfile(event->restrict_to_profile)); 371 profile_->IsSameProfile(event->restrict_to_profile));
342 372
343 LoadLazyBackgroundPagesForEvent(extension_id, event); 373 std::set<const EventListener*> listeners(
344 374 listeners_.GetEventListeners(*event));
345 ListenerMap::iterator it = listeners_.find(event->event_name); 375 for (std::set<const EventListener*>::iterator it = listeners.begin();
346 if (it == listeners_.end()) 376 it != listeners.end(); it++) {
347 return; 377 const EventListener* listener = *it;
348 378 if (listener->process) {
349 std::set<ListenerProcess>& listeners = it->second; 379 if (restrict_to_extension_id.empty() ||
350 for (std::set<ListenerProcess>::iterator listener = listeners.begin(); 380 restrict_to_extension_id == listener->extension_id)
351 listener != listeners.end(); ++listener) { 381 DispatchEventToProcess(listener->extension_id, listener->process,
352 if (!extension_id.empty() && extension_id != listener->extension_id) 382 event);
353 continue; 383 } else {
354 384 DispatchLazyEvent(listener->extension_id, event);
355 DispatchEventToListener(*listener, event); 385 }
356 } 386 }
357 } 387 }
358 388
359 void ExtensionEventRouter::DispatchEventToListener( 389 void ExtensionEventRouter::DispatchLazyEvent(
360 const ListenerProcess& listener, 390 const std::string& extension_id,
361 const linked_ptr<ExtensionEvent>& event) { 391 const linked_ptr<ExtensionEvent>& event) {
362 ExtensionService* service = profile_->GetExtensionService(); 392 ExtensionService* service = profile_->GetExtensionService();
363 const Extension* extension = service->extensions()->GetByID( 393 // Check both the original and the incognito profile to see if we
364 listener.extension_id); 394 // should load a lazy bg page to handle the event. The latter case
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);
365 413
366 // The extension could have been removed, but we do not unregister it until 414 // The extension could have been removed, but we do not unregister it until
367 // the extension process is unloaded. 415 // the extension process is unloaded.
368 if (!extension) 416 if (!extension)
369 return; 417 return;
370 418
371 Profile* listener_profile = Profile::FromBrowserContext( 419 Profile* listener_profile = Profile::FromBrowserContext(
372 listener.process->GetBrowserContext()); 420 process->GetBrowserContext());
373 extensions::ProcessMap* process_map = 421 extensions::ProcessMap* process_map =
374 listener_profile->GetExtensionService()->process_map(); 422 listener_profile->GetExtensionService()->process_map();
375 // If the event is privileged, only send to extension processes. Otherwise, 423 // 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). 424 // it's OK to send to normal renderers (e.g., for content scripts).
377 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && 425 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) &&
378 !process_map->Contains(extension->id(), listener.process->GetID())) { 426 !process_map->Contains(extension->id(), process->GetID())) {
379 return; 427 return;
380 } 428 }
381 429
382 const Value* event_args = NULL; 430 const Value* event_args = NULL;
383 if (!CanDispatchEventToProfile(listener_profile, extension, 431 if (!CanDispatchEventToProfile(listener_profile, extension,
384 event, &event_args)) { 432 event, &event_args)) {
385 return; 433 return;
386 } 434 }
387 435
388 DispatchEvent(listener.process, listener.extension_id, 436 DispatchEvent(process, extension_id,
389 event->event_name, *event_args, 437 event->event_name, *event_args,
390 event->event_url, event->user_gesture); 438 event->event_url, event->user_gesture,
439 event->info);
391 IncrementInFlightEvents(listener_profile, extension); 440 IncrementInFlightEvents(listener_profile, extension);
392 } 441 }
393 442
394 bool ExtensionEventRouter::CanDispatchEventToProfile( 443 bool ExtensionEventRouter::CanDispatchEventToProfile(
395 Profile* profile, 444 Profile* profile,
396 const Extension* extension, 445 const Extension* extension,
397 const linked_ptr<ExtensionEvent>& event, 446 const linked_ptr<ExtensionEvent>& event,
398 const Value** event_args) { 447 const Value** event_args) {
399 *event_args = event->event_args.get(); 448 *event_args = event->event_args.get();
400 449
401 // Is this event from a different profile than the renderer (ie, an 450 // Is this event from a different profile than the renderer (ie, an
402 // incognito tab event sent to a normal process, or vice versa). 451 // incognito tab event sent to a normal process, or vice versa).
403 bool cross_incognito = event->restrict_to_profile && 452 bool cross_incognito = event->restrict_to_profile &&
404 profile != event->restrict_to_profile; 453 profile != event->restrict_to_profile;
405 if (cross_incognito && 454 if (cross_incognito &&
406 !profile->GetExtensionService()->CanCrossIncognito(extension)) { 455 !profile->GetExtensionService()->CanCrossIncognito(extension)) {
407 if (!event->cross_incognito_args.get()) 456 if (!event->cross_incognito_args.get())
408 return false; 457 return false;
409 // Send the event with different arguments to extensions that can't 458 // Send the event with different arguments to extensions that can't
410 // cross incognito. 459 // cross incognito.
411 *event_args = event->cross_incognito_args.get(); 460 *event_args = event->cross_incognito_args.get();
412 } 461 }
413 462
414 return true; 463 return true;
415 } 464 }
416 465
417 void ExtensionEventRouter::LoadLazyBackgroundPagesForEvent( 466 void ExtensionEventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent(
418 const std::string& extension_id,
419 const linked_ptr<ExtensionEvent>& event) {
420 ExtensionService* service = profile_->GetExtensionService();
421
422 ListenerMap::iterator it = lazy_listeners_.find(event->event_name);
423 if (it == lazy_listeners_.end())
424 return;
425
426 std::set<ListenerProcess>& listeners = it->second;
427 for (std::set<ListenerProcess>::iterator listener = listeners.begin();
428 listener != listeners.end(); ++listener) {
429 if (!extension_id.empty() && extension_id != listener->extension_id)
430 continue;
431
432 // Check both the original and the incognito profile to see if we
433 // should load a lazy bg page to handle the event. The latter case
434 // occurs in the case of split-mode extensions.
435 const Extension* extension = service->extensions()->GetByID(
436 listener->extension_id);
437 if (extension) {
438 MaybeLoadLazyBackgroundPage(profile_, extension, event);
439 if (profile_->HasOffTheRecordProfile() &&
440 extension->incognito_split_mode()) {
441 MaybeLoadLazyBackgroundPage(
442 profile_->GetOffTheRecordProfile(), extension, event);
443 }
444 }
445 }
446 }
447
448 void ExtensionEventRouter::MaybeLoadLazyBackgroundPage(
449 Profile* profile, 467 Profile* profile,
450 const Extension* extension, 468 const Extension* extension,
451 const linked_ptr<ExtensionEvent>& event) { 469 const linked_ptr<ExtensionEvent>& event) {
452 const Value* event_args = NULL; 470 const Value* event_args = NULL;
453 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) 471 if (!CanDispatchEventToProfile(profile, extension, event, &event_args))
454 return; 472 return;
455 473
456 extensions::LazyBackgroundTaskQueue* queue = 474 extensions::LazyBackgroundTaskQueue* queue =
457 ExtensionSystem::Get(profile)->lazy_background_task_queue(); 475 ExtensionSystem::Get(profile)->lazy_background_task_queue();
458 if (queue->ShouldEnqueueTask(profile, extension)) { 476 if (queue->ShouldEnqueueTask(profile, extension)) {
(...skipping 25 matching lines...) Expand all
484 // The event ACK is routed to the background host, so this should never be 502 // The event ACK is routed to the background host, so this should never be
485 // NULL. 503 // NULL.
486 CHECK(host); 504 CHECK(host);
487 // TODO(mpcomplete): We should never get this message unless 505 // TODO(mpcomplete): We should never get this message unless
488 // has_lazy_background_page is true. Find out why we're getting it anyway. 506 // has_lazy_background_page is true. Find out why we're getting it anyway.
489 if (host->extension() && host->extension()->has_lazy_background_page()) 507 if (host->extension() && host->extension()->has_lazy_background_page())
490 pm->DecrementLazyKeepaliveCount(host->extension()); 508 pm->DecrementLazyKeepaliveCount(host->extension());
491 } 509 }
492 510
493 void ExtensionEventRouter::DispatchPendingEvent( 511 void ExtensionEventRouter::DispatchPendingEvent(
494 const linked_ptr<ExtensionEvent>& event, ExtensionHost* host) { 512 const linked_ptr<ExtensionEvent>& event,
513 ExtensionHost* host) {
495 if (!host) 514 if (!host)
496 return; 515 return;
497 516
498 ListenerProcess listener(host->render_process_host(), 517 if (listeners_.HasProcessListener(host->render_process_host(),
499 host->extension()->id()); 518 host->extension()->id()))
500 if (listeners_[event->event_name].count(listener) > 0u) 519 DispatchEventToProcess(host->extension()->id(),
501 DispatchEventToListener(listener, event); 520 host->render_process_host(), event);
502 } 521 }
503 522
504 void ExtensionEventRouter::Observe( 523 void ExtensionEventRouter::Observe(
505 int type, 524 int type,
506 const content::NotificationSource& source, 525 const content::NotificationSource& source,
507 const content::NotificationDetails& details) { 526 const content::NotificationDetails& details) {
508 switch (type) { 527 switch (type) {
509 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 528 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
510 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 529 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
511 content::RenderProcessHost* renderer = 530 content::RenderProcessHost* renderer =
512 content::Source<content::RenderProcessHost>(source).ptr(); 531 content::Source<content::RenderProcessHost>(source).ptr();
513 // Remove all event listeners associated with this renderer. 532 // Remove all event listeners associated with this renderer.
514 for (ListenerMap::iterator it = listeners_.begin(); 533 listeners_.RemoveListenersForProcess(renderer);
515 it != listeners_.end(); ) {
516 ListenerMap::iterator current_it = it++;
517 for (std::set<ListenerProcess>::iterator jt =
518 current_it->second.begin();
519 jt != current_it->second.end(); ) {
520 std::set<ListenerProcess>::iterator current_jt = jt++;
521 if (current_jt->process == renderer) {
522 RemoveEventListener(current_it->first,
523 current_jt->process,
524 current_jt->extension_id);
525 }
526 }
527 }
528 break; 534 break;
529 } 535 }
530 case chrome::NOTIFICATION_EXTENSION_LOADED: { 536 case chrome::NOTIFICATION_EXTENSION_LOADED: {
531 // Add all registered lazy listeners to our cache. 537 // Add all registered lazy listeners to our cache.
532 const Extension* extension = 538 const Extension* extension =
533 content::Details<const Extension>(details).ptr(); 539 content::Details<const Extension>(details).ptr();
540 ExtensionPrefs* prefs =
541 profile_->GetExtensionService()->extension_prefs();
534 std::set<std::string> registered_events = 542 std::set<std::string> registered_events =
535 profile_->GetExtensionService()->extension_prefs()-> 543 prefs->GetRegisteredEvents(extension->id());
536 GetRegisteredEvents(extension->id()); 544 listeners_.LoadUnfilteredLazyListeners(extension->id(),
537 ListenerProcess lazy_listener(NULL, extension->id()); 545 registered_events);
538 for (std::set<std::string>::iterator it = registered_events.begin(); 546 const DictionaryValue* filtered_events =
539 it != registered_events.end(); ++it) { 547 prefs->GetFilteredEvents(extension->id());
540 lazy_listeners_[*it].insert(lazy_listener); 548 if (filtered_events)
541 } 549 listeners_.LoadFilteredLazyListeners(extension->id(), *filtered_events);
542 break; 550 break;
543 } 551 }
544 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 552 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
545 // Remove all registered lazy listeners from our cache. 553 // Remove all registered lazy listeners from our cache.
546 extensions::UnloadedExtensionInfo* unloaded = 554 extensions::UnloadedExtensionInfo* unloaded =
547 content::Details<extensions::UnloadedExtensionInfo>(details).ptr(); 555 content::Details<extensions::UnloadedExtensionInfo>(details).ptr();
548 ListenerProcess lazy_listener(NULL, unloaded->extension->id()); 556 listeners_.RemoveLazyListenersForExtension(unloaded->extension->id());
549 for (ListenerMap::iterator it = lazy_listeners_.begin();
550 it != lazy_listeners_.end(); ++it) {
551 it->second.erase(lazy_listener);
552 }
553 break; 557 break;
554 } 558 }
555 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { 559 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
556 // Dispatch the onInstalled event. 560 // Dispatch the onInstalled event.
557 const Extension* extension = 561 const Extension* extension =
558 content::Details<const Extension>(details).ptr(); 562 content::Details<const Extension>(details).ptr();
559 MessageLoop::current()->PostTask(FROM_HERE, 563 MessageLoop::current()->PostTask(FROM_HERE,
560 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, 564 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent,
561 profile_, extension->id())); 565 profile_, extension->id()));
562 break; 566 break;
563 } 567 }
564 default: 568 default:
565 NOTREACHED(); 569 NOTREACHED();
566 return; 570 return;
567 } 571 }
568 } 572 }
573
574 ExtensionEvent::ExtensionEvent(
575 const std::string& event_name,
576 const Value& event_args,
577 const GURL& event_url,
578 Profile* restrict_to_profile,
579 const Value& cross_incognito_args,
580 ExtensionEventRouter::UserGestureState user_gesture,
581 const extensions::EventFilteringInfo& info)
582 : event_name(event_name),
583 event_args(event_args.DeepCopy()),
584 event_url(event_url),
585 restrict_to_profile(restrict_to_profile),
586 cross_incognito_args(cross_incognito_args.DeepCopy()),
587 user_gesture(user_gesture),
588 info(info) {
589 }
590
591 ExtensionEvent::ExtensionEvent(
592 const std::string& event_name,
593 const std::string& event_args,
594 const GURL& event_url,
595 Profile* restrict_to_profile,
596 const std::string& cross_incognito_args,
597 ExtensionEventRouter::UserGestureState user_gesture,
598 const extensions::EventFilteringInfo& info)
599 : event_name(event_name),
600 event_args(Value::CreateStringValue(event_args)),
601 event_url(event_url),
602 restrict_to_profile(restrict_to_profile),
603 cross_incognito_args(Value::CreateStringValue(cross_incognito_args)),
604 user_gesture(user_gesture),
605 info(info) {
606 }
607
608 ExtensionEvent::ExtensionEvent(
609 const std::string& event_name,
610 const Value& event_args,
611 const GURL& event_url,
612 Profile* restrict_to_profile,
613 ExtensionEventRouter::UserGestureState user_gesture,
614 const extensions::EventFilteringInfo& info)
615 : event_name(event_name),
616 event_args(event_args.DeepCopy()),
617 event_url(event_url),
618 restrict_to_profile(restrict_to_profile),
619 cross_incognito_args(NULL),
620 user_gesture(user_gesture),
621 info(info) {
622 }
623
624 ExtensionEvent::~ExtensionEvent() {
625 }
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