OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/values.h" | 9 #include "base/values.h" |
10 #include "chrome/browser/extensions/extension_devtools_manager.h" | 10 #include "chrome/browser/extensions/extension_devtools_manager.h" |
11 #include "chrome/browser/extensions/extension_host.h" | 11 #include "chrome/browser/extensions/extension_host.h" |
12 #include "chrome/browser/extensions/extension_process_manager.h" | 12 #include "chrome/browser/extensions/extension_process_manager.h" |
13 #include "chrome/browser/extensions/extension_processes_api.h" | 13 #include "chrome/browser/extensions/extension_processes_api.h" |
14 #include "chrome/browser/extensions/extension_processes_api_constants.h" | 14 #include "chrome/browser/extensions/extension_processes_api_constants.h" |
15 #include "chrome/browser/extensions/extension_service.h" | 15 #include "chrome/browser/extensions/extension_service.h" |
16 #include "chrome/browser/extensions/extension_tabs_module.h" | 16 #include "chrome/browser/extensions/extension_tabs_module.h" |
17 #include "chrome/browser/extensions/extension_webrequest_api.h" | 17 #include "chrome/browser/extensions/extension_webrequest_api.h" |
18 #include "chrome/browser/extensions/process_map.h" | 18 #include "chrome/browser/extensions/process_map.h" |
19 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
20 #include "chrome/common/chrome_switches.h" | 20 #include "chrome/common/chrome_switches.h" |
21 #include "chrome/common/extensions/extension.h" | 21 #include "chrome/common/extensions/extension.h" |
22 #include "chrome/common/extensions/extension_messages.h" | 22 #include "chrome/common/extensions/extension_messages.h" |
23 #include "chrome/common/extensions/api/extension_api.h" | 23 #include "chrome/common/extensions/api/extension_api.h" |
24 #include "content/browser/child_process_security_policy.h" | 24 #include "content/browser/child_process_security_policy.h" |
25 #include "content/browser/renderer_host/render_process_host.h" | |
26 #include "content/public/browser/notification_service.h" | 25 #include "content/public/browser/notification_service.h" |
| 26 #include "content/public/browser/render_process_host.h" |
27 | 27 |
28 using content::BrowserThread; | 28 using content::BrowserThread; |
29 using extensions::ExtensionAPI; | 29 using extensions::ExtensionAPI; |
30 | 30 |
31 namespace { | 31 namespace { |
32 | 32 |
33 const char kDispatchEvent[] = "Event.dispatchJSON"; | 33 const char kDispatchEvent[] = "Event.dispatchJSON"; |
34 | 34 |
35 void NotifyEventListenerRemovedOnIOThread( | 35 void NotifyEventListenerRemovedOnIOThread( |
36 void* profile, | 36 void* profile, |
37 const std::string& extension_id, | 37 const std::string& extension_id, |
38 const std::string& sub_event_name) { | 38 const std::string& sub_event_name) { |
39 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | 39 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
40 profile, extension_id, sub_event_name); | 40 profile, extension_id, sub_event_name); |
41 } | 41 } |
42 | 42 |
43 } // namespace | 43 } // namespace |
44 | 44 |
45 struct ExtensionEventRouter::EventListener { | 45 struct ExtensionEventRouter::EventListener { |
46 RenderProcessHost* process; | 46 content::RenderProcessHost* process; |
47 std::string extension_id; | 47 std::string extension_id; |
48 | 48 |
49 EventListener(RenderProcessHost* process, const std::string& extension_id) | 49 EventListener(content::RenderProcessHost* process, |
| 50 const std::string& extension_id) |
50 : process(process), extension_id(extension_id) {} | 51 : process(process), extension_id(extension_id) {} |
51 | 52 |
52 bool operator<(const EventListener& that) const { | 53 bool operator<(const EventListener& that) const { |
53 if (process < that.process) | 54 if (process < that.process) |
54 return true; | 55 return true; |
55 if (process == that.process && extension_id < that.extension_id) | 56 if (process == that.process && extension_id < that.extension_id) |
56 return true; | 57 return true; |
57 return false; | 58 return false; |
58 } | 59 } |
59 }; | 60 }; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 content::NotificationService::AllSources()); | 103 content::NotificationService::AllSources()); |
103 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, | 104 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
104 content::Source<Profile>(profile_)); | 105 content::Source<Profile>(profile_)); |
105 // TODO(tessamac): also get notified for background page crash/failure. | 106 // TODO(tessamac): also get notified for background page crash/failure. |
106 } | 107 } |
107 | 108 |
108 ExtensionEventRouter::~ExtensionEventRouter() {} | 109 ExtensionEventRouter::~ExtensionEventRouter() {} |
109 | 110 |
110 void ExtensionEventRouter::AddEventListener( | 111 void ExtensionEventRouter::AddEventListener( |
111 const std::string& event_name, | 112 const std::string& event_name, |
112 RenderProcessHost* process, | 113 content::RenderProcessHost* process, |
113 const std::string& extension_id) { | 114 const std::string& extension_id) { |
114 EventListener listener(process, extension_id); | 115 EventListener listener(process, extension_id); |
115 DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name; | 116 DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name; |
116 listeners_[event_name].insert(listener); | 117 listeners_[event_name].insert(listener); |
117 | 118 |
118 if (extension_devtools_manager_.get()) | 119 if (extension_devtools_manager_.get()) |
119 extension_devtools_manager_->AddEventListener(event_name, process->id()); | 120 extension_devtools_manager_->AddEventListener(event_name, |
| 121 process->GetID()); |
120 | 122 |
121 // We lazily tell the TaskManager to start updating when listeners to the | 123 // We lazily tell the TaskManager to start updating when listeners to the |
122 // processes.onUpdated event arrive. | 124 // processes.onUpdated event arrive. |
123 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0) | 125 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0) |
124 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded(); | 126 ExtensionProcessesEventRouter::GetInstance()->ListenerAdded(); |
125 } | 127 } |
126 | 128 |
127 void ExtensionEventRouter::RemoveEventListener( | 129 void ExtensionEventRouter::RemoveEventListener( |
128 const std::string& event_name, | 130 const std::string& event_name, |
129 RenderProcessHost* process, | 131 content::RenderProcessHost* process, |
130 const std::string& extension_id) { | 132 const std::string& extension_id) { |
131 EventListener listener(process, extension_id); | 133 EventListener listener(process, extension_id); |
132 DCHECK_EQ(listeners_[event_name].count(listener), 1u) << | 134 DCHECK_EQ(listeners_[event_name].count(listener), 1u) << |
133 " PID=" << process->id() << " extension=" << extension_id << | 135 " PID=" << process->GetID() << " extension=" << extension_id << |
134 " event=" << event_name; | 136 " event=" << event_name; |
135 listeners_[event_name].erase(listener); | 137 listeners_[event_name].erase(listener); |
136 // Note: extension_id may point to data in the now-deleted listeners_ object. | 138 // Note: extension_id may point to data in the now-deleted listeners_ object. |
137 // Do not use. | 139 // Do not use. |
138 | 140 |
139 if (extension_devtools_manager_.get()) | 141 if (extension_devtools_manager_.get()) |
140 extension_devtools_manager_->RemoveEventListener(event_name, process->id()); | 142 extension_devtools_manager_->RemoveEventListener(event_name, |
| 143 process->GetID()); |
141 | 144 |
142 // If a processes.onUpdated event listener is removed (or a process with one | 145 // If a processes.onUpdated event listener is removed (or a process with one |
143 // exits), then we let the TaskManager know that it has one fewer listener. | 146 // exits), then we let the TaskManager know that it has one fewer listener. |
144 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0) | 147 if (event_name.compare(extension_processes_api_constants::kOnUpdated) == 0) |
145 ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved(); | 148 ExtensionProcessesEventRouter::GetInstance()->ListenerRemoved(); |
146 | 149 |
147 BrowserThread::PostTask( | 150 BrowserThread::PostTask( |
148 BrowserThread::IO, FROM_HERE, | 151 BrowserThread::IO, FROM_HERE, |
149 base::Bind( | 152 base::Bind( |
150 &NotifyEventListenerRemovedOnIOThread, | 153 &NotifyEventListenerRemovedOnIOThread, |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 | 269 |
267 const Extension* extension = service->GetExtensionById( | 270 const Extension* extension = service->GetExtensionById( |
268 listener->extension_id, false); | 271 listener->extension_id, false); |
269 | 272 |
270 // The extension could have been removed, but we do not unregister it until | 273 // The extension could have been removed, but we do not unregister it until |
271 // the extension process is unloaded. | 274 // the extension process is unloaded. |
272 if (!extension) | 275 if (!extension) |
273 continue; | 276 continue; |
274 | 277 |
275 Profile* listener_profile = Profile::FromBrowserContext( | 278 Profile* listener_profile = Profile::FromBrowserContext( |
276 listener->process->browser_context()); | 279 listener->process->GetBrowserContext()); |
277 extensions::ProcessMap* process_map = | 280 extensions::ProcessMap* process_map = |
278 listener_profile->GetExtensionService()->process_map(); | 281 listener_profile->GetExtensionService()->process_map(); |
279 | |
280 // If the event is privileged, only send to extension processes. Otherwise, | 282 // If the event is privileged, only send to extension processes. Otherwise, |
281 // it's OK to send to normal renderers (e.g., for content scripts). | 283 // it's OK to send to normal renderers (e.g., for content scripts). |
282 if (ExtensionAPI::GetInstance()->IsPrivileged(event->event_name) && | 284 if (ExtensionAPI::GetInstance()->IsPrivileged(event->event_name) && |
283 !process_map->Contains(extension->id(), listener->process->id())) { | 285 !process_map->Contains(extension->id(), listener->process->GetID())) { |
284 continue; | 286 continue; |
285 } | 287 } |
286 | 288 |
287 // Is this event from a different profile than the renderer (ie, an | 289 // Is this event from a different profile than the renderer (ie, an |
288 // incognito tab event sent to a normal process, or vice versa). | 290 // incognito tab event sent to a normal process, or vice versa). |
289 bool cross_incognito = event->restrict_to_profile && | 291 bool cross_incognito = event->restrict_to_profile && |
290 listener_profile != event->restrict_to_profile; | 292 listener_profile != event->restrict_to_profile; |
291 // Send the event with different arguments to extensions that can't | 293 // Send the event with different arguments to extensions that can't |
292 // cross incognito, if necessary. | 294 // cross incognito, if necessary. |
293 if (cross_incognito && !service->CanCrossIncognito(extension)) { | 295 if (cross_incognito && !service->CanCrossIncognito(extension)) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 pending_events_.erase(extension_id); | 361 pending_events_.erase(extension_id); |
360 } | 362 } |
361 | 363 |
362 void ExtensionEventRouter::Observe( | 364 void ExtensionEventRouter::Observe( |
363 int type, | 365 int type, |
364 const content::NotificationSource& source, | 366 const content::NotificationSource& source, |
365 const content::NotificationDetails& details) { | 367 const content::NotificationDetails& details) { |
366 switch (type) { | 368 switch (type) { |
367 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: | 369 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
368 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | 370 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
369 RenderProcessHost* renderer = | 371 content::RenderProcessHost* renderer = |
370 content::Source<RenderProcessHost>(source).ptr(); | 372 content::Source<content::RenderProcessHost>(source).ptr(); |
371 // Remove all event listeners associated with this renderer | 373 // Remove all event listeners associated with this renderer |
372 for (ListenerMap::iterator it = listeners_.begin(); | 374 for (ListenerMap::iterator it = listeners_.begin(); |
373 it != listeners_.end(); ) { | 375 it != listeners_.end(); ) { |
374 ListenerMap::iterator current_it = it++; | 376 ListenerMap::iterator current_it = it++; |
375 for (std::set<EventListener>::iterator jt = current_it->second.begin(); | 377 for (std::set<EventListener>::iterator jt = current_it->second.begin(); |
376 jt != current_it->second.end(); ) { | 378 jt != current_it->second.end(); ) { |
377 std::set<EventListener>::iterator current_jt = jt++; | 379 std::set<EventListener>::iterator current_jt = jt++; |
378 if (current_jt->process == renderer) { | 380 if (current_jt->process == renderer) { |
379 RemoveEventListener(current_it->first, | 381 RemoveEventListener(current_it->first, |
380 current_jt->process, | 382 current_jt->process, |
381 current_jt->extension_id); | 383 current_jt->extension_id); |
382 } | 384 } |
383 } | 385 } |
384 } | 386 } |
385 break; | 387 break; |
386 } | 388 } |
387 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: { | 389 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: { |
388 // TODO: dispatch events in queue. ExtensionHost is in the details. | 390 // TODO: dispatch events in queue. ExtensionHost is in the details. |
389 ExtensionHost* eh = content::Details<ExtensionHost>(details).ptr(); | 391 ExtensionHost* eh = content::Details<ExtensionHost>(details).ptr(); |
390 DispatchPendingEvents(eh->extension_id()); | 392 DispatchPendingEvents(eh->extension_id()); |
391 break; | 393 break; |
392 } | 394 } |
393 // TODO(tessamac): if background page crashed/failed clear queue. | 395 // TODO(tessamac): if background page crashed/failed clear queue. |
394 default: | 396 default: |
395 NOTREACHED(); | 397 NOTREACHED(); |
396 return; | 398 return; |
397 } | 399 } |
398 } | 400 } |
OLD | NEW |