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
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/event_router_forwarder.h"
6
7#include "base/bind.h"
8#include "base/message_loop/message_loop.h"
9#include "base/power_monitor/power_monitor.h"
10#include "base/power_monitor/power_monitor_device_source.h"
11#include "base/test/thread_test_helper.h"
12#include "chrome/browser/profiles/profile_manager.h"
13#include "chrome/test/base/testing_browser_process.h"
14#include "chrome/test/base/testing_profile.h"
15#include "chrome/test/base/testing_profile_manager.h"
16#include "content/public/test/test_browser_thread.h"
17#include "content/public/test/test_browser_thread_bundle.h"
18#include "testing/gmock/include/gmock/gmock.h"
19#include "testing/gtest/include/gtest/gtest.h"
20#include "url/gurl.h"
21
22using content::BrowserThread;
23
24namespace extensions {
25
26namespace {
27
28const char kEventName[] = "event_name";
29const char kExt[] = "extension";
30
31class MockEventRouterForwarder : public EventRouterForwarder {
32 public:
33  MOCK_METHOD5(CallEventRouter,
34      void(Profile*, const std::string&, const std::string&, Profile*,
35           const GURL&));
36
37  virtual void CallEventRouter(
38      Profile* profile, const std::string& extension_id,
39      const std::string& event_name, scoped_ptr<base::ListValue> event_args,
40      Profile* restrict_to_profile, const GURL& event_url) {
41    CallEventRouter(profile, extension_id, event_name,
42                             restrict_to_profile, event_url);
43  }
44
45 protected:
46  virtual ~MockEventRouterForwarder() {}
47};
48
49static void BroadcastEventToRenderers(EventRouterForwarder* event_router,
50                                      const std::string& event_name,
51                                      const GURL& url) {
52  scoped_ptr<base::ListValue> args(new base::ListValue());
53  event_router->BroadcastEventToRenderers(event_name, args.Pass(), url);
54}
55
56static void DispatchEventToRenderers(EventRouterForwarder* event_router,
57                                     const std::string& event_name,
58                                     void* profile,
59                                     bool use_profile_to_restrict_events,
60                                     const GURL& url) {
61  scoped_ptr<base::ListValue> args(new base::ListValue());
62  event_router->DispatchEventToRenderers(event_name, args.Pass(), profile,
63                                         use_profile_to_restrict_events, url);
64}
65
66static void BroadcastEventToExtension(EventRouterForwarder* event_router,
67                                      const std::string& extension,
68                                      const std::string& event_name,
69                                      const GURL& url) {
70  scoped_ptr<base::ListValue> args(new base::ListValue());
71  event_router->BroadcastEventToExtension(extension, event_name, args.Pass(),
72                                          url);
73}
74
75static void DispatchEventToExtension(EventRouterForwarder* event_router,
76                                     const std::string& extension,
77                                     const std::string& event_name,
78                                     void* profile,
79                                     bool use_profile_to_restrict_events,
80                                     const GURL& url) {
81  scoped_ptr<base::ListValue> args(new base::ListValue());
82  event_router->DispatchEventToExtension(
83      extension, event_name, args.Pass(), profile,
84      use_profile_to_restrict_events, url);
85}
86
87}  // namespace
88
89class EventRouterForwarderTest : public testing::Test {
90 protected:
91  EventRouterForwarderTest()
92      : thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD),
93        profile_manager_(
94            TestingBrowserProcess::GetGlobal()) {
95#if defined(OS_MACOSX)
96    base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
97#endif
98    scoped_ptr<base::PowerMonitorSource> power_monitor_source(
99      new base::PowerMonitorDeviceSource());
100    dummy.reset(new base::PowerMonitor(power_monitor_source.Pass()));
101  }
102
103  virtual void SetUp() {
104    ASSERT_TRUE(profile_manager_.SetUp());
105
106    // Inject a BrowserProcess with a ProfileManager.
107    profile1_ = profile_manager_.CreateTestingProfile("one");
108    profile2_ = profile_manager_.CreateTestingProfile("two");
109  }
110
111  content::TestBrowserThreadBundle thread_bundle_;
112  TestingProfileManager profile_manager_;
113  scoped_ptr<base::PowerMonitor> dummy;
114  // Profiles are weak pointers, owned by ProfileManager in |browser_process_|.
115  TestingProfile* profile1_;
116  TestingProfile* profile2_;
117};
118
119TEST_F(EventRouterForwarderTest, BroadcastRendererUI) {
120  scoped_refptr<MockEventRouterForwarder> event_router(
121      new MockEventRouterForwarder);
122  GURL url;
123  EXPECT_CALL(*event_router.get(),
124              CallEventRouter(profile1_, "", kEventName, profile1_, url));
125  EXPECT_CALL(*event_router.get(),
126              CallEventRouter(profile2_, "", kEventName, profile2_, url));
127  BroadcastEventToRenderers(event_router.get(), kEventName, url);
128}
129
130TEST_F(EventRouterForwarderTest, BroadcastRendererUIIncognito) {
131  scoped_refptr<MockEventRouterForwarder> event_router(
132      new MockEventRouterForwarder);
133  using ::testing::_;
134  GURL url;
135  Profile* incognito = profile1_->GetOffTheRecordProfile();
136  EXPECT_CALL(*event_router.get(),
137              CallEventRouter(profile1_, "", kEventName, profile1_, url));
138  EXPECT_CALL(*event_router.get(), CallEventRouter(incognito, _, _, _, _))
139      .Times(0);
140  EXPECT_CALL(*event_router.get(),
141              CallEventRouter(profile2_, "", kEventName, profile2_, url));
142  BroadcastEventToRenderers(event_router.get(), kEventName, url);
143}
144
145// This is the canonical test for passing control flow from the IO thread
146// to the UI thread. Repeating this for all public functions of
147// EventRouterForwarder would not increase coverage.
148TEST_F(EventRouterForwarderTest, BroadcastRendererIO) {
149  scoped_refptr<MockEventRouterForwarder> event_router(
150      new MockEventRouterForwarder);
151  GURL url;
152  EXPECT_CALL(*event_router.get(),
153              CallEventRouter(profile1_, "", kEventName, profile1_, url));
154  EXPECT_CALL(*event_router.get(),
155              CallEventRouter(profile2_, "", kEventName, profile2_, url));
156  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
157      base::Bind(
158          &BroadcastEventToRenderers, base::Unretained(event_router.get()),
159          kEventName, url));
160
161  // Wait for IO thread's message loop to be processed
162  scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper(
163      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()));
164  ASSERT_TRUE(helper->Run());
165
166  base::MessageLoop::current()->RunUntilIdle();
167}
168
169TEST_F(EventRouterForwarderTest, UnicastRendererUIRestricted) {
170  scoped_refptr<MockEventRouterForwarder> event_router(
171      new MockEventRouterForwarder);
172  using ::testing::_;
173  GURL url;
174  EXPECT_CALL(*event_router.get(),
175              CallEventRouter(profile1_, "", kEventName, profile1_, url));
176  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
177      .Times(0);
178  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, true,
179                           url);
180}
181
182TEST_F(EventRouterForwarderTest, UnicastRendererUIRestrictedIncognito1) {
183  scoped_refptr<MockEventRouterForwarder> event_router(
184      new MockEventRouterForwarder);
185  Profile* incognito = profile1_->GetOffTheRecordProfile();
186  using ::testing::_;
187  GURL url;
188  EXPECT_CALL(*event_router.get(),
189              CallEventRouter(profile1_, "", kEventName, profile1_, url));
190  EXPECT_CALL(*event_router.get(), CallEventRouter(incognito, _, _, _, _))
191      .Times(0);
192  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
193      .Times(0);
194  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, true,
195                           url);
196}
197
198TEST_F(EventRouterForwarderTest, UnicastRendererUIRestrictedIncognito2) {
199  scoped_refptr<MockEventRouterForwarder> event_router(
200      new MockEventRouterForwarder);
201  Profile* incognito = profile1_->GetOffTheRecordProfile();
202  using ::testing::_;
203  GURL url;
204  EXPECT_CALL(*event_router.get(), CallEventRouter(profile1_, _, _, _, _))
205      .Times(0);
206  EXPECT_CALL(*event_router.get(),
207              CallEventRouter(incognito, "", kEventName, incognito, url));
208  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
209      .Times(0);
210  DispatchEventToRenderers(event_router.get(), kEventName, incognito, true,
211                           url);
212}
213
214TEST_F(EventRouterForwarderTest, UnicastRendererUIUnrestricted) {
215  scoped_refptr<MockEventRouterForwarder> event_router(
216      new MockEventRouterForwarder);
217  using ::testing::_;
218  GURL url;
219  EXPECT_CALL(*event_router.get(),
220              CallEventRouter(profile1_, "", kEventName, NULL, url));
221  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
222      .Times(0);
223  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, false,
224                           url);
225}
226
227TEST_F(EventRouterForwarderTest, UnicastRendererUIUnrestrictedIncognito) {
228  scoped_refptr<MockEventRouterForwarder> event_router(
229      new MockEventRouterForwarder);
230  Profile* incognito = profile1_->GetOffTheRecordProfile();
231  using ::testing::_;
232  GURL url;
233  EXPECT_CALL(*event_router.get(),
234              CallEventRouter(profile1_, "", kEventName, NULL, url));
235  EXPECT_CALL(*event_router.get(), CallEventRouter(incognito, _, _, _, _))
236      .Times(0);
237  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
238      .Times(0);
239  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, false,
240                           url);
241}
242
243TEST_F(EventRouterForwarderTest, BroadcastExtensionUI) {
244  scoped_refptr<MockEventRouterForwarder> event_router(
245      new MockEventRouterForwarder);
246  GURL url;
247  EXPECT_CALL(*event_router.get(),
248              CallEventRouter(profile1_, kExt, kEventName, profile1_, url));
249  EXPECT_CALL(*event_router.get(),
250              CallEventRouter(profile2_, kExt, kEventName, profile2_, url));
251  BroadcastEventToExtension(event_router.get(), kExt, kEventName, url);
252}
253
254TEST_F(EventRouterForwarderTest, UnicastExtensionUIRestricted) {
255  scoped_refptr<MockEventRouterForwarder> event_router(
256      new MockEventRouterForwarder);
257  using ::testing::_;
258  GURL url;
259  EXPECT_CALL(*event_router.get(),
260              CallEventRouter(profile1_, kExt, kEventName, profile1_, url));
261  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
262      .Times(0);
263  DispatchEventToExtension(event_router.get(), kExt, kEventName, profile1_,
264                           true, url);
265}
266
267TEST_F(EventRouterForwarderTest, UnicastExtensionUIUnrestricted) {
268  scoped_refptr<MockEventRouterForwarder> event_router(
269      new MockEventRouterForwarder);
270  using ::testing::_;
271  GURL url;
272  EXPECT_CALL(*event_router.get(),
273              CallEventRouter(profile1_, kExt, kEventName, NULL, url));
274  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
275      .Times(0);
276  DispatchEventToExtension(event_router.get(), kExt, kEventName, profile1_,
277                           false, url);
278}
279
280}  // namespace extensions
281