| 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 "extensions/browser/event_router.h" | 5 #include "extensions/browser/event_router.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 content::Source<BrowserContext>(browser_context_)); | 181 content::Source<BrowserContext>(browser_context_)); |
| 182 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, | 182 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, |
| 183 content::Source<BrowserContext>(browser_context_)); | 183 content::Source<BrowserContext>(browser_context_)); |
| 184 } | 184 } |
| 185 | 185 |
| 186 EventRouter::~EventRouter() {} | 186 EventRouter::~EventRouter() {} |
| 187 | 187 |
| 188 void EventRouter::AddEventListener(const std::string& event_name, | 188 void EventRouter::AddEventListener(const std::string& event_name, |
| 189 content::RenderProcessHost* process, | 189 content::RenderProcessHost* process, |
| 190 const std::string& extension_id) { | 190 const std::string& extension_id) { |
| 191 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( | 191 listeners_.AddListener(scoped_ptr<EventListener>( |
| 192 event_name, extension_id, process, scoped_ptr<DictionaryValue>()))); | 192 new EventListener(event_name, |
| 193 extension_id, |
| 194 GURL(), // listener_url |
| 195 process, |
| 196 scoped_ptr<DictionaryValue>()))); |
| 193 } | 197 } |
| 194 | 198 |
| 195 void EventRouter::RemoveEventListener(const std::string& event_name, | 199 void EventRouter::RemoveEventListener(const std::string& event_name, |
| 196 content::RenderProcessHost* process, | 200 content::RenderProcessHost* process, |
| 197 const std::string& extension_id) { | 201 const std::string& extension_id) { |
| 198 EventListener listener(event_name, extension_id, process, | 202 EventListener listener(event_name, |
| 203 extension_id, |
| 204 GURL(), // listener_url |
| 205 process, |
| 199 scoped_ptr<DictionaryValue>()); | 206 scoped_ptr<DictionaryValue>()); |
| 200 listeners_.RemoveListener(&listener); | 207 listeners_.RemoveListener(&listener); |
| 201 } | 208 } |
| 209 |
| 210 void EventRouter::AddEventListenerForURL(const std::string& event_name, |
| 211 content::RenderProcessHost* process, |
| 212 const GURL& listener_url) { |
| 213 listeners_.AddListener(scoped_ptr<EventListener>( |
| 214 new EventListener(event_name, |
| 215 "", // extension_id |
| 216 listener_url, |
| 217 process, |
| 218 scoped_ptr<DictionaryValue>()))); |
| 219 } |
| 220 |
| 221 void EventRouter::RemoveEventListenerForURL(const std::string& event_name, |
| 222 content::RenderProcessHost* process, |
| 223 const GURL& listener_url) { |
| 224 EventListener listener(event_name, |
| 225 "", // extension_id |
| 226 listener_url, |
| 227 process, |
| 228 scoped_ptr<DictionaryValue>()); |
| 229 listeners_.RemoveListener(&listener); |
| 230 } |
| 202 | 231 |
| 203 void EventRouter::RegisterObserver(Observer* observer, | 232 void EventRouter::RegisterObserver(Observer* observer, |
| 204 const std::string& event_name) { | 233 const std::string& event_name) { |
| 205 // Observing sub-event names like "foo.onBar/123" is not allowed. | 234 // Observing sub-event names like "foo.onBar/123" is not allowed. |
| 206 DCHECK(event_name.find('/') == std::string::npos); | 235 DCHECK(event_name.find('/') == std::string::npos); |
| 207 observers_[event_name] = observer; | 236 observers_[event_name] = observer; |
| 208 } | 237 } |
| 209 | 238 |
| 210 void EventRouter::UnregisterObserver(Observer* observer) { | 239 void EventRouter::UnregisterObserver(Observer* observer) { |
| 211 std::vector<ObserverMap::iterator> iters_to_remove; | 240 std::vector<ObserverMap::iterator> iters_to_remove; |
| 212 for (ObserverMap::iterator iter = observers_.begin(); | 241 for (ObserverMap::iterator iter = observers_.begin(); |
| 213 iter != observers_.end(); ++iter) { | 242 iter != observers_.end(); ++iter) { |
| 214 if (iter->second == observer) | 243 if (iter->second == observer) |
| 215 iters_to_remove.push_back(iter); | 244 iters_to_remove.push_back(iter); |
| 216 } | 245 } |
| 217 for (size_t i = 0; i < iters_to_remove.size(); ++i) | 246 for (size_t i = 0; i < iters_to_remove.size(); ++i) |
| 218 observers_.erase(iters_to_remove[i]); | 247 observers_.erase(iters_to_remove[i]); |
| 219 } | 248 } |
| 220 | 249 |
| 221 void EventRouter::OnListenerAdded(const EventListener* listener) { | 250 void EventRouter::OnListenerAdded(const EventListener* listener) { |
| 222 const EventListenerInfo details(listener->event_name(), | 251 const EventListenerInfo details(listener->event_name(), |
| 223 listener->extension_id(), | 252 listener->extension_id(), |
| 253 listener->listener_url(), |
| 224 listener->GetBrowserContext()); | 254 listener->GetBrowserContext()); |
| 225 std::string base_event_name = GetBaseEventName(listener->event_name()); | 255 std::string base_event_name = GetBaseEventName(listener->event_name()); |
| 226 ObserverMap::iterator observer = observers_.find(base_event_name); | 256 ObserverMap::iterator observer = observers_.find(base_event_name); |
| 227 if (observer != observers_.end()) | 257 if (observer != observers_.end()) |
| 228 observer->second->OnListenerAdded(details); | 258 observer->second->OnListenerAdded(details); |
| 229 } | 259 } |
| 230 | 260 |
| 231 void EventRouter::OnListenerRemoved(const EventListener* listener) { | 261 void EventRouter::OnListenerRemoved(const EventListener* listener) { |
| 232 const EventListenerInfo details(listener->event_name(), | 262 const EventListenerInfo details(listener->event_name(), |
| 233 listener->extension_id(), | 263 listener->extension_id(), |
| 264 listener->listener_url(), |
| 234 listener->GetBrowserContext()); | 265 listener->GetBrowserContext()); |
| 235 std::string base_event_name = GetBaseEventName(listener->event_name()); | 266 std::string base_event_name = GetBaseEventName(listener->event_name()); |
| 236 ObserverMap::iterator observer = observers_.find(base_event_name); | 267 ObserverMap::iterator observer = observers_.find(base_event_name); |
| 237 if (observer != observers_.end()) | 268 if (observer != observers_.end()) |
| 238 observer->second->OnListenerRemoved(details); | 269 observer->second->OnListenerRemoved(details); |
| 239 } | 270 } |
| 240 | 271 |
| 241 void EventRouter::AddLazyEventListener(const std::string& event_name, | 272 void EventRouter::AddLazyEventListener(const std::string& event_name, |
| 242 const std::string& extension_id) { | 273 const std::string& extension_id) { |
| 243 scoped_ptr<EventListener> listener(new EventListener( | 274 scoped_ptr<EventListener> listener(new EventListener( |
| 244 event_name, extension_id, NULL, scoped_ptr<DictionaryValue>())); | 275 event_name, extension_id, GURL(), NULL, scoped_ptr<DictionaryValue>())); |
| 245 bool is_new = listeners_.AddListener(listener.Pass()); | 276 bool is_new = listeners_.AddListener(listener.Pass()); |
| 246 | 277 |
| 247 if (is_new) { | 278 if (is_new) { |
| 248 std::set<std::string> events = GetRegisteredEvents(extension_id); | 279 std::set<std::string> events = GetRegisteredEvents(extension_id); |
| 249 bool prefs_is_new = events.insert(event_name).second; | 280 bool prefs_is_new = events.insert(event_name).second; |
| 250 if (prefs_is_new) | 281 if (prefs_is_new) |
| 251 SetRegisteredEvents(extension_id, events); | 282 SetRegisteredEvents(extension_id, events); |
| 252 } | 283 } |
| 253 } | 284 } |
| 254 | 285 |
| 255 void EventRouter::RemoveLazyEventListener(const std::string& event_name, | 286 void EventRouter::RemoveLazyEventListener(const std::string& event_name, |
| 256 const std::string& extension_id) { | 287 const std::string& extension_id) { |
| 257 EventListener listener(event_name, extension_id, NULL, | 288 EventListener listener( |
| 258 scoped_ptr<DictionaryValue>()); | 289 event_name, extension_id, GURL(), NULL, scoped_ptr<DictionaryValue>()); |
| 259 bool did_exist = listeners_.RemoveListener(&listener); | 290 bool did_exist = listeners_.RemoveListener(&listener); |
| 260 | 291 |
| 261 if (did_exist) { | 292 if (did_exist) { |
| 262 std::set<std::string> events = GetRegisteredEvents(extension_id); | 293 std::set<std::string> events = GetRegisteredEvents(extension_id); |
| 263 bool prefs_did_exist = events.erase(event_name) > 0; | 294 bool prefs_did_exist = events.erase(event_name) > 0; |
| 264 DCHECK(prefs_did_exist); | 295 DCHECK(prefs_did_exist); |
| 265 SetRegisteredEvents(extension_id, events); | 296 SetRegisteredEvents(extension_id, events); |
| 266 } | 297 } |
| 267 } | 298 } |
| 268 | 299 |
| 269 void EventRouter::AddFilteredEventListener(const std::string& event_name, | 300 void EventRouter::AddFilteredEventListener(const std::string& event_name, |
| 270 content::RenderProcessHost* process, | 301 content::RenderProcessHost* process, |
| 271 const std::string& extension_id, | 302 const std::string& extension_id, |
| 272 const base::DictionaryValue& filter, | 303 const base::DictionaryValue& filter, |
| 273 bool add_lazy_listener) { | 304 bool add_lazy_listener) { |
| 274 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( | 305 listeners_.AddListener(scoped_ptr<EventListener>(new EventListener( |
| 275 event_name, extension_id, process, | 306 event_name, |
| 307 extension_id, |
| 308 GURL(), // TODO(kalman): pass through URL from filtered events |
| 309 process, |
| 276 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); | 310 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); |
| 277 | 311 |
| 278 if (add_lazy_listener) { | 312 if (add_lazy_listener) { |
| 279 bool added = listeners_.AddListener(scoped_ptr<EventListener>( | 313 bool added = listeners_.AddListener(scoped_ptr<EventListener>( |
| 280 new EventListener(event_name, extension_id, NULL, | 314 new EventListener(event_name, |
| 281 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); | 315 extension_id, |
| 316 GURL(), // URL is irrelevant for lazy listeners. |
| 317 NULL, |
| 318 scoped_ptr<DictionaryValue>(filter.DeepCopy())))); |
| 282 | 319 |
| 283 if (added) | 320 if (added) |
| 284 AddFilterToEvent(event_name, extension_id, &filter); | 321 AddFilterToEvent(event_name, extension_id, &filter); |
| 285 } | 322 } |
| 286 } | 323 } |
| 287 | 324 |
| 288 void EventRouter::RemoveFilteredEventListener( | 325 void EventRouter::RemoveFilteredEventListener( |
| 289 const std::string& event_name, | 326 const std::string& event_name, |
| 290 content::RenderProcessHost* process, | 327 content::RenderProcessHost* process, |
| 291 const std::string& extension_id, | 328 const std::string& extension_id, |
| 292 const base::DictionaryValue& filter, | 329 const base::DictionaryValue& filter, |
| 293 bool remove_lazy_listener) { | 330 bool remove_lazy_listener) { |
| 294 EventListener listener(event_name, extension_id, process, | 331 EventListener listener(event_name, |
| 332 extension_id, |
| 333 GURL(), // TODO(kalman): URLs for filtered events |
| 334 process, |
| 295 scoped_ptr<DictionaryValue>(filter.DeepCopy())); | 335 scoped_ptr<DictionaryValue>(filter.DeepCopy())); |
| 296 | 336 |
| 297 listeners_.RemoveListener(&listener); | 337 listeners_.RemoveListener(&listener); |
| 298 | 338 |
| 299 if (remove_lazy_listener) { | 339 if (remove_lazy_listener) { |
| 300 listener.MakeLazy(); | 340 listener.MakeLazy(); |
| 301 bool removed = listeners_.RemoveListener(&listener); | 341 bool removed = listeners_.RemoveListener(&listener); |
| 302 | 342 |
| 303 if (removed) | 343 if (removed) |
| 304 RemoveFilterFromEvent(event_name, extension_id, &filter); | 344 RemoveFilterFromEvent(event_name, extension_id, &filter); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 | 504 |
| 465 for (std::set<const EventListener*>::iterator it = listeners.begin(); | 505 for (std::set<const EventListener*>::iterator it = listeners.begin(); |
| 466 it != listeners.end(); it++) { | 506 it != listeners.end(); it++) { |
| 467 const EventListener* listener = *it; | 507 const EventListener* listener = *it; |
| 468 if (restrict_to_extension_id.empty() || | 508 if (restrict_to_extension_id.empty() || |
| 469 restrict_to_extension_id == listener->extension_id()) { | 509 restrict_to_extension_id == listener->extension_id()) { |
| 470 if (listener->process()) { | 510 if (listener->process()) { |
| 471 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(), | 511 EventDispatchIdentifier dispatch_id(listener->GetBrowserContext(), |
| 472 listener->extension_id()); | 512 listener->extension_id()); |
| 473 if (!ContainsKey(already_dispatched, dispatch_id)) { | 513 if (!ContainsKey(already_dispatched, dispatch_id)) { |
| 474 DispatchEventToProcess( | 514 DispatchEventToProcess(listener->extension_id(), |
| 475 listener->extension_id(), listener->process(), event); | 515 listener->listener_url(), |
| 516 listener->process(), |
| 517 event); |
| 476 } | 518 } |
| 477 } | 519 } |
| 478 } | 520 } |
| 479 } | 521 } |
| 480 } | 522 } |
| 481 | 523 |
| 482 void EventRouter::DispatchLazyEvent( | 524 void EventRouter::DispatchLazyEvent( |
| 483 const std::string& extension_id, | 525 const std::string& extension_id, |
| 484 const linked_ptr<Event>& event, | 526 const linked_ptr<Event>& event, |
| 485 std::set<EventDispatchIdentifier>* already_dispatched) { | 527 std::set<EventDispatchIdentifier>* already_dispatched) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 504 browser_client->GetOffTheRecordContext(browser_context_); | 546 browser_client->GetOffTheRecordContext(browser_context_); |
| 505 if (MaybeLoadLazyBackgroundPageToDispatchEvent( | 547 if (MaybeLoadLazyBackgroundPageToDispatchEvent( |
| 506 incognito_context, extension, event)) { | 548 incognito_context, extension, event)) { |
| 507 already_dispatched->insert( | 549 already_dispatched->insert( |
| 508 std::make_pair(incognito_context, extension_id)); | 550 std::make_pair(incognito_context, extension_id)); |
| 509 } | 551 } |
| 510 } | 552 } |
| 511 } | 553 } |
| 512 | 554 |
| 513 void EventRouter::DispatchEventToProcess(const std::string& extension_id, | 555 void EventRouter::DispatchEventToProcess(const std::string& extension_id, |
| 556 const GURL& listener_url, |
| 514 content::RenderProcessHost* process, | 557 content::RenderProcessHost* process, |
| 515 const linked_ptr<Event>& event) { | 558 const linked_ptr<Event>& event) { |
| 516 BrowserContext* listener_context = process->GetBrowserContext(); | 559 BrowserContext* listener_context = process->GetBrowserContext(); |
| 517 ProcessMap* process_map = ProcessMap::Get(listener_context); | 560 ProcessMap* process_map = ProcessMap::Get(listener_context); |
| 518 | 561 |
| 519 const Extension* extension = | 562 const Extension* extension = |
| 520 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID( | 563 ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID( |
| 521 extension_id); | 564 extension_id); |
| 522 // NOTE: |extension| being NULL does not necessarily imply that this event | 565 // NOTE: |extension| being NULL does not necessarily imply that this event |
| 523 // shouldn't be dispatched. Events can be dispatched to WebUI as well. | 566 // shouldn't be dispatched. Events can be dispatched to WebUI as well. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 549 return; | 592 return; |
| 550 } | 593 } |
| 551 | 594 |
| 552 if (!CanDispatchEventToBrowserContext(listener_context, extension, event)) { | 595 if (!CanDispatchEventToBrowserContext(listener_context, extension, event)) { |
| 553 return; | 596 return; |
| 554 } | 597 } |
| 555 } else if (content::ChildProcessSecurityPolicy::GetInstance() | 598 } else if (content::ChildProcessSecurityPolicy::GetInstance() |
| 556 ->HasWebUIBindings(process->GetID())) { | 599 ->HasWebUIBindings(process->GetID())) { |
| 557 // Dispatching event to WebUI. | 600 // Dispatching event to WebUI. |
| 558 if (!ExtensionAPI::GetSharedInstance()->IsAvailableToWebUI( | 601 if (!ExtensionAPI::GetSharedInstance()->IsAvailableToWebUI( |
| 559 event->event_name)) { | 602 event->event_name, listener_url)) { |
| 560 return; | 603 return; |
| 561 } | 604 } |
| 562 } else { | 605 } else { |
| 563 // Dispatching event to a webpage - however, all such events (e.g. | 606 // Dispatching event to a webpage - however, all such events (e.g. |
| 564 // messaging) don't go through EventRouter so this should be impossible. | 607 // messaging) don't go through EventRouter so this should be impossible. |
| 565 return; | 608 return; |
| 566 } | 609 } |
| 567 | 610 |
| 568 if (!event->will_dispatch_callback.is_null()) { | 611 if (!event->will_dispatch_callback.is_null()) { |
| 569 event->will_dispatch_callback.Run( | 612 event->will_dispatch_callback.Run( |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 pm->DecrementLazyKeepaliveCount(host->extension()); | 726 pm->DecrementLazyKeepaliveCount(host->extension()); |
| 684 } | 727 } |
| 685 | 728 |
| 686 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event, | 729 void EventRouter::DispatchPendingEvent(const linked_ptr<Event>& event, |
| 687 ExtensionHost* host) { | 730 ExtensionHost* host) { |
| 688 if (!host) | 731 if (!host) |
| 689 return; | 732 return; |
| 690 | 733 |
| 691 if (listeners_.HasProcessListener(host->render_process_host(), | 734 if (listeners_.HasProcessListener(host->render_process_host(), |
| 692 host->extension()->id())) { | 735 host->extension()->id())) { |
| 693 DispatchEventToProcess(host->extension()->id(), | 736 DispatchEventToProcess( |
| 694 host->render_process_host(), event); | 737 host->extension()->id(), GURL(), host->render_process_host(), event); |
| 695 } | 738 } |
| 696 } | 739 } |
| 697 | 740 |
| 698 void EventRouter::Observe(int type, | 741 void EventRouter::Observe(int type, |
| 699 const content::NotificationSource& source, | 742 const content::NotificationSource& source, |
| 700 const content::NotificationDetails& details) { | 743 const content::NotificationDetails& details) { |
| 701 switch (type) { | 744 switch (type) { |
| 702 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: | 745 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
| 703 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | 746 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
| 704 content::RenderProcessHost* renderer = | 747 content::RenderProcessHost* renderer = |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 restrict_to_browser_context, | 835 restrict_to_browser_context, |
| 793 event_url, | 836 event_url, |
| 794 user_gesture, | 837 user_gesture, |
| 795 filter_info); | 838 filter_info); |
| 796 copy->will_dispatch_callback = will_dispatch_callback; | 839 copy->will_dispatch_callback = will_dispatch_callback; |
| 797 return copy; | 840 return copy; |
| 798 } | 841 } |
| 799 | 842 |
| 800 EventListenerInfo::EventListenerInfo(const std::string& event_name, | 843 EventListenerInfo::EventListenerInfo(const std::string& event_name, |
| 801 const std::string& extension_id, | 844 const std::string& extension_id, |
| 845 const GURL& listener_url, |
| 802 content::BrowserContext* browser_context) | 846 content::BrowserContext* browser_context) |
| 803 : event_name(event_name), | 847 : event_name(event_name), |
| 804 extension_id(extension_id), | 848 extension_id(extension_id), |
| 805 browser_context(browser_context) {} | 849 listener_url(listener_url), |
| 850 browser_context(browser_context) { |
| 851 } |
| 806 | 852 |
| 807 } // namespace extensions | 853 } // namespace extensions |
| OLD | NEW |