OLD | NEW |
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/values.h" | 9 #include "base/values.h" |
10 #include "chrome/browser/extensions/api/runtime/runtime_api.h" | 10 #include "chrome/browser/extensions/api/runtime/runtime_api.h" |
(...skipping 101 matching lines...) Loading... |
112 content::Source<Profile>(profile_)); | 112 content::Source<Profile>(profile_)); |
113 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 113 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
114 content::Source<Profile>(profile_)); | 114 content::Source<Profile>(profile_)); |
115 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, | 115 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, |
116 content::Source<Profile>(profile_)); | 116 content::Source<Profile>(profile_)); |
117 // TODO(tessamac): also get notified for background page crash/failure. | 117 // TODO(tessamac): also get notified for background page crash/failure. |
118 } | 118 } |
119 | 119 |
120 ExtensionEventRouter::~ExtensionEventRouter() {} | 120 ExtensionEventRouter::~ExtensionEventRouter() {} |
121 | 121 |
| 122 bool ExtensionEventRouter::IsEventAvailable( |
| 123 const std::string& event_name, |
| 124 const std::string& extension_id, |
| 125 content::RenderProcessHost* render_process, |
| 126 Feature::Context context_type) const { |
| 127 ExtensionService* extension_service = profile_->GetExtensionService(); |
| 128 const Extension* extension = |
| 129 extension_service->extensions()->GetByID(extension_id); |
| 130 if (!extension) |
| 131 return false; |
| 132 |
| 133 ExtensionAPI* api = ExtensionAPI::GetSharedInstance(); |
| 134 |
| 135 // If the API has been ported to the feature system, use that. |
| 136 if (api->GetFeature(event_name)) { |
| 137 if (!api->IsAvailable( |
| 138 event_name, |
| 139 extension, |
| 140 static_cast<Feature::Context>(context_type))) { |
| 141 LOG(ERROR) << "Access to extension API '" << event_name << "' denied."; |
| 142 return false; |
| 143 } |
| 144 } else { |
| 145 // Otherwise, fall back to the older system. |
| 146 // TODO(aa): Remove this when all APIs have been ported. |
| 147 if (!extension->HasAPIPermission(event_name)) { |
| 148 LOG(ERROR) << "Extension " << extension->id() << " does not have " |
| 149 << "permission to event: " << event_name; |
| 150 return false; |
| 151 } |
| 152 } |
| 153 |
| 154 // If the API requires a privileged process, ensure it is in one. |
| 155 if (api->IsPrivileged(event_name) && |
| 156 !extension_service->process_map()->Contains(extension->id(), |
| 157 render_process->GetID())) { |
| 158 LOG(ERROR) << "Extension API called from incorrect process"; |
| 159 return false; |
| 160 } |
| 161 |
| 162 return true; |
| 163 } |
| 164 |
122 void ExtensionEventRouter::AddEventListener( | 165 void ExtensionEventRouter::AddEventListener( |
123 const std::string& event_name, | 166 const std::string& event_name, |
| 167 const std::string& extension_id, |
124 content::RenderProcessHost* process, | 168 content::RenderProcessHost* process, |
125 const std::string& extension_id) { | 169 Feature::Context context_type) { |
| 170 if (!IsEventAvailable(event_name, extension_id, process, context_type)) |
| 171 return; |
| 172 |
126 ListenerProcess listener(process, extension_id); | 173 ListenerProcess listener(process, extension_id); |
127 DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name; | 174 DCHECK_EQ(listeners_[event_name].count(listener), 0u) << event_name; |
128 listeners_[event_name].insert(listener); | 175 listeners_[event_name].insert(listener); |
129 | 176 |
130 if (extension_devtools_manager_.get()) | 177 if (extension_devtools_manager_.get()) |
131 extension_devtools_manager_->AddEventListener(event_name, | 178 extension_devtools_manager_->AddEventListener(event_name, |
132 process->GetID()); | 179 process->GetID()); |
133 | 180 |
134 // We lazily tell the TaskManager to start updating when listeners to the | 181 // We lazily tell the TaskManager to start updating when listeners to the |
135 // processes.onUpdated event arrive. | 182 // processes.onUpdated event arrive. |
(...skipping 24 matching lines...) Loading... |
160 | 207 |
161 BrowserThread::PostTask( | 208 BrowserThread::PostTask( |
162 BrowserThread::IO, FROM_HERE, | 209 BrowserThread::IO, FROM_HERE, |
163 base::Bind( | 210 base::Bind( |
164 &NotifyEventListenerRemovedOnIOThread, | 211 &NotifyEventListenerRemovedOnIOThread, |
165 profile_, listener.extension_id, event_name)); | 212 profile_, listener.extension_id, event_name)); |
166 } | 213 } |
167 | 214 |
168 void ExtensionEventRouter::AddLazyEventListener( | 215 void ExtensionEventRouter::AddLazyEventListener( |
169 const std::string& event_name, | 216 const std::string& event_name, |
| 217 const std::string& extension_id, |
| 218 content::RenderProcessHost* render_process, |
| 219 Feature::Context context_type) { |
| 220 if (!IsEventAvailable(event_name, extension_id, render_process, context_type)) |
| 221 AddLazyEventListener(event_name, extension_id); |
| 222 } |
| 223 |
| 224 void ExtensionEventRouter::AddLazyEventListener( |
| 225 const std::string& event_name, |
170 const std::string& extension_id) { | 226 const std::string& extension_id) { |
171 ListenerProcess lazy_listener(NULL, extension_id); | 227 ListenerProcess lazy_listener(NULL, extension_id); |
172 bool is_new = lazy_listeners_[event_name].insert(lazy_listener).second; | 228 bool is_new = lazy_listeners_[event_name].insert(lazy_listener).second; |
173 if (is_new) { | 229 if (is_new) { |
174 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 230 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
175 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); | 231 std::set<std::string> events = prefs->GetRegisteredEvents(extension_id); |
176 bool prefs_is_new = events.insert(event_name).second; | 232 bool prefs_is_new = events.insert(event_name).second; |
177 if (prefs_is_new) | 233 if (prefs_is_new) |
178 prefs->SetRegisteredEvents(extension_id, events); | 234 prefs->SetRegisteredEvents(extension_id, events); |
179 } | 235 } |
(...skipping 125 matching lines...) Loading... |
305 const Extension* extension = service->extensions()->GetByID( | 361 const Extension* extension = service->extensions()->GetByID( |
306 listener.extension_id); | 362 listener.extension_id); |
307 | 363 |
308 // The extension could have been removed, but we do not unregister it until | 364 // The extension could have been removed, but we do not unregister it until |
309 // the extension process is unloaded. | 365 // the extension process is unloaded. |
310 if (!extension) | 366 if (!extension) |
311 return; | 367 return; |
312 | 368 |
313 Profile* listener_profile = Profile::FromBrowserContext( | 369 Profile* listener_profile = Profile::FromBrowserContext( |
314 listener.process->GetBrowserContext()); | 370 listener.process->GetBrowserContext()); |
315 extensions::ProcessMap* process_map = | |
316 listener_profile->GetExtensionService()->process_map(); | |
317 // If the event is privileged, only send to extension processes. Otherwise, | |
318 // it's OK to send to normal renderers (e.g., for content scripts). | |
319 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && | |
320 !process_map->Contains(extension->id(), listener.process->GetID())) { | |
321 return; | |
322 } | |
323 | |
324 const std::string* event_args; | 371 const std::string* event_args; |
325 if (!CanDispatchEventToProfile(listener_profile, extension, | 372 if (!CanDispatchEventToProfile(listener_profile, extension, |
326 event, &event_args)) | 373 event, &event_args)) |
327 return; | 374 return; |
328 | 375 |
329 DispatchEvent(listener.process, listener.extension_id, | 376 DispatchEvent(listener.process, listener.extension_id, |
330 event->event_name, *event_args, | 377 event->event_name, *event_args, |
331 event->event_url, event->user_gesture); | 378 event->event_url, event->user_gesture); |
332 IncrementInFlightEvents(listener_profile, extension); | 379 IncrementInFlightEvents(listener_profile, extension); |
333 } | 380 } |
(...skipping 155 matching lines...) Loading... |
489 profile_, extension); | 536 profile_, extension); |
490 break; | 537 break; |
491 } | 538 } |
492 | 539 |
493 // TODO(tessamac): if background page crashed/failed clear queue. | 540 // TODO(tessamac): if background page crashed/failed clear queue. |
494 default: | 541 default: |
495 NOTREACHED(); | 542 NOTREACHED(); |
496 return; | 543 return; |
497 } | 544 } |
498 } | 545 } |
OLD | NEW |