Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / media / router / media_router_mojo_impl_unittest.cc
blobc55f918b9a1a2dd8ed49184729682596d3a02082
1 // Copyright 2015 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 <string>
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "chrome/browser/media/router/media_route.h"
13 #include "chrome/browser/media/router/media_router_mojo_test.h"
14 #include "chrome/browser/media/router/mock_media_router.h"
15 #include "chrome/browser/media/router/test_helper.h"
16 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/browser/process_manager.h"
20 #include "extensions/browser/process_manager_factory.h"
21 #include "media/base/gmock_callback_support.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using testing::_;
26 using testing::Eq;
27 using testing::Invoke;
28 using testing::Pointee;
29 using testing::Return;
30 using testing::ReturnRef;
31 using testing::SaveArg;
33 namespace media_router {
35 namespace {
37 const char kDescription[] = "description";
38 const char kError[] = "error";
39 const char kExtensionId[] = "extension1234";
40 const char kMessage[] = "message";
41 const char kSource[] = "source1";
42 const char kSource2[] = "source2";
43 const char kRouteId[] = "routeId";
44 const char kRouteId2[] = "routeId2";
45 const char kSink[] = "sink";
46 const char kSink2[] = "sink2";
47 const char kSinkName[] = "sinkName";
49 } // namespace
51 // Adapts Invoke(), which takes a move-only scoped_ptr parameter (not mockable)
52 // to a variant that accepts raw pointers instead (mock friendly).
53 class RouteResponseCallbackHandler {
54 public:
55 void Invoke(scoped_ptr<MediaRoute> route, const std::string& error_text) {
56 InvokeObserver(route.get(), error_text);
59 MOCK_METHOD2(InvokeObserver,
60 void(MediaRoute* route, const std::string& error_text));
63 template <typename T>
64 void StoreAndRun(T* result, const base::Closure& closure, const T& result_val) {
65 *result = result_val;
66 closure.Run();
69 class MediaRouterMojoImplTest : public MediaRouterMojoTest {
70 public:
71 MediaRouterMojoImplTest() {}
72 ~MediaRouterMojoImplTest() override {}
75 // ProcessManager with a mocked method subset, for testing extension suspend
76 // handling.
77 class TestProcessManager : public extensions::ProcessManager {
78 public:
79 explicit TestProcessManager(content::BrowserContext* context)
80 : extensions::ProcessManager(
81 context,
82 context,
83 extensions::ExtensionRegistry::Get(context)) {}
84 ~TestProcessManager() override {}
86 static KeyedService* Create(content::BrowserContext* context) {
87 return new TestProcessManager(context);
90 MOCK_METHOD1(IsEventPageSuspended, bool(const std::string& ext_id));
92 MOCK_METHOD2(WakeEventPage,
93 bool(const std::string& extension_id,
94 const base::Callback<void(bool)>& callback));
96 private:
97 DISALLOW_COPY_AND_ASSIGN(TestProcessManager);
100 // Mockable class for awaiting ProvideMediaRouter callbacks.
101 class ProvideMediaRouterHandler {
102 public:
103 MOCK_METHOD1(Invoke, void(const std::string& instance_id));
106 TEST_F(MediaRouterMojoImplTest, CreateRoute) {
107 MediaRoute expected_route(kRouteId, MediaSource(std::string(kSource)),
108 MediaSink(kSink, kSinkName), "", false);
109 interfaces::MediaRoutePtr route = interfaces::MediaRoute::New();
110 route->media_source = kSource;
111 route->media_sink = interfaces::MediaSink::New();
112 route->media_sink->sink_id = kSink;
113 route->media_sink->name = kSinkName;
114 route->media_route_id = kRouteId;
115 route->description = kDescription;
117 // Use a lambda function as an invocation target here to work around
118 // a limitation with GMock::Invoke that prevents it from using move-only types
119 // in runnable parameter lists.
120 EXPECT_CALL(mock_mojo_media_router_service_,
121 CreateRoute(mojo::String(kSource), mojo::String(kSink), _))
122 .WillOnce(Invoke(
123 [&route](const mojo::String& source, const mojo::String& sink,
124 const interfaces::MediaRouter::CreateRouteCallback& cb) {
125 cb.Run(route.Pass(), mojo::String());
126 }));
128 RouteResponseCallbackHandler handler;
129 EXPECT_CALL(handler, InvokeObserver(Pointee(Equals(expected_route)), ""));
130 router()->CreateRoute(kSource, kSink,
131 base::Bind(&RouteResponseCallbackHandler::Invoke,
132 base::Unretained(&handler)));
133 ProcessEventLoop();
136 TEST_F(MediaRouterMojoImplTest, CreateRouteFails) {
137 EXPECT_CALL(mock_mojo_media_router_service_,
138 CreateRoute(mojo::String(kSource), mojo::String(kSink), _))
139 .WillOnce(
140 Invoke([](const mojo::String& source, const mojo::String& sink,
141 const interfaces::MediaRouter::CreateRouteCallback& cb) {
142 cb.Run(interfaces::MediaRoutePtr(), mojo::String(kError));
143 }));
145 RouteResponseCallbackHandler handler;
146 EXPECT_CALL(handler, InvokeObserver(nullptr, kError));
147 router()->CreateRoute(kSource, kSink,
148 base::Bind(&RouteResponseCallbackHandler::Invoke,
149 base::Unretained(&handler)));
150 ProcessEventLoop();
153 TEST_F(MediaRouterMojoImplTest, CloseRoute) {
154 EXPECT_CALL(mock_mojo_media_router_service_,
155 CloseRoute(mojo::String(kRouteId)));
156 router()->CloseRoute(kRouteId);
157 ProcessEventLoop();
160 TEST_F(MediaRouterMojoImplTest, RegisterAndUnregisterMediaSinksObserver) {
161 MediaSource media_source(kSource);
163 MockMediaRouter mock_router;
164 EXPECT_CALL(mock_mojo_media_router_service_,
165 StartObservingMediaSinks(mojo::String(kSource))).Times(2);
166 EXPECT_CALL(mock_mojo_media_router_service_,
167 StartObservingMediaSinks(mojo::String(kSource2)));
169 MediaSinksObserver* captured_observer;
170 EXPECT_CALL(mock_router, RegisterMediaSinksObserver(_))
171 .Times(3)
172 .WillRepeatedly(SaveArg<0>(&captured_observer));
174 MockMediaSinksObserver sinks_observer(&mock_router, media_source);
175 EXPECT_EQ(&sinks_observer, captured_observer);
176 router()->RegisterMediaSinksObserver(&sinks_observer);
177 MockMediaSinksObserver extra_sinks_observer(&mock_router, media_source);
178 EXPECT_EQ(&extra_sinks_observer, captured_observer);
179 router()->RegisterMediaSinksObserver(&extra_sinks_observer);
180 MockMediaSinksObserver unrelated_sinks_observer(&mock_router,
181 MediaSource(kSource2));
182 EXPECT_EQ(&unrelated_sinks_observer, captured_observer);
183 router()->RegisterMediaSinksObserver(&unrelated_sinks_observer);
185 std::vector<MediaSink> expected_sinks;
186 expected_sinks.push_back(MediaSink(kSink, kSinkName));
187 expected_sinks.push_back(MediaSink(kSink2, kSinkName));
189 mojo::Array<interfaces::MediaSinkPtr> mojo_sinks(2);
190 mojo_sinks[0] = interfaces::MediaSink::New();
191 mojo_sinks[0]->sink_id = kSink;
192 mojo_sinks[0]->name = kSink;
193 mojo_sinks[1] = interfaces::MediaSink::New();
194 mojo_sinks[1]->sink_id = kSink2;
195 mojo_sinks[1]->name = kSink2;
197 EXPECT_CALL(sinks_observer, OnSinksReceived(SequenceEquals(expected_sinks)));
198 EXPECT_CALL(extra_sinks_observer,
199 OnSinksReceived(SequenceEquals(expected_sinks)));
200 mojo_media_router_observer_->OnSinksReceived(media_source.id(),
201 mojo_sinks.Pass());
202 ProcessEventLoop();
204 EXPECT_CALL(mock_router, UnregisterMediaSinksObserver(&sinks_observer));
205 EXPECT_CALL(mock_router, UnregisterMediaSinksObserver(&extra_sinks_observer));
206 EXPECT_CALL(mock_router,
207 UnregisterMediaSinksObserver(&unrelated_sinks_observer));
208 EXPECT_CALL(mock_mojo_media_router_service_,
209 StopObservingMediaSinks(mojo::String(kSource)));
210 EXPECT_CALL(mock_mojo_media_router_service_,
211 StopObservingMediaSinks(mojo::String(kSource2)));
212 router()->UnregisterMediaSinksObserver(&sinks_observer);
213 router()->UnregisterMediaSinksObserver(&extra_sinks_observer);
214 router()->UnregisterMediaSinksObserver(&unrelated_sinks_observer);
215 ProcessEventLoop();
218 TEST_F(MediaRouterMojoImplTest, RegisterAndUnregisterMediaRoutesObserver) {
219 MockMediaRouter mock_router;
220 EXPECT_CALL(mock_mojo_media_router_service_, StartObservingMediaRoutes())
221 .Times(2);
223 MediaRoutesObserver* observer_captured;
224 EXPECT_CALL(mock_router, RegisterMediaRoutesObserver(_))
225 .Times(2)
226 .WillRepeatedly(SaveArg<0>(&observer_captured));
227 MockMediaRoutesObserver routes_observer(&mock_router);
228 EXPECT_EQ(observer_captured, &routes_observer);
229 MockMediaRoutesObserver extra_routes_observer(&mock_router);
230 EXPECT_EQ(observer_captured, &extra_routes_observer);
231 router()->RegisterMediaRoutesObserver(&routes_observer);
232 router()->RegisterMediaRoutesObserver(&extra_routes_observer);
234 std::vector<MediaRoute> expected_routes;
235 expected_routes.push_back(MediaRoute(kRouteId, MediaSource(kSource),
236 MediaSink(kSink, kSink), kDescription,
237 false));
238 expected_routes.push_back(MediaRoute(kRouteId2, MediaSource(kSource),
239 MediaSink(kSink, kSink), kDescription,
240 false));
242 mojo::Array<interfaces::MediaRoutePtr> mojo_routes(2);
243 mojo_routes[0] = interfaces::MediaRoute::New();
244 mojo_routes[0]->media_route_id = kRouteId;
245 mojo_routes[0]->media_source = kSource;
246 mojo_routes[0]->media_sink = interfaces::MediaSink::New();
247 mojo_routes[0]->media_sink->sink_id = kSink;
248 mojo_routes[0]->media_sink->name = kSink;
249 mojo_routes[0]->description = kDescription;
250 mojo_routes[0]->is_local = false;
251 mojo_routes[1] = interfaces::MediaRoute::New();
252 mojo_routes[1]->media_route_id = kRouteId2;
253 mojo_routes[1]->media_source = kSource;
254 mojo_routes[1]->media_sink = interfaces::MediaSink::New();
255 mojo_routes[1]->media_sink->sink_id = kSink;
256 mojo_routes[1]->media_sink->name = kSink;
257 mojo_routes[1]->description = kDescription;
258 mojo_routes[1]->is_local = false;
260 EXPECT_CALL(routes_observer,
261 OnRoutesUpdated(SequenceEquals(expected_routes)));
262 EXPECT_CALL(extra_routes_observer,
263 OnRoutesUpdated(SequenceEquals(expected_routes)));
264 mojo_media_router_observer_->OnRoutesUpdated(mojo_routes.Pass());
265 ProcessEventLoop();
267 EXPECT_CALL(mock_router, UnregisterMediaRoutesObserver(&routes_observer));
268 EXPECT_CALL(mock_router,
269 UnregisterMediaRoutesObserver(&extra_routes_observer));
270 router()->UnregisterMediaRoutesObserver(&routes_observer);
271 router()->UnregisterMediaRoutesObserver(&extra_routes_observer);
272 EXPECT_CALL(mock_mojo_media_router_service_, StopObservingMediaRoutes());
273 ProcessEventLoop();
276 TEST_F(MediaRouterMojoImplTest, PostMessage) {
277 EXPECT_CALL(mock_mojo_media_router_service_,
278 PostMessage(mojo::String(kRouteId), mojo::String(kMessage)));
279 router()->PostMessage(kRouteId, kMessage);
280 ProcessEventLoop();
283 TEST_F(MediaRouterMojoImplTest, QueuedWhileAsleep) {
284 EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id()))
285 .Times(2)
286 .WillRepeatedly(Return(true));
287 EXPECT_CALL(mock_event_page_tracker_, WakeEventPage(extension_id(), _))
288 .Times(2)
289 .WillRepeatedly(Return(true));
290 router()->CloseRoute(kRouteId);
291 router()->CloseRoute(kRouteId2);
292 ProcessEventLoop();
293 EXPECT_CALL(mock_event_page_tracker_, IsEventPageSuspended(extension_id()))
294 .Times(1)
295 .WillRepeatedly(Return(false));
296 EXPECT_CALL(mock_mojo_media_router_service_,
297 CloseRoute(mojo::String(kRouteId)));
298 EXPECT_CALL(mock_mojo_media_router_service_,
299 CloseRoute(mojo::String(kRouteId2)));
300 ConnectProviderManagerService();
301 ProcessEventLoop();
304 // Temporarily disabled until the issues with extension system teardown
305 // are addressed.
306 // TODO(kmarshall): Re-enable this test. (http://crbug.com/490468)
307 TEST(MediaRouterMojoExtensionTest, DISABLED_DeferredBindingAndSuspension) {
308 base::MessageLoop message_loop(mojo::common::MessagePumpMojo::Create());
310 // Set up a mock ProcessManager instance.
311 TestingProfile profile;
312 extensions::ProcessManagerFactory::GetInstance()->SetTestingFactory(
313 &profile, &TestProcessManager::Create);
314 TestProcessManager* process_manager = static_cast<TestProcessManager*>(
315 extensions::ProcessManager::Get(&profile));
317 // Create MR and its proxy, so that it can be accessed through Mojo.
318 MediaRouterMojoImpl media_router;
319 interfaces::MediaRouterObserverPtr mojo_media_router_observer;
321 // Create a client object and its Mojo proxy.
322 testing::StrictMock<MockMojoMediaRouterService>
323 mock_mojo_media_router_service;
324 interfaces::MediaRouterPtr mojo_media_router;
326 // CloseRoute is called before *any* extension has connected.
327 // It should be queued.
328 media_router.CloseRoute(kRouteId);
330 // Construct bindings so that |media_router| delegates calls to
331 // |mojo_media_router|, which are then handled by
332 // |mock_mojo_media_router_service|.
333 scoped_ptr<mojo::Binding<interfaces::MediaRouter>> binding(
334 new mojo::Binding<interfaces::MediaRouter>(
335 &mock_mojo_media_router_service, mojo::GetProxy(&mojo_media_router)));
336 media_router.BindToMojoRequest(mojo::GetProxy(&mojo_media_router_observer),
337 kExtensionId, &profile);
339 // |mojo_media_router| signals its readiness to the MR by registering
340 // itself via ProvideMediaRouter().
341 // Now that the |media_router| and |mojo_media_router| are fully initialized,
342 // the queued CloseRoute() call should be executed.
343 ProvideMediaRouterHandler provide_handler;
344 EXPECT_CALL(provide_handler, Invoke(testing::Not("")));
345 EXPECT_CALL(*process_manager, IsEventPageSuspended(kExtensionId))
346 .WillOnce(Return(false));
347 EXPECT_CALL(mock_mojo_media_router_service,
348 CloseRoute(mojo::String(kRouteId)));
349 mojo_media_router_observer->ProvideMediaRouter(
350 mojo_media_router.Pass(), base::Bind(&ProvideMediaRouterHandler::Invoke,
351 base::Unretained(&provide_handler)));
352 message_loop.RunUntilIdle();
354 // Extension is suspended and re-awoken.
355 binding.reset();
356 media_router.BindToMojoRequest(mojo::GetProxy(&mojo_media_router_observer),
357 kExtensionId, &profile);
358 EXPECT_CALL(*process_manager, IsEventPageSuspended(kExtensionId))
359 .WillOnce(Return(true));
360 EXPECT_CALL(*process_manager, WakeEventPage(kExtensionId, _))
361 .WillOnce(testing::DoAll(media::RunCallback<1>(true), Return(true)));
362 media_router.CloseRoute(kRouteId2);
363 message_loop.RunUntilIdle();
365 // ProvideMediaRouter() is called.
366 // The queued CloseRoute(kRouteId2) call should be executed.
367 EXPECT_CALL(provide_handler, Invoke(testing::Not("")));
368 EXPECT_CALL(*process_manager, IsEventPageSuspended(kExtensionId))
369 .WillOnce(Return(false));
370 EXPECT_CALL(mock_mojo_media_router_service,
371 CloseRoute(mojo::String(kRouteId2)));
372 binding.reset(new mojo::Binding<interfaces::MediaRouter>(
373 &mock_mojo_media_router_service, mojo::GetProxy(&mojo_media_router)));
374 mojo_media_router_observer->ProvideMediaRouter(
375 mojo_media_router.Pass(), base::Bind(&ProvideMediaRouterHandler::Invoke,
376 base::Unretained(&provide_handler)));
377 message_loop.RunUntilIdle();
380 } // namespace media_router