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 18 matching lines...) Expand all Loading... | |
| 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 base::Value; |
| 33 using content::BrowserThread; | 33 using content::BrowserThread; |
| 34 using extensions::Extension; | 34 using extensions::Extension; |
| 35 using extensions::ExtensionAPI; | 35 using extensions::ExtensionAPI; |
| 36 | 36 |
| 37 namespace { | 37 namespace { |
| 38 | 38 |
| 39 const char kDispatchEvent[] = "Event.dispatchJSON"; | 39 const char kDispatchEvent[] = "Event.dispatch"; |
| 40 | 40 |
| 41 void NotifyEventListenerRemovedOnIOThread( | 41 void NotifyEventListenerRemovedOnIOThread( |
| 42 void* profile, | 42 void* profile, |
| 43 const std::string& extension_id, | 43 const std::string& extension_id, |
| 44 const std::string& sub_event_name) { | 44 const std::string& sub_event_name) { |
| 45 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | 45 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| 46 profile, extension_id, sub_event_name); | 46 profile, extension_id, sub_event_name); |
| 47 } | 47 } |
| 48 | 48 |
| 49 } // namespace | 49 } // namespace |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 63 return true; | 63 return true; |
| 64 return false; | 64 return false; |
| 65 } | 65 } |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 // static | 68 // static |
| 69 void ExtensionEventRouter::DispatchEvent( | 69 void ExtensionEventRouter::DispatchEvent( |
| 70 IPC::Sender* ipc_sender, | 70 IPC::Sender* ipc_sender, |
| 71 const std::string& extension_id, | 71 const std::string& extension_id, |
| 72 const std::string& event_name, | 72 const std::string& event_name, |
| 73 const Value& event_args, | 73 ListValue* event_args, |
| 74 const GURL& event_url, | 74 const GURL& event_url, |
| 75 UserGestureState user_gesture, | 75 UserGestureState user_gesture, |
| 76 const extensions::EventFilteringInfo& info) { | 76 const extensions::EventFilteringInfo& info) { |
| 77 // TODO(gdk): Reduce number of DeepCopy() calls throughout the event dispatch | |
| 78 // chain, starting by replacing the event_args with a Value*. | |
| 79 ListValue args; | 77 ListValue args; |
| 80 args.Set(0, Value::CreateStringValue(event_name)); | 78 args.Set(0, Value::CreateStringValue(event_name)); |
| 81 args.Set(1, event_args.DeepCopy()); | 79 args.Set(1, event_args); |
| 82 args.Set(2, info.AsValue().release()); | 80 args.Set(2, info.AsValue().release()); |
| 83 | |
| 84 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, | 81 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, |
| 85 extension_id, kDispatchEvent, args, event_url, | 82 extension_id, kDispatchEvent, args, event_url, |
| 86 user_gesture == USER_GESTURE_ENABLED)); | 83 user_gesture == USER_GESTURE_ENABLED)); |
| 87 } | |
| 88 | 84 |
| 89 // static | 85 // The event_args for this dispatch are possibly going to be re-used by |
| 90 void ExtensionEventRouter::DispatchEvent( | 86 // dispatches to other listeners (to avoid copying them), therefore we need to |
| 91 IPC::Sender* ipc_sender, | 87 // ensure that args' destruction doesn't result in event_args' deletion. |
|
asargent_no_longer_on_chrome
2012/07/09 18:51:50
In the header documentation you specify that this
| |
| 92 const std::string& extension_id, | 88 Value* removed_event_args = NULL; |
| 93 const std::string& event_name, | 89 args.Remove(1, &removed_event_args); |
| 94 const std::string& event_args, | |
| 95 const GURL& event_url, | |
| 96 UserGestureState user_gesture, | |
| 97 const extensions::EventFilteringInfo& info) { | |
| 98 scoped_ptr<Value> event_args_value(Value::CreateStringValue(event_args)); | |
| 99 DispatchEvent(ipc_sender, extension_id, event_name, *event_args_value.get(), | |
| 100 event_url, user_gesture, info); | |
| 101 } | 90 } |
| 102 | 91 |
| 103 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) | 92 ExtensionEventRouter::ExtensionEventRouter(Profile* profile) |
| 104 : profile_(profile), | 93 : profile_(profile), |
| 105 extension_devtools_manager_( | 94 extension_devtools_manager_( |
| 106 ExtensionSystem::Get(profile)->devtools_manager()), | 95 ExtensionSystem::Get(profile)->devtools_manager()), |
| 107 listeners_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 96 listeners_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 108 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 97 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 109 content::NotificationService::AllSources()); | 98 content::NotificationService::AllSources()); |
| 110 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 99 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); | 270 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); |
| 282 listener != listeners.end(); ++listener) { | 271 listener != listeners.end(); ++listener) { |
| 283 if (listener->extension_id == extension_id) | 272 if (listener->extension_id == extension_id) |
| 284 return true; | 273 return true; |
| 285 } | 274 } |
| 286 return false; | 275 return false; |
| 287 } | 276 } |
| 288 | 277 |
| 289 void ExtensionEventRouter::DispatchEventToRenderers( | 278 void ExtensionEventRouter::DispatchEventToRenderers( |
| 290 const std::string& event_name, | 279 const std::string& event_name, |
| 291 const std::string& event_args, | 280 ListValue* event_args, |
| 292 Profile* restrict_to_profile, | 281 Profile* restrict_to_profile, |
| 293 const GURL& event_url, | 282 const GURL& event_url, |
| 294 extensions::EventFilteringInfo info) { | 283 extensions::EventFilteringInfo info) { |
| 295 DCHECK(!event_args.empty()); | |
| 296 StringValue event_args_value(event_args); | |
| 297 linked_ptr<ExtensionEvent> event( | 284 linked_ptr<ExtensionEvent> event( |
| 298 new ExtensionEvent(event_name, event_args_value, event_url, | 285 new ExtensionEvent(event_name, event_args, event_url, restrict_to_profile, |
| 299 restrict_to_profile, USER_GESTURE_UNKNOWN, info)); | 286 NULL, USER_GESTURE_UNKNOWN, |
| 287 info)); | |
| 300 DispatchEventImpl("", event); | 288 DispatchEventImpl("", event); |
| 301 } | 289 } |
| 302 | 290 |
| 303 void ExtensionEventRouter::DispatchEventToRenderers( | 291 void ExtensionEventRouter::DispatchEventToRenderers( |
| 304 const std::string& event_name, | 292 const std::string& event_name, |
| 305 const std::string& event_args, | 293 ListValue* event_args, |
| 306 Profile* restrict_to_profile, | 294 Profile* restrict_to_profile, |
| 307 const GURL& event_url) { | 295 const GURL& event_url) { |
| 308 DispatchEventToRenderers(event_name, event_args, restrict_to_profile, | 296 DispatchEventToRenderers(event_name, event_args, restrict_to_profile, |
| 309 event_url, extensions::EventFilteringInfo()); | 297 event_url, extensions::EventFilteringInfo()); |
| 310 } | 298 } |
| 311 | 299 |
| 312 void ExtensionEventRouter::DispatchEventToExtension( | 300 void ExtensionEventRouter::DispatchEventToExtension( |
| 313 const std::string& extension_id, | 301 const std::string& extension_id, |
| 314 const std::string& event_name, | 302 const std::string& event_name, |
| 315 const Value& event_args, | 303 ListValue* event_args, |
| 316 Profile* restrict_to_profile, | 304 Profile* restrict_to_profile, |
| 317 const GURL& event_url) { | 305 const GURL& event_url) { |
| 318 DCHECK(!extension_id.empty()); | 306 DCHECK(!extension_id.empty()); |
| 319 linked_ptr<ExtensionEvent> event( | 307 linked_ptr<ExtensionEvent> event( |
| 320 new ExtensionEvent(event_name, event_args, event_url, | 308 new ExtensionEvent(event_name, event_args, event_url, restrict_to_profile, |
| 321 restrict_to_profile, USER_GESTURE_UNKNOWN, | 309 NULL, USER_GESTURE_UNKNOWN, EventFilteringInfo())); |
| 322 EventFilteringInfo())); | |
| 323 DispatchEventImpl(extension_id, event); | 310 DispatchEventImpl(extension_id, event); |
| 324 } | 311 } |
| 325 | 312 |
| 326 void ExtensionEventRouter::DispatchEventToExtension( | 313 void ExtensionEventRouter::DispatchEventToExtension( |
| 327 const std::string& extension_id, | 314 const std::string& extension_id, |
| 328 const std::string& event_name, | 315 const std::string& event_name, |
| 329 const std::string& event_args, | 316 ListValue* event_args, |
| 330 Profile* restrict_to_profile, | |
| 331 const GURL& event_url) { | |
| 332 StringValue event_args_value(event_args); | |
| 333 DispatchEventToExtension(extension_id, event_name, event_args_value, | |
| 334 restrict_to_profile, event_url); | |
| 335 } | |
| 336 | |
| 337 void ExtensionEventRouter::DispatchEventToExtension( | |
| 338 const std::string& extension_id, | |
| 339 const std::string& event_name, | |
| 340 const std::string& event_args, | |
| 341 Profile* restrict_to_profile, | 317 Profile* restrict_to_profile, |
| 342 const GURL& event_url, | 318 const GURL& event_url, |
| 343 UserGestureState user_gesture) { | 319 UserGestureState user_gesture) { |
| 344 DCHECK(!extension_id.empty()); | 320 DCHECK(!extension_id.empty()); |
| 345 StringValue event_args_value(event_args); | |
| 346 linked_ptr<ExtensionEvent> event( | 321 linked_ptr<ExtensionEvent> event( |
| 347 new ExtensionEvent(event_name, event_args_value, event_url, | 322 new ExtensionEvent(event_name, event_args, event_url, restrict_to_profile, |
| 348 restrict_to_profile, user_gesture, | 323 NULL, user_gesture, EventFilteringInfo())); |
| 349 EventFilteringInfo())); | |
| 350 DispatchEventImpl(extension_id, event); | 324 DispatchEventImpl(extension_id, event); |
| 351 } | 325 } |
| 352 | 326 |
| 353 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( | 327 void ExtensionEventRouter::DispatchEventsToRenderersAcrossIncognito( |
| 354 const std::string& event_name, | 328 const std::string& event_name, |
| 355 const std::string& event_args, | 329 ListValue* event_args, |
| 356 Profile* restrict_to_profile, | 330 Profile* restrict_to_profile, |
| 357 const std::string& cross_incognito_args, | 331 ListValue* cross_incognito_args, |
| 358 const GURL& event_url) { | 332 const GURL& event_url) { |
| 359 linked_ptr<ExtensionEvent> event( | 333 linked_ptr<ExtensionEvent> event( |
| 360 new ExtensionEvent(event_name, event_args, event_url, | 334 new ExtensionEvent(event_name, event_args, event_url, |
| 361 restrict_to_profile, cross_incognito_args, | 335 restrict_to_profile, cross_incognito_args, |
| 362 USER_GESTURE_UNKNOWN, EventFilteringInfo())); | 336 USER_GESTURE_UNKNOWN, EventFilteringInfo())); |
| 363 DispatchEventImpl("", event); | 337 DispatchEventImpl("", event); |
| 364 } | 338 } |
| 365 | 339 |
| 366 void ExtensionEventRouter::DispatchEventImpl( | 340 void ExtensionEventRouter::DispatchEventImpl( |
| 367 const std::string& restrict_to_extension_id, | 341 const std::string& restrict_to_extension_id, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 process->GetBrowserContext()); | 394 process->GetBrowserContext()); |
| 421 extensions::ProcessMap* process_map = | 395 extensions::ProcessMap* process_map = |
| 422 listener_profile->GetExtensionService()->process_map(); | 396 listener_profile->GetExtensionService()->process_map(); |
| 423 // If the event is privileged, only send to extension processes. Otherwise, | 397 // If the event is privileged, only send to extension processes. Otherwise, |
| 424 // it's OK to send to normal renderers (e.g., for content scripts). | 398 // it's OK to send to normal renderers (e.g., for content scripts). |
| 425 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && | 399 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && |
| 426 !process_map->Contains(extension->id(), process->GetID())) { | 400 !process_map->Contains(extension->id(), process->GetID())) { |
| 427 return; | 401 return; |
| 428 } | 402 } |
| 429 | 403 |
| 430 const Value* event_args = NULL; | 404 ListValue* event_args = NULL; |
| 431 if (!CanDispatchEventToProfile(listener_profile, extension, | 405 if (!CanDispatchEventToProfile(listener_profile, extension, |
| 432 event, &event_args)) { | 406 event, &event_args)) { |
| 433 return; | 407 return; |
| 434 } | 408 } |
| 435 | 409 |
| 436 DispatchEvent(process, extension_id, | 410 DispatchEvent(process, extension_id, |
| 437 event->event_name, *event_args, | 411 event->event_name, event_args, |
| 438 event->event_url, event->user_gesture, | 412 event->event_url, event->user_gesture, |
| 439 event->info); | 413 event->info); |
| 440 IncrementInFlightEvents(listener_profile, extension); | 414 IncrementInFlightEvents(listener_profile, extension); |
| 441 } | 415 } |
| 442 | 416 |
| 443 bool ExtensionEventRouter::CanDispatchEventToProfile( | 417 bool ExtensionEventRouter::CanDispatchEventToProfile( |
| 444 Profile* profile, | 418 Profile* profile, |
| 445 const Extension* extension, | 419 const Extension* extension, |
| 446 const linked_ptr<ExtensionEvent>& event, | 420 const linked_ptr<ExtensionEvent>& event, |
| 447 const Value** event_args) { | 421 ListValue** event_args) { |
| 448 *event_args = event->event_args.get(); | 422 if (event_args) |
| 423 *event_args = event->event_args.get(); | |
| 449 | 424 |
| 450 // Is this event from a different profile than the renderer (ie, an | 425 // Is this event from a different profile than the renderer (ie, an |
| 451 // incognito tab event sent to a normal process, or vice versa). | 426 // incognito tab event sent to a normal process, or vice versa). |
| 452 bool cross_incognito = event->restrict_to_profile && | 427 bool cross_incognito = event->restrict_to_profile && |
| 453 profile != event->restrict_to_profile; | 428 profile != event->restrict_to_profile; |
| 454 if (cross_incognito && | 429 if (cross_incognito && |
| 455 !profile->GetExtensionService()->CanCrossIncognito(extension)) { | 430 !profile->GetExtensionService()->CanCrossIncognito(extension)) { |
| 456 if (!event->cross_incognito_args.get()) | 431 if (!event->cross_incognito_args.get()) |
| 457 return false; | 432 return false; |
| 458 // Send the event with different arguments to extensions that can't | 433 // Send the event with different arguments to extensions that can't |
| 459 // cross incognito. | 434 // cross incognito. |
| 460 *event_args = event->cross_incognito_args.get(); | 435 if (event_args) { |
| 436 *event_args = event->cross_incognito_args.get(); | |
| 437 } | |
| 461 } | 438 } |
| 462 | 439 |
| 463 return true; | 440 return true; |
| 464 } | 441 } |
| 465 | 442 |
| 466 void ExtensionEventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent( | 443 void ExtensionEventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent( |
| 467 Profile* profile, | 444 Profile* profile, |
| 468 const Extension* extension, | 445 const Extension* extension, |
| 469 const linked_ptr<ExtensionEvent>& event) { | 446 const linked_ptr<ExtensionEvent>& event) { |
| 470 const Value* event_args = NULL; | 447 if (!CanDispatchEventToProfile(profile, extension, event, NULL)) |
| 471 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) | |
| 472 return; | 448 return; |
| 473 | 449 |
| 474 extensions::LazyBackgroundTaskQueue* queue = | 450 extensions::LazyBackgroundTaskQueue* queue = |
| 475 ExtensionSystem::Get(profile)->lazy_background_task_queue(); | 451 ExtensionSystem::Get(profile)->lazy_background_task_queue(); |
| 476 if (queue->ShouldEnqueueTask(profile, extension)) { | 452 if (queue->ShouldEnqueueTask(profile, extension)) { |
| 477 queue->AddPendingTask( | 453 queue->AddPendingTask( |
| 478 profile, extension->id(), | 454 profile, extension->id(), |
| 479 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, | 455 base::Bind(&ExtensionEventRouter::DispatchPendingEvent, |
| 480 base::Unretained(this), event)); | 456 base::Unretained(this), event)); |
| 481 } | 457 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 break; | 542 break; |
| 567 } | 543 } |
| 568 default: | 544 default: |
| 569 NOTREACHED(); | 545 NOTREACHED(); |
| 570 return; | 546 return; |
| 571 } | 547 } |
| 572 } | 548 } |
| 573 | 549 |
| 574 ExtensionEvent::ExtensionEvent( | 550 ExtensionEvent::ExtensionEvent( |
| 575 const std::string& event_name, | 551 const std::string& event_name, |
| 576 const Value& event_args, | 552 ListValue* event_args, |
| 577 const GURL& event_url, | 553 const GURL& event_url, |
| 578 Profile* restrict_to_profile, | 554 Profile* restrict_to_profile, |
| 579 const Value& cross_incognito_args, | 555 ListValue* cross_incognito_args, |
| 580 ExtensionEventRouter::UserGestureState user_gesture, | 556 ExtensionEventRouter::UserGestureState user_gesture, |
| 581 const extensions::EventFilteringInfo& info) | 557 const extensions::EventFilteringInfo& info) |
| 582 : event_name(event_name), | 558 : event_name(event_name), |
| 583 event_args(event_args.DeepCopy()), | 559 event_args(event_args), |
| 584 event_url(event_url), | 560 event_url(event_url), |
| 585 restrict_to_profile(restrict_to_profile), | 561 restrict_to_profile(restrict_to_profile), |
| 586 cross_incognito_args(cross_incognito_args.DeepCopy()), | 562 cross_incognito_args(cross_incognito_args), |
| 587 user_gesture(user_gesture), | 563 user_gesture(user_gesture), |
| 588 info(info) { | 564 info(info) { |
| 565 if (!event_args) | |
| 566 this->event_args.reset(new ListValue()); | |
| 589 } | 567 } |
| 590 | 568 |
| 591 ExtensionEvent::ExtensionEvent( | 569 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 } | |
| OLD | NEW |