• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MockEventRouterObserver()25   MockEventRouterObserver()
26       : listener_added_count_(0),
27         listener_removed_count_(0) {}
~MockEventRouterObserver()28   virtual ~MockEventRouterObserver() {}
29 
listener_added_count() const30   int listener_added_count() const { return listener_added_count_; }
listener_removed_count() const31   int listener_removed_count() const { return listener_removed_count_; }
last_event_name() const32   const std::string& last_event_name() const { return last_event_name_; }
33 
Reset()34   void Reset() {
35     listener_added_count_ = 0;
36     listener_removed_count_ = 0;
37     last_event_name_.clear();
38   }
39 
40   // EventRouter::Observer overrides:
OnListenerAdded(const EventListenerInfo & details)41   virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE {
42     listener_added_count_++;
43     last_event_name_ = details.event_name;
44   }
45 
OnListenerRemoved(const EventListenerInfo & details)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 
CreateEventListenerForExtension(const std::string & extension_id,const std::string & event_name,content::RenderProcessHost * process,base::DictionaryValue * filter)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 
CreateEventListenerForURL(const GURL & listener_url,const std::string & event_name,content::RenderProcessHost * process,base::DictionaryValue * filter)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:
EventRouterTest()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 
TEST_F(EventRouterTest,GetBaseEventName)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.
RunEventRouterObserverTest(const EventListenerConstructor & constructor)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 
TEST_F(EventRouterTest,EventRouterObserverForExtensions)163 TEST_F(EventRouterTest, EventRouterObserverForExtensions) {
164   RunEventRouterObserverTest(
165       base::Bind(&CreateEventListenerForExtension, "extension_id"));
166 }
167 
TEST_F(EventRouterTest,EventRouterObserverForURLs)168 TEST_F(EventRouterTest, EventRouterObserverForURLs) {
169   RunEventRouterObserverTest(
170       base::Bind(&CreateEventListenerForURL, GURL("http://google.com/path")));
171 }
172 
173 }  // namespace extensions
174