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.
5 #include "extensions/browser/event_router.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"
18 namespace extensions
{
22 // A simple mock to keep track of listener additions and removals.
23 class MockEventRouterObserver
: public EventRouter::Observer
{
25 MockEventRouterObserver()
26 : listener_added_count_(0),
27 listener_removed_count_(0) {}
28 virtual ~MockEventRouterObserver() {}
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_
; }
35 listener_added_count_
= 0;
36 listener_removed_count_
= 0;
37 last_event_name_
.clear();
40 // EventRouter::Observer overrides:
41 virtual void OnListenerAdded(const EventListenerInfo
& details
) OVERRIDE
{
42 listener_added_count_
++;
43 last_event_name_
= details
.event_name
;
46 virtual void OnListenerRemoved(const EventListenerInfo
& details
) OVERRIDE
{
47 listener_removed_count_
++;
48 last_event_name_
= details
.event_name
;
52 int listener_added_count_
;
53 int listener_removed_count_
;
54 std::string last_event_name_
;
56 DISALLOW_COPY_AND_ASSIGN(MockEventRouterObserver
);
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
;
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
));
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
));
85 class EventRouterTest
: public ExtensionsTest
{
88 : notification_service_(content::NotificationService::Create()) {}
91 // Tests adding and removing observers from EventRouter.
92 void RunEventRouterObserverTest(const EventListenerConstructor
& constructor
);
95 scoped_ptr
<content::NotificationService
> notification_service_
;
97 DISALLOW_COPY_AND_ASSIGN(EventRouterTest
);
100 TEST_F(EventRouterTest
, GetBaseEventName
) {
101 // Normal event names are passed through unchanged.
102 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar"));
104 // Sub-events are converted to the part before the slash.
105 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar/123"));
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());
115 // Add/remove works without any observers.
116 router
.OnListenerAdded(listener
.get());
117 router
.OnListenerRemoved(listener
.get());
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");
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());
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());
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());
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());
145 // Adding a listener with a sub-event notifies the main observer with
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());
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());
163 TEST_F(EventRouterTest
, EventRouterObserverForExtensions
) {
164 RunEventRouterObserverTest(
165 base::Bind(&CreateEventListenerForExtension
, "extension_id"));
168 TEST_F(EventRouterTest
, EventRouterObserverForURLs
) {
169 RunEventRouterObserverTest(
170 base::Bind(&CreateEventListenerForURL
, GURL("http://google.com/path")));
173 } // namespace extensions