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

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

Powered by Google App Engine
This is Rietveld 408576698