Home | History | Annotate | Download | only in browser
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "extensions/browser/event_router.h"
      6 
      7 #include <string>
      8 
      9 #include "base/bind.h"
     10 #include "base/compiler_specific.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/values.h"
     13 #include "content/public/browser/notification_service.h"
     14 #include "extensions/browser/event_listener_map.h"
     15 #include "extensions/browser/extensions_test.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace extensions {
     19 
     20 namespace {
     21 
     22 // A simple mock to keep track of listener additions and removals.
     23 class MockEventRouterObserver : public EventRouter::Observer {
     24  public:
     25   MockEventRouterObserver()
     26       : listener_added_count_(0),
     27         listener_removed_count_(0) {}
     28   virtual ~MockEventRouterObserver() {}
     29 
     30   int listener_added_count() const { return listener_added_count_; }
     31   int listener_removed_count() const { return listener_removed_count_; }
     32   const std::string& last_event_name() const { return last_event_name_; }
     33 
     34   void Reset() {
     35     listener_added_count_ = 0;
     36     listener_removed_count_ = 0;
     37     last_event_name_.clear();
     38   }
     39 
     40   // EventRouter::Observer overrides:
     41   virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE {
     42     listener_added_count_++;
     43     last_event_name_ = details.event_name;
     44   }
     45 
     46   virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE {
     47     listener_removed_count_++;
     48     last_event_name_ = details.event_name;
     49   }
     50 
     51  private:
     52   int listener_added_count_;
     53   int listener_removed_count_;
     54   std::string last_event_name_;
     55 
     56   DISALLOW_COPY_AND_ASSIGN(MockEventRouterObserver);
     57 };
     58 
     59 typedef base::Callback<scoped_ptr<EventListener>(
     60     const std::string&,           // event_name
     61     content::RenderProcessHost*,  // process
     62     base::DictionaryValue*        // filter (takes ownership)
     63     )> EventListenerConstructor;
     64 
     65 scoped_ptr<EventListener> CreateEventListenerForExtension(
     66     const std::string& extension_id,
     67     const std::string& event_name,
     68     content::RenderProcessHost* process,
     69     base::DictionaryValue* filter) {
     70   return EventListener::ForExtension(
     71       event_name, extension_id, process, make_scoped_ptr(filter));
     72 }
     73 
     74 scoped_ptr<EventListener> CreateEventListenerForURL(
     75     const GURL& listener_url,
     76     const std::string& event_name,
     77     content::RenderProcessHost* process,
     78     base::DictionaryValue* filter) {
     79   return EventListener::ForURL(
     80       event_name, listener_url, process, make_scoped_ptr(filter));
     81 }
     82 
     83 }  // namespace
     84 
     85 class EventRouterTest : public ExtensionsTest {
     86  public:
     87   EventRouterTest()
     88       : notification_service_(content::NotificationService::Create()) {}
     89 
     90  protected:
     91   // Tests adding and removing observers from EventRouter.
     92   void RunEventRouterObserverTest(const EventListenerConstructor& constructor);
     93 
     94  private:
     95   scoped_ptr<content::NotificationService> notification_service_;
     96 
     97   DISALLOW_COPY_AND_ASSIGN(EventRouterTest);
     98 };
     99 
    100 TEST_F(EventRouterTest, GetBaseEventName) {
    101   // Normal event names are passed through unchanged.
    102   EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar"));
    103 
    104   // Sub-events are converted to the part before the slash.
    105   EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar/123"));
    106 }
    107 
    108 // Tests adding and removing observers from EventRouter.
    109 void EventRouterTest::RunEventRouterObserverTest(
    110     const EventListenerConstructor& constructor) {
    111   EventRouter router(NULL, NULL);
    112   scoped_ptr<EventListener> listener =
    113       constructor.Run("event_name", NULL, new base::DictionaryValue());
    114 
    115   // Add/remove works without any observers.
    116   router.OnListenerAdded(listener.get());
    117   router.OnListenerRemoved(listener.get());
    118 
    119   // Register observers that both match and don't match the event above.
    120   MockEventRouterObserver matching_observer;
    121   router.RegisterObserver(&matching_observer, "event_name");
    122   MockEventRouterObserver non_matching_observer;
    123   router.RegisterObserver(&non_matching_observer, "other");
    124 
    125   // Adding a listener notifies the appropriate observers.
    126   router.OnListenerAdded(listener.get());
    127   EXPECT_EQ(1, matching_observer.listener_added_count());
    128   EXPECT_EQ(0, non_matching_observer.listener_added_count());
    129 
    130   // Removing a listener notifies the appropriate observers.
    131   router.OnListenerRemoved(listener.get());
    132   EXPECT_EQ(1, matching_observer.listener_removed_count());
    133   EXPECT_EQ(0, non_matching_observer.listener_removed_count());
    134 
    135   // Adding the listener again notifies again.
    136   router.OnListenerAdded(listener.get());
    137   EXPECT_EQ(2, matching_observer.listener_added_count());
    138   EXPECT_EQ(0, non_matching_observer.listener_added_count());
    139 
    140   // Removing the listener again notifies again.
    141   router.OnListenerRemoved(listener.get());
    142   EXPECT_EQ(2, matching_observer.listener_removed_count());
    143   EXPECT_EQ(0, non_matching_observer.listener_removed_count());
    144 
    145   // Adding a listener with a sub-event notifies the main observer with
    146   // proper details.
    147   matching_observer.Reset();
    148   scoped_ptr<EventListener> sub_event_listener =
    149       constructor.Run("event_name/1", NULL, new base::DictionaryValue());
    150   router.OnListenerAdded(sub_event_listener.get());
    151   EXPECT_EQ(1, matching_observer.listener_added_count());
    152   EXPECT_EQ(0, matching_observer.listener_removed_count());
    153   EXPECT_EQ("event_name/1", matching_observer.last_event_name());
    154 
    155   // Ditto for removing the listener.
    156   matching_observer.Reset();
    157   router.OnListenerRemoved(sub_event_listener.get());
    158   EXPECT_EQ(0, matching_observer.listener_added_count());
    159   EXPECT_EQ(1, matching_observer.listener_removed_count());
    160   EXPECT_EQ("event_name/1", matching_observer.last_event_name());
    161 }
    162 
    163 TEST_F(EventRouterTest, EventRouterObserverForExtensions) {
    164   RunEventRouterObserverTest(
    165       base::Bind(&CreateEventListenerForExtension, "extension_id"));
    166 }
    167 
    168 TEST_F(EventRouterTest, EventRouterObserverForURLs) {
    169   RunEventRouterObserverTest(
    170       base::Bind(&CreateEventListenerForURL, GURL("http://google.com/path")));
    171 }
    172 
    173 }  // namespace extensions
    174