| 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/event_router.h" | 5 #include "chrome/browser/extensions/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 16 matching lines...) Expand all Loading... |
| 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 base::Value; |
| 33 using content::BrowserThread; | 33 using content::BrowserThread; |
| 34 | 34 |
| 35 namespace { | 35 namespace { |
| 36 | 36 |
| 37 const char kDispatchEvent[] = "Event.dispatchJSON"; | 37 const char kDispatchEvent[] = "Event.dispatchEvent"; |
| 38 | 38 |
| 39 void NotifyEventListenerRemovedOnIOThread( | 39 void NotifyEventListenerRemovedOnIOThread( |
| 40 void* profile, | 40 void* profile, |
| 41 const std::string& extension_id, | 41 const std::string& extension_id, |
| 42 const std::string& sub_event_name) { | 42 const std::string& sub_event_name) { |
| 43 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( | 43 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener( |
| 44 profile, extension_id, sub_event_name); | 44 profile, extension_id, sub_event_name); |
| 45 } | 45 } |
| 46 | 46 |
| 47 } // namespace | 47 } // namespace |
| (...skipping 11 matching lines...) Expand all Loading... |
| 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 // static | 68 // static |
| 69 void EventRouter::DispatchEvent(IPC::Sender* ipc_sender, | 69 void EventRouter::DispatchExtensionMessage(IPC::Sender* ipc_sender, |
| 70 const std::string& extension_id, | 70 const std::string& extension_id, |
| 71 const std::string& event_name, | 71 const std::string& event_name, |
| 72 const Value& event_args, | 72 ListValue* event_args, |
| 73 const GURL& event_url, | 73 const GURL& event_url, |
| 74 UserGestureState user_gesture, | 74 UserGestureState user_gesture, |
| 75 const EventFilteringInfo& info) { | 75 const EventFilteringInfo& info) { |
| 76 // TODO(gdk): Reduce number of DeepCopy() calls throughout the event dispatch | |
| 77 // chain, starting by replacing the event_args with a Value*. | |
| 78 ListValue args; | 76 ListValue args; |
| 79 args.Set(0, Value::CreateStringValue(event_name)); | 77 args.Set(0, Value::CreateStringValue(event_name)); |
| 80 args.Set(1, event_args.DeepCopy()); | 78 args.Set(1, event_args); |
| 81 args.Set(2, info.AsValue().release()); | 79 args.Set(2, info.AsValue().release()); |
| 82 | |
| 83 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, | 80 ipc_sender->Send(new ExtensionMsg_MessageInvoke(MSG_ROUTING_CONTROL, |
| 84 extension_id, kDispatchEvent, args, event_url, | 81 extension_id, kDispatchEvent, args, event_url, |
| 85 user_gesture == USER_GESTURE_ENABLED)); | 82 user_gesture == USER_GESTURE_ENABLED)); |
| 83 |
| 84 // DispatchExtensionMessage does _not_ take ownership of event_args, so we |
| 85 // must ensure that the destruction of args does not attempt to free it. |
| 86 Value* removed_event_args = NULL; |
| 87 args.Remove(1, &removed_event_args); |
| 86 } | 88 } |
| 87 | 89 |
| 88 // static | 90 // static |
| 89 void EventRouter::DispatchEvent(IPC::Sender* ipc_sender, | 91 void EventRouter::DispatchEvent(IPC::Sender* ipc_sender, |
| 90 const std::string& extension_id, | 92 const std::string& extension_id, |
| 91 const std::string& event_name, | 93 const std::string& event_name, |
| 92 const std::string& event_args, | 94 scoped_ptr<ListValue> event_args, |
| 93 const GURL& event_url, | 95 const GURL& event_url, |
| 94 UserGestureState user_gesture, | 96 UserGestureState user_gesture, |
| 95 const EventFilteringInfo& info) { | 97 const EventFilteringInfo& info) { |
| 96 scoped_ptr<Value> event_args_value(Value::CreateStringValue(event_args)); | 98 DispatchExtensionMessage(ipc_sender, extension_id, event_name, |
| 97 DispatchEvent(ipc_sender, extension_id, event_name, *event_args_value.get(), | 99 event_args.get(), event_url, user_gesture, info); |
| 98 event_url, user_gesture, info); | |
| 99 } | 100 } |
| 100 | 101 |
| 101 EventRouter::EventRouter(Profile* profile) | 102 EventRouter::EventRouter(Profile* profile) |
| 102 : profile_(profile), | 103 : profile_(profile), |
| 103 extension_devtools_manager_( | 104 extension_devtools_manager_( |
| 104 ExtensionSystem::Get(profile)->devtools_manager()), | 105 ExtensionSystem::Get(profile)->devtools_manager()), |
| 105 listeners_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 106 listeners_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 106 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 107 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 107 content::NotificationService::AllSources()); | 108 content::NotificationService::AllSources()); |
| 108 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 109 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 | 274 |
| 274 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); | 275 for (std::set<ListenerProcess>::const_iterator listener = listeners.begin(); |
| 275 listener != listeners.end(); ++listener) { | 276 listener != listeners.end(); ++listener) { |
| 276 if (listener->extension_id == extension_id) | 277 if (listener->extension_id == extension_id) |
| 277 return true; | 278 return true; |
| 278 } | 279 } |
| 279 return false; | 280 return false; |
| 280 } | 281 } |
| 281 | 282 |
| 282 void EventRouter::DispatchEventToRenderers(const std::string& event_name, | 283 void EventRouter::DispatchEventToRenderers(const std::string& event_name, |
| 283 const std::string& event_args, | 284 scoped_ptr<ListValue> event_args, |
| 284 Profile* restrict_to_profile, | 285 Profile* restrict_to_profile, |
| 285 const GURL& event_url, | 286 const GURL& event_url, |
| 286 EventFilteringInfo info) { | 287 EventFilteringInfo info) { |
| 287 DCHECK(!event_args.empty()); | 288 linked_ptr<Event> event(new Event(event_name, event_args.Pass(), |
| 288 StringValue event_args_value(event_args); | |
| 289 linked_ptr<Event> event(new Event(event_name, event_args_value, | |
| 290 event_url, restrict_to_profile, | 289 event_url, restrict_to_profile, |
| 291 USER_GESTURE_UNKNOWN, info)); | 290 USER_GESTURE_UNKNOWN, info)); |
| 292 DispatchEventImpl("", event); | 291 DispatchEventImpl("", event); |
| 293 } | 292 } |
| 294 | 293 |
| 295 void EventRouter::DispatchEventToRenderers(const std::string& event_name, | 294 void EventRouter::DispatchEventToRenderers(const std::string& event_name, |
| 296 const std::string& event_args, | 295 scoped_ptr<ListValue> event_args, |
| 297 Profile* restrict_to_profile, | 296 Profile* restrict_to_profile, |
| 298 const GURL& event_url) { | 297 const GURL& event_url) { |
| 299 DispatchEventToRenderers(event_name, event_args, restrict_to_profile, | 298 DispatchEventToRenderers(event_name, event_args.Pass(), restrict_to_profile, |
| 300 event_url, EventFilteringInfo()); | 299 event_url, EventFilteringInfo()); |
| 301 } | 300 } |
| 302 | 301 |
| 303 void EventRouter::DispatchEventToRenderers(const std::string& event_name, | 302 void EventRouter::DispatchEventToRenderers(const std::string& event_name, |
| 304 const std::string& event_args, | 303 scoped_ptr<ListValue> event_args, |
| 305 Profile* restrict_to_profile, | 304 Profile* restrict_to_profile, |
| 306 const GURL& event_url, | 305 const GURL& event_url, |
| 307 UserGestureState user_gesture) { | 306 UserGestureState user_gesture) { |
| 308 DCHECK(!event_args.empty()); | |
| 309 StringValue event_args_value(event_args); | |
| 310 EventFilteringInfo info; | 307 EventFilteringInfo info; |
| 311 linked_ptr<Event> event(new Event(event_name, event_args_value, | 308 linked_ptr<Event> event(new Event(event_name, event_args.Pass(), |
| 312 event_url, restrict_to_profile, | 309 event_url, restrict_to_profile, |
| 313 user_gesture, info)); | 310 user_gesture, info)); |
| 314 DispatchEventImpl("", event); | 311 DispatchEventImpl("", event); |
| 315 } | 312 } |
| 316 | 313 |
| 317 void EventRouter::DispatchEventToExtension(const std::string& extension_id, | 314 void EventRouter::DispatchEventToExtension(const std::string& extension_id, |
| 318 const std::string& event_name, | 315 const std::string& event_name, |
| 319 const Value& event_args, | 316 scoped_ptr<ListValue> event_args, |
| 320 Profile* restrict_to_profile, | 317 Profile* restrict_to_profile, |
| 321 const GURL& event_url) { | 318 const GURL& event_url) { |
| 322 DCHECK(!extension_id.empty()); | 319 DCHECK(!extension_id.empty()); |
| 323 linked_ptr<Event> event(new Event(event_name, event_args, event_url, | 320 linked_ptr<Event> event(new Event(event_name, event_args.Pass(), event_url, |
| 324 restrict_to_profile, USER_GESTURE_UNKNOWN, | 321 restrict_to_profile, USER_GESTURE_UNKNOWN, |
| 325 EventFilteringInfo())); | 322 EventFilteringInfo())); |
| 326 DispatchEventImpl(extension_id, event); | 323 DispatchEventImpl(extension_id, event); |
| 327 } | 324 } |
| 328 | 325 |
| 329 void EventRouter::DispatchEventToExtension(const std::string& extension_id, | 326 void EventRouter::DispatchEventToExtension(const std::string& extension_id, |
| 330 const std::string& event_name, | 327 const std::string& event_name, |
| 331 const std::string& event_args, | 328 scoped_ptr<ListValue> event_args, |
| 332 Profile* restrict_to_profile, | |
| 333 const GURL& event_url) { | |
| 334 StringValue event_args_value(event_args); | |
| 335 DispatchEventToExtension(extension_id, event_name, event_args_value, | |
| 336 restrict_to_profile, event_url); | |
| 337 } | |
| 338 | |
| 339 void EventRouter::DispatchEventToExtension(const std::string& extension_id, | |
| 340 const std::string& event_name, | |
| 341 const std::string& event_args, | |
| 342 Profile* restrict_to_profile, | 329 Profile* restrict_to_profile, |
| 343 const GURL& event_url, | 330 const GURL& event_url, |
| 344 UserGestureState user_gesture) { | 331 UserGestureState user_gesture) { |
| 345 DCHECK(!extension_id.empty()); | 332 DCHECK(!extension_id.empty()); |
| 346 StringValue event_args_value(event_args); | 333 linked_ptr<Event> event(new Event(event_name, event_args.Pass(), event_url, |
| 347 linked_ptr<Event> event(new Event(event_name, event_args_value, event_url, | |
| 348 restrict_to_profile, user_gesture, | 334 restrict_to_profile, user_gesture, |
| 349 EventFilteringInfo())); | 335 EventFilteringInfo())); |
| 350 DispatchEventImpl(extension_id, event); | 336 DispatchEventImpl(extension_id, event); |
| 351 } | 337 } |
| 352 | 338 |
| 353 void EventRouter::DispatchEventsToRenderersAcrossIncognito( | 339 void EventRouter::DispatchEventsToRenderersAcrossIncognito( |
| 354 const std::string& event_name, | 340 const std::string& event_name, |
| 355 const std::string& event_args, | 341 scoped_ptr<ListValue> event_args, |
| 356 Profile* restrict_to_profile, | 342 Profile* restrict_to_profile, |
| 357 const std::string& cross_incognito_args, | 343 scoped_ptr<ListValue> cross_incognito_args, |
| 358 const GURL& event_url) { | 344 const GURL& event_url) { |
| 359 linked_ptr<Event> event(new Event(event_name, event_args, | 345 linked_ptr<Event> event(new Event(event_name, event_args.Pass(), event_url, |
| 360 event_url, restrict_to_profile, | 346 restrict_to_profile, |
| 361 cross_incognito_args, USER_GESTURE_UNKNOWN, | 347 cross_incognito_args.Pass(), |
| 348 USER_GESTURE_UNKNOWN, |
| 362 EventFilteringInfo())); | 349 EventFilteringInfo())); |
| 363 DispatchEventImpl("", event); | 350 DispatchEventImpl("", event); |
| 364 } | 351 } |
| 365 | 352 |
| 366 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id, | 353 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id, |
| 367 const linked_ptr<Event>& event) { | 354 const linked_ptr<Event>& event) { |
| 368 // We don't expect to get events from a completely different profile. | 355 // We don't expect to get events from a completely different profile. |
| 369 DCHECK(!event->restrict_to_profile || | 356 DCHECK(!event->restrict_to_profile || |
| 370 profile_->IsSameProfile(event->restrict_to_profile)); | 357 profile_->IsSameProfile(event->restrict_to_profile)); |
| 371 | 358 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 process->GetBrowserContext()); | 420 process->GetBrowserContext()); |
| 434 ProcessMap* process_map = | 421 ProcessMap* process_map = |
| 435 listener_profile->GetExtensionService()->process_map(); | 422 listener_profile->GetExtensionService()->process_map(); |
| 436 // If the event is privileged, only send to extension processes. Otherwise, | 423 // If the event is privileged, only send to extension processes. Otherwise, |
| 437 // it's OK to send to normal renderers (e.g., for content scripts). | 424 // it's OK to send to normal renderers (e.g., for content scripts). |
| 438 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && | 425 if (ExtensionAPI::GetSharedInstance()->IsPrivileged(event->event_name) && |
| 439 !process_map->Contains(extension->id(), process->GetID())) { | 426 !process_map->Contains(extension->id(), process->GetID())) { |
| 440 return; | 427 return; |
| 441 } | 428 } |
| 442 | 429 |
| 443 const Value* event_args = NULL; | 430 ListValue* event_args = NULL; |
| 444 if (!CanDispatchEventToProfile(listener_profile, extension, | 431 if (!CanDispatchEventToProfile(listener_profile, extension, |
| 445 event, &event_args)) { | 432 event, &event_args)) { |
| 446 return; | 433 return; |
| 447 } | 434 } |
| 448 | 435 |
| 449 DispatchEvent(process, extension_id, | 436 DispatchExtensionMessage(process, extension_id, |
| 450 event->event_name, *event_args, | 437 event->event_name, event_args, |
| 451 event->event_url, event->user_gesture, | 438 event->event_url, event->user_gesture, |
| 452 event->info); | 439 event->info); |
| 453 IncrementInFlightEvents(listener_profile, extension); | 440 IncrementInFlightEvents(listener_profile, extension); |
| 454 } | 441 } |
| 455 | 442 |
| 456 bool EventRouter::CanDispatchEventToProfile(Profile* profile, | 443 bool EventRouter::CanDispatchEventToProfile(Profile* profile, |
| 457 const Extension* extension, | 444 const Extension* extension, |
| 458 const linked_ptr<Event>& event, | 445 const linked_ptr<Event>& event, |
| 459 const Value** event_args) { | 446 ListValue** event_args) { |
| 460 *event_args = event->event_args.get(); | 447 if (event_args) |
| 448 *event_args = event->event_args.get(); |
| 461 | 449 |
| 462 // Is this event from a different profile than the renderer (ie, an | 450 // Is this event from a different profile than the renderer (ie, an |
| 463 // incognito tab event sent to a normal process, or vice versa). | 451 // incognito tab event sent to a normal process, or vice versa). |
| 464 bool cross_incognito = | 452 bool cross_incognito = |
| 465 event->restrict_to_profile && profile != event->restrict_to_profile; | 453 event->restrict_to_profile && profile != event->restrict_to_profile; |
| 466 if (cross_incognito && | 454 if (cross_incognito && |
| 467 !profile->GetExtensionService()->CanCrossIncognito(extension)) { | 455 !profile->GetExtensionService()->CanCrossIncognito(extension)) { |
| 468 if (!event->cross_incognito_args.get()) | 456 if (!event->cross_incognito_args.get()) |
| 469 return false; | 457 return false; |
| 470 // Send the event with different arguments to extensions that can't | 458 // Send the event with different arguments to extensions that can't |
| 471 // cross incognito. | 459 // cross incognito. |
| 472 *event_args = event->cross_incognito_args.get(); | 460 if (event_args) |
| 461 *event_args = event->cross_incognito_args.get(); |
| 473 } | 462 } |
| 474 | 463 |
| 475 return true; | 464 return true; |
| 476 } | 465 } |
| 477 | 466 |
| 478 void EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent( | 467 void EventRouter::MaybeLoadLazyBackgroundPageToDispatchEvent( |
| 479 Profile* profile, | 468 Profile* profile, |
| 480 const Extension* extension, | 469 const Extension* extension, |
| 481 const linked_ptr<Event>& event) { | 470 const linked_ptr<Event>& event) { |
| 482 const Value* event_args = NULL; | 471 if (!CanDispatchEventToProfile(profile, extension, event, NULL)) |
| 483 if (!CanDispatchEventToProfile(profile, extension, event, &event_args)) | |
| 484 return; | 472 return; |
| 485 | 473 |
| 486 LazyBackgroundTaskQueue* queue = | 474 LazyBackgroundTaskQueue* queue = |
| 487 ExtensionSystem::Get(profile)->lazy_background_task_queue(); | 475 ExtensionSystem::Get(profile)->lazy_background_task_queue(); |
| 488 if (queue->ShouldEnqueueTask(profile, extension)) { | 476 if (queue->ShouldEnqueueTask(profile, extension)) { |
| 489 queue->AddPendingTask(profile, extension->id(), | 477 queue->AddPendingTask(profile, extension->id(), |
| 490 base::Bind(&EventRouter::DispatchPendingEvent, | 478 base::Bind(&EventRouter::DispatchPendingEvent, |
| 491 base::Unretained(this), event)); | 479 base::Unretained(this), event)); |
| 492 } | 480 } |
| 493 } | 481 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 profile_, extension->id())); | 562 profile_, extension->id())); |
| 575 break; | 563 break; |
| 576 } | 564 } |
| 577 default: | 565 default: |
| 578 NOTREACHED(); | 566 NOTREACHED(); |
| 579 return; | 567 return; |
| 580 } | 568 } |
| 581 } | 569 } |
| 582 | 570 |
| 583 Event::Event(const std::string& event_name, | 571 Event::Event(const std::string& event_name, |
| 584 const Value& event_args, | 572 scoped_ptr<ListValue> event_args, |
| 585 const GURL& event_url, | 573 const GURL& event_url, |
| 586 Profile* restrict_to_profile, | 574 Profile* restrict_to_profile, |
| 587 const Value& cross_incognito_args, | 575 scoped_ptr<ListValue> cross_incognito_args, |
| 588 EventRouter::UserGestureState user_gesture, | 576 EventRouter::UserGestureState user_gesture, |
| 589 const EventFilteringInfo& info) | 577 const EventFilteringInfo& info) |
| 590 : event_name(event_name), | 578 : event_name(event_name), |
| 591 event_args(event_args.DeepCopy()), | 579 event_args(event_args.Pass()), |
| 592 event_url(event_url), | 580 event_url(event_url), |
| 593 restrict_to_profile(restrict_to_profile), | 581 restrict_to_profile(restrict_to_profile), |
| 594 cross_incognito_args(cross_incognito_args.DeepCopy()), | 582 cross_incognito_args(cross_incognito_args.Pass()), |
| 595 user_gesture(user_gesture), | 583 user_gesture(user_gesture), |
| 596 info(info) { | 584 info(info) {} |
| 597 } | |
| 598 | 585 |
| 599 Event::Event(const std::string& event_name, | 586 Event::Event(const std::string& event_name, |
| 600 const std::string& event_args, | 587 scoped_ptr<ListValue> event_args, |
| 601 const GURL& event_url, | |
| 602 Profile* restrict_to_profile, | |
| 603 const std::string& cross_incognito_args, | |
| 604 EventRouter::UserGestureState user_gesture, | |
| 605 const EventFilteringInfo& info) | |
| 606 : event_name(event_name), | |
| 607 event_args(Value::CreateStringValue(event_args)), | |
| 608 event_url(event_url), | |
| 609 restrict_to_profile(restrict_to_profile), | |
| 610 cross_incognito_args(Value::CreateStringValue(cross_incognito_args)), | |
| 611 user_gesture(user_gesture), | |
| 612 info(info) { | |
| 613 } | |
| 614 | |
| 615 Event::Event(const std::string& event_name, | |
| 616 const Value& event_args, | |
| 617 const GURL& event_url, | 588 const GURL& event_url, |
| 618 Profile* restrict_to_profile, | 589 Profile* restrict_to_profile, |
| 619 EventRouter::UserGestureState user_gesture, | 590 EventRouter::UserGestureState user_gesture, |
| 620 const EventFilteringInfo& info) | 591 const EventFilteringInfo& info) |
| 621 : event_name(event_name), | 592 : event_name(event_name), |
| 622 event_args(event_args.DeepCopy()), | 593 event_args(event_args.Pass()), |
| 623 event_url(event_url), | 594 event_url(event_url), |
| 624 restrict_to_profile(restrict_to_profile), | 595 restrict_to_profile(restrict_to_profile), |
| 625 cross_incognito_args(NULL), | 596 cross_incognito_args(NULL), |
| 626 user_gesture(user_gesture), | 597 user_gesture(user_gesture), |
| 627 info(info) { | 598 info(info) {} |
| 628 } | |
| 629 | 599 |
| 630 Event::~Event() { | 600 Event::~Event() {} |
| 631 } | |
| 632 | 601 |
| 633 } // namespace extensions | 602 } // namespace extensions |
| OLD | NEW |