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* incognito = new TestingProfile;  // Owned by |base|.
115    incognito->set_incognito(true);
116    base->SetOffTheRecordProfile(incognito);
117    return incognito;
118  }
119
120  base::MessageLoopForUI message_loop_;
121  content::TestBrowserThread ui_thread_;
122  content::TestBrowserThread io_thread_;
123  TestingProfileManager profile_manager_;
124  scoped_ptr<base::PowerMonitor> dummy;
125  // Profiles are weak pointers, owned by ProfileManager in |browser_process_|.
126  TestingProfile* profile1_;
127  TestingProfile* profile2_;
128};
129
130TEST_F(EventRouterForwarderTest, BroadcastRendererUI) {
131  scoped_refptr<MockEventRouterForwarder> event_router(
132      new MockEventRouterForwarder);
133  GURL url;
134  EXPECT_CALL(*event_router.get(),
135              CallEventRouter(profile1_, "", kEventName, profile1_, url));
136  EXPECT_CALL(*event_router.get(),
137              CallEventRouter(profile2_, "", kEventName, profile2_, url));
138  BroadcastEventToRenderers(event_router.get(), kEventName, url);
139}
140
141TEST_F(EventRouterForwarderTest, BroadcastRendererUIIncognito) {
142  scoped_refptr<MockEventRouterForwarder> event_router(
143      new MockEventRouterForwarder);
144  using ::testing::_;
145  GURL url;
146  Profile* incognito = CreateIncognitoProfile(profile1_);
147  EXPECT_CALL(*event_router.get(),
148              CallEventRouter(profile1_, "", kEventName, profile1_, url));
149  EXPECT_CALL(*event_router.get(), CallEventRouter(incognito, _, _, _, _))
150      .Times(0);
151  EXPECT_CALL(*event_router.get(),
152              CallEventRouter(profile2_, "", kEventName, profile2_, url));
153  BroadcastEventToRenderers(event_router.get(), kEventName, url);
154}
155
156// This is the canonical test for passing control flow from the IO thread
157// to the UI thread. Repeating this for all public functions of
158// EventRouterForwarder would not increase coverage.
159TEST_F(EventRouterForwarderTest, BroadcastRendererIO) {
160  scoped_refptr<MockEventRouterForwarder> event_router(
161      new MockEventRouterForwarder);
162  GURL url;
163  EXPECT_CALL(*event_router.get(),
164              CallEventRouter(profile1_, "", kEventName, profile1_, url));
165  EXPECT_CALL(*event_router.get(),
166              CallEventRouter(profile2_, "", kEventName, profile2_, url));
167  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
168      base::Bind(
169          &BroadcastEventToRenderers, base::Unretained(event_router.get()),
170          kEventName, url));
171
172  // Wait for IO thread's message loop to be processed
173  scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper(
174      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()));
175  ASSERT_TRUE(helper->Run());
176
177  base::MessageLoop::current()->RunUntilIdle();
178}
179
180TEST_F(EventRouterForwarderTest, UnicastRendererUIRestricted) {
181  scoped_refptr<MockEventRouterForwarder> event_router(
182      new MockEventRouterForwarder);
183  using ::testing::_;
184  GURL url;
185  EXPECT_CALL(*event_router.get(),
186              CallEventRouter(profile1_, "", kEventName, profile1_, url));
187  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
188      .Times(0);
189  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, true,
190                           url);
191}
192
193TEST_F(EventRouterForwarderTest, UnicastRendererUIRestrictedIncognito1) {
194  scoped_refptr<MockEventRouterForwarder> event_router(
195      new MockEventRouterForwarder);
196  Profile* incognito = CreateIncognitoProfile(profile1_);
197  using ::testing::_;
198  GURL url;
199  EXPECT_CALL(*event_router.get(),
200              CallEventRouter(profile1_, "", kEventName, profile1_, url));
201  EXPECT_CALL(*event_router.get(), CallEventRouter(incognito, _, _, _, _))
202      .Times(0);
203  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
204      .Times(0);
205  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, true,
206                           url);
207}
208
209TEST_F(EventRouterForwarderTest, UnicastRendererUIRestrictedIncognito2) {
210  scoped_refptr<MockEventRouterForwarder> event_router(
211      new MockEventRouterForwarder);
212  Profile* incognito = CreateIncognitoProfile(profile1_);
213  using ::testing::_;
214  GURL url;
215  EXPECT_CALL(*event_router.get(), CallEventRouter(profile1_, _, _, _, _))
216      .Times(0);
217  EXPECT_CALL(*event_router.get(),
218              CallEventRouter(incognito, "", kEventName, incognito, url));
219  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
220      .Times(0);
221  DispatchEventToRenderers(event_router.get(), kEventName, incognito, true,
222                           url);
223}
224
225TEST_F(EventRouterForwarderTest, UnicastRendererUIUnrestricted) {
226  scoped_refptr<MockEventRouterForwarder> event_router(
227      new MockEventRouterForwarder);
228  using ::testing::_;
229  GURL url;
230  EXPECT_CALL(*event_router.get(),
231              CallEventRouter(profile1_, "", kEventName, NULL, url));
232  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
233      .Times(0);
234  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, false,
235                           url);
236}
237
238TEST_F(EventRouterForwarderTest, UnicastRendererUIUnrestrictedIncognito) {
239  scoped_refptr<MockEventRouterForwarder> event_router(
240      new MockEventRouterForwarder);
241  Profile* incognito = CreateIncognitoProfile(profile1_);
242  using ::testing::_;
243  GURL url;
244  EXPECT_CALL(*event_router.get(),
245              CallEventRouter(profile1_, "", kEventName, NULL, url));
246  EXPECT_CALL(*event_router.get(), CallEventRouter(incognito, _, _, _, _))
247      .Times(0);
248  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
249      .Times(0);
250  DispatchEventToRenderers(event_router.get(), kEventName, profile1_, false,
251                           url);
252}
253
254TEST_F(EventRouterForwarderTest, BroadcastExtensionUI) {
255  scoped_refptr<MockEventRouterForwarder> event_router(
256      new MockEventRouterForwarder);
257  GURL url;
258  EXPECT_CALL(*event_router.get(),
259              CallEventRouter(profile1_, kExt, kEventName, profile1_, url));
260  EXPECT_CALL(*event_router.get(),
261              CallEventRouter(profile2_, kExt, kEventName, profile2_, url));
262  BroadcastEventToExtension(event_router.get(), kExt, kEventName, url);
263}
264
265TEST_F(EventRouterForwarderTest, UnicastExtensionUIRestricted) {
266  scoped_refptr<MockEventRouterForwarder> event_router(
267      new MockEventRouterForwarder);
268  using ::testing::_;
269  GURL url;
270  EXPECT_CALL(*event_router.get(),
271              CallEventRouter(profile1_, kExt, kEventName, profile1_, url));
272  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
273      .Times(0);
274  DispatchEventToExtension(event_router.get(), kExt, kEventName, profile1_,
275                           true, url);
276}
277
278TEST_F(EventRouterForwarderTest, UnicastExtensionUIUnrestricted) {
279  scoped_refptr<MockEventRouterForwarder> event_router(
280      new MockEventRouterForwarder);
281  using ::testing::_;
282  GURL url;
283  EXPECT_CALL(*event_router.get(),
284              CallEventRouter(profile1_, kExt, kEventName, NULL, url));
285  EXPECT_CALL(*event_router.get(), CallEventRouter(profile2_, _, _, _, _))
286      .Times(0);
287  DispatchEventToExtension(event_router.get(), kExt, kEventName, profile1_,
288                           false, url);
289}
290
291}  // namespace extensions
292