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 "testing/gmock/include/gmock/gmock.h"
18#include "testing/gtest/include/gtest/gtest.h"
19#include "url/gurl.h"
20
21using content::BrowserThread;
22
23namespace extensions {
24
25namespace {
26
27const char kEventName[] = "event_name";
28const char kExt[] = "extension";
29
30class MockEventRouterForwarder : public EventRouterForwarder {
31 public:
32  MOCK_METHOD5(CallEventRouter,
33      void(Profile*, const std::string&, const std::string&, Profile*,
34           const GURL&));
35
36  virtual void CallEventRouter(
37      Profile* profile, const std::string& extension_id,
38      const std::string& event_name, scoped_ptr<base::ListValue> event_args,
39      Profile* restrict_to_profile, const GURL& event_url) {
40    CallEventRouter(profile, extension_id, event_name,
41                             restrict_to_profile, event_url);
42  }
43
44 protected:
45  virtual ~MockEventRouterForwarder() {}
46};
47
48static void BroadcastEventToRenderers(EventRouterForwarder* event_router,
49                                      const std::string& event_name,
50                                      const GURL& url) {
51  scoped_ptr<base::ListValue> args(new base::ListValue());
52  event_router->BroadcastEventToRenderers(event_name, args.Pass(), url);
53}
54
55static void DispatchEventToRenderers(EventRouterForwarder* event_router,
56                                     const std::string& event_name,
57                                     void* profile,
58                                     bool use_profile_to_restrict_events,
59                                     const GURL& url) {
60  scoped_ptr<base::ListValue> args(new base::ListValue());
61  event_router->DispatchEventToRenderers(event_name, args.Pass(), profile,
62                                         use_profile_to_restrict_events, url);
63}
64
65static void BroadcastEventToExtension(EventRouterForwarder* event_router,
66                                      const std::string& extension,
67                                      const std::string& event_name,
68                                      const GURL& url) {
69  scoped_ptr<base::ListValue> args(new base::ListValue());
70  event_router->BroadcastEventToExtension(extension, event_name, args.Pass(),
71                                          url);
72}
73
74static void DispatchEventToExtension(EventRouterForwarder* event_router,
75                                     const std::string& extension,
76                                     const std::string& event_name,
77                                     void* profile,
78                                     bool use_profile_to_restrict_events,
79                                     const GURL& url) {
80  scoped_ptr<base::ListValue> args(new base::ListValue());
81  event_router->DispatchEventToExtension(
82      extension, event_name, args.Pass(), profile,
83      use_profile_to_restrict_events, url);
84}
85
86}  // namespace
87
88class EventRouterForwarderTest : public testing::Test {
89 protected:
90  EventRouterForwarderTest()
91      : ui_thread_(BrowserThread::UI, &message_loop_),
92        io_thread_(BrowserThread::IO),
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    ASSERT_TRUE(io_thread_.Start());
108
109    profile1_ = profile_manager_.CreateTestingProfile("one");
110    profile2_ = profile_manager_.CreateTestingProfile("two");
111  }
112
113  TestingProfile* CreateIncognitoProfile(TestingProfile* base) {
114    TestingProfile::Builder builder;
115    builder.SetIncognito();
116    scoped_ptr<TestingProfile> incognito = builder.Build();
117    TestingProfile* incognito_ptr = incognito.get();
118    // Incognito profile now owned by |base|
119    base->SetOffTheRecordProfile(incognito.PassAs<Profile>());
120    return incognito_ptr;
121  }
122
123  base::MessageLoopForUI message_loop_;
124  content::TestBrowserThread ui_thread_;
125  content::TestBrowserThread io_thread_;
126  TestingProfileManager profile_manager_;
127  scoped_ptr<base::PowerMonitor> dummy;
128  // Profiles are weak pointers, owned by ProfileManager in |browser_process_|.
129  TestingProfile* profile1_;
130  TestingProfile* profile2_;
131};
132
133TEST_F(EventRouterForwarderTest, BroadcastRendererUI) {
134  scoped_refptr<MockEventRouterForwarder> event_router(
135      new MockEventRouterForwarder);
136  GURL url;
137  EXPECT_CALL(*event_router.get(),
138              CallEventRouter(profile1_, "", kEventName, profile1_, url));
139  EXPECT_CALL(*event_router.get(),
140              CallEventRouter(profile2_, "", kEventName, profile2_, url));
141  BroadcastEventToRenderers(event_router.get(), kEventName, url);
142}
143
144TEST_F(EventRouterForwarderTest, BroadcastRendererUIIncognito) {
145  scoped_refptr<MockEventRouterForwarder> event_router(
146      new MockEventRouterForwarder);
147  using ::testing::_;
148  GURL url;
149  Profile* incognito = CreateIncognitoProfile(profile1_);
150  EXPECT_CALL(*event_router.get(),
151              CallEventRouter(profile1_, "", kEventName, profile1_, url));
152  EXPECT_CALL(*event_router.get(), CallEventRouter(incognito, _, _, _, _))
153      .Times(0);
154  EXPECT_CALL(*event_router.get(),
155              CallEventRouter(profile2_, "", kEventName, profile2_, url));
156  BroadcastEventToRenderers(event_router.get(), kEventName, url);
157}
158
159// This is the canonical test for passing control flow from the IO thread
160// to the UI thread. Repeating this for all public functions of
161// EventRouterForwarder would not increase coverage.
162TEST_F(EventRouterForwarderTest, BroadcastRendererIO) {
163  scoped_refptr<MockEventRouterForwarder> event_router(
164      new MockEventRouterForwarder);
165  GURL url;
166  EXPECT_CALL(*event_router.get(),
167              CallEventRouter(profile1_, "", kEventName, profile1_, url));
168  EXPECT_CALL(*event_router.get(),
169              CallEventRouter(profile2_, "", kEventName, profile2_, url));
170  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
171      base::Bind(
172          &BroadcastEventToRenderers, base::Unretained(event_router.get()),
173          kEventName, url));
174
175  // Wait for IO thread's message loop to be processed
176  scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper(
177      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()));
178  ASSERT_TRUE(helper->Run());
179
180  base::MessageLoop::current()->RunUntilIdle();
181}
182
183TEST_F(EventRouterForwarderTest, UnicastRendererUIRestricted) {
184  scoped_refptr<MockEventRouterForwarder> event_router(
185      new MockEventRouterForwarder);
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(profile2_, _, _, _, _))
191      .Times(0);
192  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, true,
193                           url);
194}
195
196TEST_F(EventRouterForwarderTest, UnicastRendererUIRestrictedIncognito1) {
197  scoped_refptr<MockEventRouterForwarder> event_router(
198      new MockEventRouterForwarder);
199  Profile* incognito = CreateIncognitoProfile(profile1_);
200  using ::testing::_;
201  GURL url;
202  EXPECT_CALL(*event_router.get(),
203              CallEventRouter(profile1_, "", kEventName, profile1_, url));
204  EXPECT_CALL(*event_router.get(), CallEventRouter(incognito, _, _, _, _))
205      .Times(0);
206  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
207      .Times(0);
208  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, true,
209                           url);
210}
211
212TEST_F(EventRouterForwarderTest, UnicastRendererUIRestrictedIncognito2) {
213  scoped_refptr<MockEventRouterForwarder> event_router(
214      new MockEventRouterForwarder);
215  Profile* incognito = CreateIncognitoProfile(profile1_);
216  using ::testing::_;
217  GURL url;
218  EXPECT_CALL(*event_router.get(), CallEventRouter(profile1_, _, _, _, _))
219      .Times(0);
220  EXPECT_CALL(*event_router.get(),
221              CallEventRouter(incognito, "", kEventName, incognito, url));
222  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
223      .Times(0);
224  DispatchEventToRenderers(event_router.get(), kEventName, incognito, true,
225                           url);
226}
227
228TEST_F(EventRouterForwarderTest, UnicastRendererUIUnrestricted) {
229  scoped_refptr<MockEventRouterForwarder> event_router(
230      new MockEventRouterForwarder);
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(profile2_, _, _, _, _))
236      .Times(0);
237  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, false,
238                           url);
239}
240
241TEST_F(EventRouterForwarderTest, UnicastRendererUIUnrestrictedIncognito) {
242  scoped_refptr<MockEventRouterForwarder> event_router(
243      new MockEventRouterForwarder);
244  Profile* incognito = CreateIncognitoProfile(profile1_);
245  using ::testing::_;
246  GURL url;
247  EXPECT_CALL(*event_router.get(),
248              CallEventRouter(profile1_, "", kEventName, NULL, url));
249  EXPECT_CALL(*event_router.get(), CallEventRouter(incognito, _, _, _, _))
250      .Times(0);
251  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
252      .Times(0);
253  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, false,
254                           url);
255}
256
257TEST_F(EventRouterForwarderTest, BroadcastExtensionUI) {
258  scoped_refptr<MockEventRouterForwarder> event_router(
259      new MockEventRouterForwarder);
260  GURL url;
261  EXPECT_CALL(*event_router.get(),
262              CallEventRouter(profile1_, kExt, kEventName, profile1_, url));
263  EXPECT_CALL(*event_router.get(),
264              CallEventRouter(profile2_, kExt, kEventName, profile2_, url));
265  BroadcastEventToExtension(event_router.get(), kExt, kEventName, url);
266}
267
268TEST_F(EventRouterForwarderTest, UnicastExtensionUIRestricted) {
269  scoped_refptr<MockEventRouterForwarder> event_router(
270      new MockEventRouterForwarder);
271  using ::testing::_;
272  GURL url;
273  EXPECT_CALL(*event_router.get(),
274              CallEventRouter(profile1_, kExt, kEventName, profile1_, url));
275  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
276      .Times(0);
277  DispatchEventToExtension(event_router.get(), kExt, kEventName, profile1_,
278                           true, url);
279}
280
281TEST_F(EventRouterForwarderTest, UnicastExtensionUIUnrestricted) {
282  scoped_refptr<MockEventRouterForwarder> event_router(
283      new MockEventRouterForwarder);
284  using ::testing::_;
285  GURL url;
286  EXPECT_CALL(*event_router.get(),
287              CallEventRouter(profile1_, kExt, kEventName, NULL, url));
288  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
289      .Times(0);
290  DispatchEventToExtension(event_router.get(), kExt, kEventName, profile1_,
291                           false, url);
292}
293
294}  // namespace extensions
295