Chromium Code Reviews| 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/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/values.h" | 10 #include "base/values.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
| 23 #include "chrome/common/chrome_notification_types.h" | 23 #include "chrome/common/chrome_notification_types.h" |
| 24 #include "chrome/common/chrome_switches.h" | 24 #include "chrome/common/chrome_switches.h" |
| 25 #include "chrome/common/extensions/extension.h" | 25 #include "chrome/common/extensions/extension.h" |
| 26 #include "chrome/common/extensions/extension_messages.h" | 26 #include "chrome/common/extensions/extension_messages.h" |
| 27 #include "chrome/common/extensions/api/extension_api.h" | 27 #include "chrome/common/extensions/api/extension_api.h" |
| 28 #include "chrome/common/view_type.h" | 28 #include "chrome/common/view_type.h" |
| 29 #include "content/public/browser/notification_service.h" | 29 #include "content/public/browser/notification_service.h" |
| 30 #include "content/public/browser/render_process_host.h" | 30 #include "content/public/browser/render_process_host.h" |
| 31 | 31 |
| 32 using base::Value; | |
| 32 using content::BrowserThread; | 33 using content::BrowserThread; |
| 33 using extensions::Extension; | 34 using extensions::Extension; |
| 34 using extensions::ExtensionAPI; | 35 using extensions::ExtensionAPI; |
| 35 | 36 |
| 36 namespace { | 37 namespace { |
| 37 | 38 |
| 38 const char kDispatchEvent[] = "Event.dispatchJSON"; | 39 const char kDispatchEvent[] = "Event.dispatchJSON"; |
| 39 | 40 |
| 40 void NotifyEventListenerRemovedOnIOThread( | 41 void NotifyEventListenerRemovedOnIOThread( |
| 41 void* profile, | 42 void* profile, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 59 if (process < that.process) | 60 if (process < that.process) |
| 60 return true; | 61 return true; |
| 61 if (process == that.process && extension_id < that.extension_id) | 62 if (process == that.process && extension_id < that.extension_id) |
| 62 return true; | 63 return true; |
| 63 return false; | 64 return false; |
| 64 } | 65 } |
| 65 }; | 66 }; |
| 66 | 67 |
| 67 struct ExtensionEventRouter::ExtensionEvent { | 68 struct ExtensionEventRouter::ExtensionEvent { |
| 68 std::string event_name; | 69 std::string event_name; |
| 69 std::string event_args; | 70 scoped_ptr<Value> event_args; |
| 70 GURL event_url; | 71 GURL event_url; |
| 71 Profile* restrict_to_profile; | 72 Profile* restrict_to_profile; |
| 72 std::string cross_incognito_args; | 73 scoped_ptr<Value> cross_incognito_args; |
| 73 UserGestureState user_gesture; | 74 UserGestureState user_gesture; |
| 74 | 75 |
| 75 ExtensionEvent(const std::string& event_name, | 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, | |
| 76 const std::string& event_args, | 104 const std::string& event_args, |
| 77 const GURL& event_url, | 105 const GURL& event_url, |
| 78 Profile* restrict_to_profile, | 106 Profile* restrict_to_profile, |
| 79 const std::string& cross_incognito_args, | 107 const std::string& cross_incognito_args, |
| 80 UserGestureState user_gesture) | 108 UserGestureState user_gesture) |
| 81 : event_name(event_name), | 109 : event_name(event_name), |
| 82 event_args(event_args), | 110 event_args(Value::CreateStringValue(event_args)), |
| 83 event_url(event_url), | 111 event_url(event_url), |
| 84 restrict_to_profile(restrict_to_profile), | 112 restrict_to_profile(restrict_to_profile), |
| 85 cross_incognito_args(cross_incognito_args), | 113 cross_incognito_args(Value::CreateStringValue(cross_incognito_args)), |
| 86 user_gesture(user_gesture) {} | 114 user_gesture(user_gesture) {} |
| 87 }; | 115 }; |
| 88 | 116 |
| 89 // static | 117 // static |
| 90 void ExtensionEventRouter::DispatchEvent(IPC::Sender* ipc_sender, | 118 void ExtensionEventRouter::DispatchEvent(IPC::Sender* ipc_sender, |
| 91 const std::string& extension_id, | 119 const std::string& extension_id, |
| 92 const std::string& event_name, | 120 const std::string& event_name, |
| 121 const Value& event_args, | |
| 122 const GURL& event_url, | |
| 123 UserGestureState user_gesture) { | |
| 124 ListValue args; | |
| 125 args.Set(0, Value::CreateStringValue(event_name)); | |
| 126 args.Set(1, event_args.DeepCopy()); | |
|
asargent_no_longer_on_chrome
2012/06/18 16:25:30
It's a bummer to have to copy the arguments just t
Garret Kelly
2012/06/18 18:15:01
I've added a TODO, I'll refactor that as part of t
| |
| 127 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, | |
| 128 extension_id, kDispatchEvent, args, event_url, | |
| 129 user_gesture == USER_GESTURE_ENABLED)); | |
| 130 } | |
| 131 | |
| 132 // static | |
| 133 void ExtensionEventRouter::DispatchEvent(IPC::Sender* ipc_sender, | |
| 134 const std::string& extension_id, | |
| 135 const std::string& event_name, | |
| 93 const std::string& event_args, | 136 const std::string& event_args, |
| 94 const GURL& event_url, | 137 const GURL& event_url, |
| 95 UserGestureState user_gesture) { | 138 UserGestureState user_gesture) { |
| 96 ListValue args; | 139 scoped_ptr<Value> event_args_value(Value::CreateStringValue(event_args)); |
| 97 args.Set(0, Value::CreateStringValue(event_name)); | 140 DispatchEvent(ipc_sender, extension_id, event_name, *event_args_value.get(), |
| 98 args.Set(1, Value::CreateStringValue(event_args)); | 141 event_url, user_gesture); |
| 99 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, | |
| 100 extension_id, kDispatchEvent, args, event_url, | |
| 101 user_gesture == USER_GESTURE_ENABLED)); | |
| 102 } | 142 } |
| 103 | 143 |
| 104 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) | 144 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) |
| 105 : profile_(profile), | 145 : profile_(profile), |
| 106 extension_devtools_manager_( | 146 extension_devtools_manager_( |
| 107 ExtensionSystem::Get(profile)->devtools_manager()) { | 147 ExtensionSystem::Get(profile)->devtools_manager()) { |
| 108 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 148 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 109 content::NotificationService::AllSources()); | 149 content::NotificationService::AllSources()); |
| 110 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 150 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 111 content::NotificationService::AllSources()); | 151 content::NotificationService::AllSources()); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 const GURL& event_url) { | 276 const GURL& event_url) { |
| 237 linked_ptr<ExtensionEvent> event( | 277 linked_ptr<ExtensionEvent> event( |
| 238 new ExtensionEvent(event_name, event_args, event_url, | 278 new ExtensionEvent(event_name, event_args, event_url, |
| 239 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); | 279 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); |
| 240 DispatchEventImpl("", event); | 280 DispatchEventImpl("", event); |
| 241 } | 281 } |
| 242 | 282 |
| 243 void ExtensionEventRouter::DispatchEventToExtension( | 283 void ExtensionEventRouter::DispatchEventToExtension( |
| 244 const std::string& extension_id, | 284 const std::string& extension_id, |
| 245 const std::string& event_name, | 285 const std::string& event_name, |
| 246 const std::string& event_args, | 286 const Value& event_args, |
| 247 Profile* restrict_to_profile, | 287 Profile* restrict_to_profile, |
| 248 const GURL& event_url) { | 288 const GURL& event_url) { |
| 249 DCHECK(!extension_id.empty()); | 289 DCHECK(!extension_id.empty()); |
| 250 linked_ptr<ExtensionEvent> event( | 290 linked_ptr<ExtensionEvent> event( |
| 251 new ExtensionEvent(event_name, event_args, event_url, | 291 new ExtensionEvent(event_name, event_args, event_url, |
| 252 restrict_to_profile, "", USER_GESTURE_UNKNOWN)); | 292 restrict_to_profile, USER_GESTURE_UNKNOWN)); |
| 253 DispatchEventImpl(extension_id, event); | 293 DispatchEventImpl(extension_id, event); |
| 254 } | 294 } |
| 255 | 295 |
| 256 void ExtensionEventRouter::DispatchEventToExtension( | 296 void ExtensionEventRouter::DispatchEventToExtension( |
| 257 const std::string& extension_id, | 297 const std::string& extension_id, |
| 258 const std::string& event_name, | 298 const std::string& event_name, |
| 259 const std::string& event_args, | 299 const std::string& event_args, |
| 260 Profile* restrict_to_profile, | 300 Profile* restrict_to_profile, |
| 301 const GURL& event_url) { | |
| 302 scoped_ptr<Value> event_args_value(Value::CreateStringValue(event_args)); | |
| 303 DispatchEventToExtension(extension_id, event_name, *event_args_value.get(), | |
| 304 restrict_to_profile, event_url); | |
| 305 } | |
| 306 | |
| 307 void ExtensionEventRouter::DispatchEventToExtension( | |
| 308 const std::string& extension_id, | |
| 309 const std::string& event_name, | |
| 310 const std::string& event_args, | |
| 311 Profile* restrict_to_profile, | |
| 261 const GURL& event_url, | 312 const GURL& event_url, |
| 262 UserGestureState user_gesture) { | 313 UserGestureState user_gesture) { |
| 263 DCHECK(!extension_id.empty()); | 314 DCHECK(!extension_id.empty()); |
| 264 linked_ptr<ExtensionEvent> event( | 315 linked_ptr<ExtensionEvent> event( |
| 265 new ExtensionEvent(event_name, event_args, event_url, | 316 new ExtensionEvent(event_name, event_args, event_url, |
| 266 restrict_to_profile, "", user_gesture)); | 317 restrict_to_profile, "", user_gesture)); |
| 267 DispatchEventImpl(extension_id, event); | 318 DispatchEventImpl(extension_id, event); |
| 268 } | 319 } |
| 269 | 320 |
| 270 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( | 321 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 319 listener.process->GetBrowserContext()); | 370 listener.process->GetBrowserContext()); |
| 320 extensions::ProcessMap* process_map = | 371 extensions::ProcessMap* process_map = |
| 321 listener_profile->GetExtensionService()->process_map(); | 372 listener_profile->GetExtensionService()->process_map(); |
| 322 // If the event is privileged, only send to extension processes. Otherwise, | 373 // If the event is privileged, only send to extension processes. Otherwise, |
| 323 // it's OK to send to normal renderers (e.g., for content scripts). | 374 // it's OK to send to normal renderers (e.g., for content scripts). |
| 324 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && | 375 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && |
| 325 !process_map->Contains(extension->id(), listener.process->GetID())) { | 376 !process_map->Contains(extension->id(), listener.process->GetID())) { |
| 326 return; | 377 return; |
| 327 } | 378 } |
| 328 | 379 |
| 329 const std::string* event_args; | 380 const Value* event_args = NULL; |
| 330 if (!CanDispatchEventToProfile(listener_profile, extension, | 381 if (!CanDispatchEventToProfile(listener_profile, extension, |
| 331 event, &event_args)) | 382 event, &event_args)) |
| 332 return; | 383 return; |
| 333 | 384 |
| 334 DispatchEvent(listener.process, listener.extension_id, | 385 DispatchEvent(listener.process, listener.extension_id, |
| 335 event->event_name, *event_args, | 386 event->event_name, *event_args, |
| 336 event->event_url, event->user_gesture); | 387 event->event_url, event->user_gesture); |
| 337 IncrementInFlightEvents(listener_profile, extension); | 388 IncrementInFlightEvents(listener_profile, extension); |
| 338 } | 389 } |
| 339 | 390 |
| 340 bool ExtensionEventRouter::CanDispatchEventToProfile( | 391 bool ExtensionEventRouter::CanDispatchEventToProfile( |
| 341 Profile* profile, | 392 Profile* profile, |
| 342 const Extension* extension, | 393 const Extension* extension, |
| 343 const linked_ptr<ExtensionEvent>& event, | 394 const linked_ptr<ExtensionEvent>& event, |
| 344 const std::string** event_args) { | 395 const Value** event_args) { |
| 345 *event_args = &event->event_args; | 396 *event_args = event->event_args.get(); |
| 346 | 397 |
| 347 // Is this event from a different profile than the renderer (ie, an | 398 // Is this event from a different profile than the renderer (ie, an |
| 348 // incognito tab event sent to a normal process, or vice versa). | 399 // incognito tab event sent to a normal process, or vice versa). |
| 349 bool cross_incognito = event->restrict_to_profile && | 400 bool cross_incognito = event->restrict_to_profile && |
| 350 profile != event->restrict_to_profile; | 401 profile != event->restrict_to_profile; |
| 351 if (cross_incognito && | 402 if (cross_incognito && |
| 352 !profile->GetExtensionService()->CanCrossIncognito(extension)) { | 403 !profile->GetExtensionService()->CanCrossIncognito(extension)) { |
| 353 if (event->cross_incognito_args.empty()) | 404 if (!event->cross_incognito_args.get()) |
| 354 return false; | 405 return false; |
| 355 // Send the event with different arguments to extensions that can't | 406 // Send the event with different arguments to extensions that can't |
| 356 // cross incognito. | 407 // cross incognito. |
| 357 *event_args = &event->cross_incognito_args; | 408 *event_args = event->cross_incognito_args.get(); |
| 358 } | 409 } |
| 359 | 410 |
| 360 return true; | 411 return true; |
| 361 } | 412 } |
| 362 | 413 |
| 363 void ExtensionEventRouter::LoadLazyBackgroundPagesForEvent( | 414 void ExtensionEventRouter::LoadLazyBackgroundPagesForEvent( |
| 364 const std::string& extension_id, | 415 const std::string& extension_id, |
| 365 const linked_ptr<ExtensionEvent>& event) { | 416 const linked_ptr<ExtensionEvent>& event) { |
| 366 ExtensionService* service = profile_->GetExtensionService(); | 417 ExtensionService* service = profile_->GetExtensionService(); |
| 367 | 418 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 388 profile_->GetOffTheRecordProfile(), extension, event); | 439 profile_->GetOffTheRecordProfile(), extension, event); |
| 389 } | 440 } |
| 390 } | 441 } |
| 391 } | 442 } |
| 392 } | 443 } |
| 393 | 444 |
| 394 void ExtensionEventRouter::MaybeLoadLazyBackgroundPage( | 445 void ExtensionEventRouter::MaybeLoadLazyBackgroundPage( |
| 395 Profile* profile, | 446 Profile* profile, |
| 396 const Extension* extension, | 447 const Extension* extension, |
| 397 const linked_ptr<ExtensionEvent>& event) { | 448 const linked_ptr<ExtensionEvent>& event) { |
| 398 const std::string* event_args; | 449 const Value* event_args = NULL; |
| 399 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) | 450 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) |
| 400 return; | 451 return; |
| 401 | 452 |
| 402 extensions::LazyBackgroundTaskQueue* queue = | 453 extensions::LazyBackgroundTaskQueue* queue = |
| 403 ExtensionSystem::Get(profile)->lazy_background_task_queue(); | 454 ExtensionSystem::Get(profile)->lazy_background_task_queue(); |
| 404 if (queue->ShouldEnqueueTask(profile, extension)) { | 455 if (queue->ShouldEnqueueTask(profile, extension)) { |
| 405 queue->AddPendingTask( | 456 queue->AddPendingTask( |
| 406 profile, extension->id(), | 457 profile, extension->id(), |
| 407 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, | 458 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, |
| 408 base::Unretained(this), event)); | 459 base::Unretained(this), event)); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 MessageLoop::current()->PostTask(FROM_HERE, | 556 MessageLoop::current()->PostTask(FROM_HERE, |
| 506 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, | 557 base::Bind(&extensions::RuntimeEventRouter::DispatchOnInstalledEvent, |
| 507 profile_, extension->id())); | 558 profile_, extension->id())); |
| 508 break; | 559 break; |
| 509 } | 560 } |
| 510 default: | 561 default: |
| 511 NOTREACHED(); | 562 NOTREACHED(); |
| 512 return; | 563 return; |
| 513 } | 564 } |
| 514 } | 565 } |
| OLD | NEW |