Android Chromoting: Remove exit-fullscreen button.
[chromium-blink-merge.git] / content / browser / presentation / presentation_service_impl_unittest.cc
blob93d02f5cf0fa9b319f9d648bc760479f445b0aed
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 "base/memory/scoped_ptr.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/run_loop.h"
8 #include "content/browser/presentation/presentation_service_impl.h"
9 #include "content/public/browser/presentation_service_delegate.h"
10 #include "content/public/browser/presentation_session.h"
11 #include "content/test/test_render_frame_host.h"
12 #include "content/test/test_render_view_host.h"
13 #include "content/test/test_web_contents.h"
14 #include "mojo/public/cpp/bindings/interface_ptr.h"
15 #include "testing/gmock/include/gmock/gmock.h"
17 using ::testing::_;
18 using ::testing::Eq;
19 using ::testing::InvokeWithoutArgs;
20 using ::testing::Mock;
21 using ::testing::Return;
22 using ::testing::SaveArg;
24 namespace content {
26 class MockPresentationServiceDelegate : public PresentationServiceDelegate {
27 public:
28 MOCK_METHOD1(AddObserver,
29 void(PresentationServiceDelegate::Observer* observer));
30 MOCK_METHOD1(RemoveObserver,
31 void(PresentationServiceDelegate::Observer* observer));
32 MOCK_METHOD3(AddScreenAvailabilityListener,
33 bool(
34 int render_process_id,
35 int routing_id,
36 PresentationScreenAvailabilityListener* listener));
37 MOCK_METHOD3(RemoveScreenAvailabilityListener,
38 void(
39 int render_process_id,
40 int routing_id,
41 PresentationScreenAvailabilityListener* listener));
42 MOCK_METHOD2(Reset,
43 void(
44 int render_process_id,
45 int routing_id));
46 MOCK_METHOD4(SetDefaultPresentationUrl,
47 void(
48 int render_process_id,
49 int routing_id,
50 const std::string& default_presentation_url,
51 const std::string& default_presentation_id));
52 MOCK_METHOD6(StartSession,
53 void(
54 int render_process_id,
55 int render_frame_id,
56 const std::string& presentation_url,
57 const std::string& presentation_id,
58 const PresentationSessionSuccessCallback& success_cb,
59 const PresentationSessionErrorCallback& error_cb));
60 MOCK_METHOD6(JoinSession,
61 void(
62 int render_process_id,
63 int render_frame_id,
64 const std::string& presentation_url,
65 const std::string& presentation_id,
66 const PresentationSessionSuccessCallback& success_cb,
67 const PresentationSessionErrorCallback& error_cb));
70 class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
71 public:
72 PresentationServiceImplTest() : callback_count_(0) {}
74 void SetUp() override {
75 RenderViewHostImplTestHarness::SetUp();
77 EXPECT_CALL(mock_delegate_, AddObserver(_)).Times(1);
78 service_impl_.reset(mojo::WeakBindToProxy(
79 new PresentationServiceImpl(
80 contents()->GetMainFrame(), contents(), &mock_delegate_),
81 &service_ptr_));
84 void TearDown() override {
85 service_ptr_.reset();
87 EXPECT_CALL(mock_delegate_, RemoveObserver(Eq(service_impl_.get())))
88 .Times(1);
89 service_impl_.reset();
91 RenderViewHostImplTestHarness::TearDown();
94 void ListenForScreenAvailabilityAndWait(
95 const std::string& presentation_url,
96 const base::Callback<void(const std::string&, bool)>& callback,
97 bool delegate_success) {
98 base::RunLoop run_loop;
99 // This will call to |service_impl_| via mojo. Process the message
100 // using RunLoop.
101 // The callback shouldn't be invoked since there is no availability
102 // result yet.
103 EXPECT_CALL(mock_delegate_, AddScreenAvailabilityListener(_, _, _))
104 .WillOnce(DoAll(
105 InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
106 Return(delegate_success)));
107 service_ptr_->ListenForScreenAvailability(presentation_url, callback);
108 run_loop.Run();
110 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_));
113 void ExpectListenerDoesNotExist(const std::string& presentation_url) {
114 const auto& contexts = service_impl_->availability_contexts_;
115 auto it = contexts.find(presentation_url);
116 EXPECT_TRUE(it == contexts.end());
119 void RunLoopFor(base::TimeDelta duration) {
120 base::RunLoop run_loop;
121 base::MessageLoop::current()->PostDelayedTask(
122 FROM_HERE, run_loop.QuitClosure(), duration);
123 run_loop.Run();
126 void SaveQuitClosureAndRunLoop() {
127 base::RunLoop run_loop;
128 run_loop_quit_closure_ = run_loop.QuitClosure();
129 run_loop.Run();
130 run_loop_quit_closure_.Reset();
133 void ShouldNotBeCalled(const std::string& presentation_url, bool available) {
134 FAIL() << "Callback unexpectedly invoked with "
135 << "url = " << presentation_url << ", available = " << available;
138 void SimulateScreenAvailabilityChange(
139 const std::string& presentation_url, bool available) {
140 const auto& contexts = service_impl_->availability_contexts_;
141 auto it = contexts.find(presentation_url);
142 ASSERT_TRUE(it != contexts.end());
143 it->second->OnScreenAvailabilityChanged(available);
146 void ScreenAvailabilityChangedCallback(
147 bool expected,
148 const std::string& presentation_url,
149 bool available) {
150 ++callback_count_;
151 EXPECT_EQ(expected, available);
152 if (!run_loop_quit_closure_.is_null())
153 run_loop_quit_closure_.Run();
156 void ExpectReset() {
157 EXPECT_CALL(mock_delegate_, Reset(_, _))
158 .Times(1);
161 void ExpectCleanState() {
162 EXPECT_TRUE(service_impl_->availability_contexts_.empty());
163 EXPECT_TRUE(service_impl_->default_presentation_url_.empty());
164 EXPECT_TRUE(service_impl_->default_presentation_id_.empty());
165 EXPECT_TRUE(service_impl_->queued_start_session_requests_.empty());
168 void ExpectNewSessionMojoCallbackSuccess(
169 presentation::PresentationSessionInfoPtr info,
170 presentation::PresentationErrorPtr error) {
171 EXPECT_FALSE(info.is_null());
172 EXPECT_TRUE(error.is_null());
173 if (!run_loop_quit_closure_.is_null())
174 run_loop_quit_closure_.Run();
177 void ExpectNewSessionMojoCallbackError(
178 presentation::PresentationSessionInfoPtr info,
179 presentation::PresentationErrorPtr error) {
180 EXPECT_TRUE(info.is_null());
181 EXPECT_FALSE(error.is_null());
182 if (!run_loop_quit_closure_.is_null())
183 run_loop_quit_closure_.Run();
186 MockPresentationServiceDelegate mock_delegate_;
187 scoped_ptr<PresentationServiceImpl> service_impl_;
188 mojo::InterfacePtr<presentation::PresentationService> service_ptr_;
189 base::Closure run_loop_quit_closure_;
190 int callback_count_;
193 TEST_F(PresentationServiceImplTest, ListenForScreenAvailability) {
194 std::string presentation_url("http://fooUrl");
195 ListenForScreenAvailabilityAndWait(
196 presentation_url,
197 base::Bind(
198 &PresentationServiceImplTest::ScreenAvailabilityChangedCallback,
199 base::Unretained(this), true),
200 true);
202 // Different presentation URL.
203 ListenForScreenAvailabilityAndWait(
204 "http://barUrl",
205 base::Bind(&PresentationServiceImplTest::ShouldNotBeCalled,
206 base::Unretained(this)),
207 true);
209 // Result now available; callback will be invoked with availability result.
210 SimulateScreenAvailabilityChange(presentation_url, true);
211 SaveQuitClosureAndRunLoop();
213 EXPECT_EQ(1, callback_count_);
215 // Result updated but callback not invoked since it's been erased.
216 SimulateScreenAvailabilityChange(presentation_url, false);
218 // Register another callback which should immediately invoke callback
219 // since updated result is available.
220 service_ptr_->ListenForScreenAvailability(
221 presentation_url,
222 base::Bind(
223 &PresentationServiceImplTest::ScreenAvailabilityChangedCallback,
224 base::Unretained(this),
225 false));
226 SaveQuitClosureAndRunLoop();
227 EXPECT_EQ(2, callback_count_);
230 TEST_F(PresentationServiceImplTest, Reset) {
231 std::string presentation_url("http://fooUrl");
232 ListenForScreenAvailabilityAndWait(
233 presentation_url,
234 base::Bind(&PresentationServiceImplTest::ShouldNotBeCalled,
235 base::Unretained(this)),
236 true);
238 ExpectReset();
239 service_impl_->Reset();
240 ExpectCleanState();
242 EXPECT_EQ(0, callback_count_);
245 TEST_F(PresentationServiceImplTest, DidNavigateThisFrame) {
246 std::string presentation_url("http://fooUrl");
247 ListenForScreenAvailabilityAndWait(
248 presentation_url,
249 base::Bind(&PresentationServiceImplTest::ShouldNotBeCalled,
250 base::Unretained(this)),
251 true);
253 ExpectReset();
254 service_impl_->DidNavigateAnyFrame(
255 contents()->GetMainFrame(),
256 content::LoadCommittedDetails(),
257 content::FrameNavigateParams());
258 ExpectCleanState();
261 TEST_F(PresentationServiceImplTest, DidNavigateNotThisFrame) {
262 std::string presentation_url("http://fooUrl");
263 ListenForScreenAvailabilityAndWait(
264 presentation_url,
265 base::Bind(
266 &PresentationServiceImplTest::ScreenAvailabilityChangedCallback,
267 base::Unretained(this),
268 true),
269 true);
271 // TODO(imcheng): How to get a different RenderFrameHost?
272 service_impl_->DidNavigateAnyFrame(
273 nullptr,
274 content::LoadCommittedDetails(),
275 content::FrameNavigateParams());
277 // Availability is reported and callback is invoked since it was not
278 // removed.
279 SimulateScreenAvailabilityChange(presentation_url, true);
280 SaveQuitClosureAndRunLoop();
281 EXPECT_EQ(1, callback_count_);
284 TEST_F(PresentationServiceImplTest, ThisRenderFrameDeleted) {
285 std::string presentation_url("http://fooUrl");
286 ListenForScreenAvailabilityAndWait(
287 presentation_url,
288 base::Bind(&PresentationServiceImplTest::ShouldNotBeCalled,
289 base::Unretained(this)),
290 true);
292 ExpectReset();
293 service_impl_->RenderFrameDeleted(contents()->GetMainFrame());
294 ExpectCleanState();
297 TEST_F(PresentationServiceImplTest, NotThisRenderFrameDeleted) {
298 std::string presentation_url("http://fooUrl");
299 ListenForScreenAvailabilityAndWait(
300 presentation_url,
301 base::Bind(
302 &PresentationServiceImplTest::ScreenAvailabilityChangedCallback,
303 base::Unretained(this),
304 true),
305 true);
307 // TODO(imcheng): How to get a different RenderFrameHost?
308 service_impl_->RenderFrameDeleted(nullptr);
310 // Availability is reported and callback should be invoked since listener
311 // has not been deleted.
312 SimulateScreenAvailabilityChange(presentation_url, true);
313 SaveQuitClosureAndRunLoop();
314 EXPECT_EQ(1, callback_count_);
317 TEST_F(PresentationServiceImplTest, ListenForScreenAvailabilityTwice) {
318 std::string presentation_url("http://fooUrl");
319 ListenForScreenAvailabilityAndWait(
320 presentation_url,
321 base::Bind(
322 &PresentationServiceImplTest::ScreenAvailabilityChangedCallback,
323 base::Unretained(this),
324 false),
325 true);
327 // Second call should overwrite the callback from first call.
328 // It shouldn't result in an extra call to delegate.
329 service_ptr_->ListenForScreenAvailability(
330 presentation_url,
331 base::Bind(
332 &PresentationServiceImplTest::ScreenAvailabilityChangedCallback,
333 base::Unretained(this),
334 false));
336 // Cannot use ListenForScreenAvailabilityAndWait here since the mock delegate
337 // won't be triggered again to quit the RunLoop.
338 RunLoopFor(base::TimeDelta::FromMilliseconds(50));
340 // Result now available; callback will be invoked with availability result.
341 SimulateScreenAvailabilityChange(presentation_url, false);
342 SaveQuitClosureAndRunLoop();
344 EXPECT_EQ(2, callback_count_);
347 TEST_F(PresentationServiceImplTest, DelegateFails) {
348 std::string presentation_url("http://fooUrl");
349 ListenForScreenAvailabilityAndWait(
350 presentation_url,
351 base::Bind(&PresentationServiceImplTest::ShouldNotBeCalled,
352 base::Unretained(this)),
353 false);
355 ExpectListenerDoesNotExist(presentation_url);
358 TEST_F(PresentationServiceImplTest, SetDefaultPresentationUrl) {
359 std::string url1("http://fooUrl");
360 std::string dpu_id("dpuId");
361 EXPECT_CALL(mock_delegate_,
362 SetDefaultPresentationUrl(_, _, Eq(url1), Eq(dpu_id)))
363 .Times(1);
364 service_impl_->SetDefaultPresentationURL(url1, dpu_id);
365 EXPECT_EQ(url1, service_impl_->default_presentation_url_);
367 // Now there should be a callback registered with the DPU.
368 ListenForScreenAvailabilityAndWait(
369 url1,
370 base::Bind(
371 &PresentationServiceImplTest::ScreenAvailabilityChangedCallback,
372 base::Unretained(this), true),
373 true);
374 const auto& contexts = service_impl_->availability_contexts_;
375 auto it = contexts.find(url1);
376 ASSERT_TRUE(it != contexts.end());
377 EXPECT_TRUE(it->second->HasPendingCallbacks());
379 std::string url2("http://barUrl");
380 // Sets different DPU.
381 // Adds listener for url2 and removes listener for url1.
382 // Also, the callback from url1 is transferred to url2.
383 EXPECT_CALL(
384 mock_delegate_,
385 AddScreenAvailabilityListener(_, _, _))
386 .WillOnce(Return(true));
387 EXPECT_CALL(
388 mock_delegate_,
389 RemoveScreenAvailabilityListener(_, _, _))
390 .Times(1);
391 EXPECT_CALL(mock_delegate_,
392 SetDefaultPresentationUrl(_, _, Eq(url2), Eq(dpu_id)))
393 .Times(1);
394 service_impl_->SetDefaultPresentationURL(url2, dpu_id);
395 EXPECT_EQ(url2, service_impl_->default_presentation_url_);
397 it = contexts.find(url2);
398 ASSERT_TRUE(it != contexts.end());
399 EXPECT_TRUE(it->second->HasPendingCallbacks());
402 TEST_F(PresentationServiceImplTest, SetSameDefaultPresentationUrl) {
403 std::string url("http://fooUrl");
404 std::string dpu_id("dpuId");
405 EXPECT_CALL(mock_delegate_,
406 SetDefaultPresentationUrl(_, _, Eq(url), Eq(dpu_id)))
407 .Times(1);
408 service_impl_->SetDefaultPresentationURL(url, dpu_id);
409 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_));
410 EXPECT_EQ(url, service_impl_->default_presentation_url_);
412 // Same URL as before; no-ops.
413 service_impl_->SetDefaultPresentationURL(url, dpu_id);
414 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_));
415 EXPECT_EQ(url, service_impl_->default_presentation_url_);
418 TEST_F(PresentationServiceImplTest, ClearDefaultPresentationUrl) {
419 std::string url("http://fooUrl");
420 std::string dpu_id("dpuId");
421 EXPECT_CALL(mock_delegate_,
422 SetDefaultPresentationUrl(_, _, Eq(url), Eq(dpu_id)))
423 .Times(1);
424 service_impl_->SetDefaultPresentationURL(url, dpu_id);
425 EXPECT_EQ(url, service_impl_->default_presentation_url_);
427 // Now there should be a callback registered with the DPU.
428 ListenForScreenAvailabilityAndWait(
429 url,
430 base::Bind(
431 &PresentationServiceImplTest::ScreenAvailabilityChangedCallback,
432 base::Unretained(this), true),
433 true);
435 const auto& contexts = service_impl_->availability_contexts_;
436 auto it = contexts.find(url);
437 ASSERT_TRUE(it != contexts.end());
438 EXPECT_TRUE(it->second->HasPendingCallbacks());
440 // Clears the default presentation URL. Transfers the listener from url to
441 // "1-UA" mode.
442 EXPECT_CALL(
443 mock_delegate_,
444 AddScreenAvailabilityListener(_, _, _))
445 .WillOnce(Return(true));
446 EXPECT_CALL(
447 mock_delegate_,
448 RemoveScreenAvailabilityListener(_, _, _))
449 .Times(1);
450 EXPECT_CALL(
451 mock_delegate_,
452 SetDefaultPresentationUrl(_, _, Eq(std::string()), Eq(std::string())))
453 .Times(1);
454 service_impl_->SetDefaultPresentationURL(std::string(), std::string());
455 EXPECT_TRUE(service_impl_->default_presentation_url_.empty());
457 it = contexts.find(url);
458 ASSERT_TRUE(it == contexts.end());
461 TEST_F(PresentationServiceImplTest, StartSessionSuccess) {
462 std::string presentation_url("http://fooUrl");
463 std::string presentation_id("presentationId");
464 service_ptr_->StartSession(
465 presentation_url,
466 presentation_id,
467 base::Bind(
468 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackSuccess,
469 base::Unretained(this)));
470 base::RunLoop run_loop;
471 base::Callback<void(const PresentationSessionInfo&)> success_cb;
472 EXPECT_CALL(mock_delegate_, StartSession(
473 _, _, Eq(presentation_url), Eq(presentation_id), _, _))
474 .WillOnce(DoAll(
475 InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
476 SaveArg<4>(&success_cb)));
477 run_loop.Run();
478 success_cb.Run(PresentationSessionInfo(presentation_url, presentation_id));
479 SaveQuitClosureAndRunLoop();
482 TEST_F(PresentationServiceImplTest, StartSessionError) {
483 std::string presentation_url("http://fooUrl");
484 std::string presentation_id("presentationId");
485 service_ptr_->StartSession(
486 presentation_url,
487 presentation_id,
488 base::Bind(
489 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError,
490 base::Unretained(this)));
491 base::RunLoop run_loop;
492 base::Callback<void(const PresentationError&)> error_cb;
493 EXPECT_CALL(mock_delegate_, StartSession(
494 _, _, Eq(presentation_url), Eq(presentation_id), _, _))
495 .WillOnce(DoAll(
496 InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
497 SaveArg<5>(&error_cb)));
498 run_loop.Run();
499 error_cb.Run(PresentationError(PRESENTATION_ERROR_UNKNOWN, "Error message"));
500 SaveQuitClosureAndRunLoop();
503 TEST_F(PresentationServiceImplTest, JoinSessionSuccess) {
504 std::string presentation_url("http://fooUrl");
505 std::string presentation_id("presentationId");
506 service_ptr_->JoinSession(
507 presentation_url,
508 presentation_id,
509 base::Bind(
510 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackSuccess,
511 base::Unretained(this)));
512 base::RunLoop run_loop;
513 base::Callback<void(const PresentationSessionInfo&)> success_cb;
514 EXPECT_CALL(mock_delegate_, JoinSession(
515 _, _, Eq(presentation_url), Eq(presentation_id), _, _))
516 .WillOnce(DoAll(
517 InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
518 SaveArg<4>(&success_cb)));
519 run_loop.Run();
520 success_cb.Run(PresentationSessionInfo(presentation_url, presentation_id));
521 SaveQuitClosureAndRunLoop();
524 TEST_F(PresentationServiceImplTest, JoinSessionError) {
525 std::string presentation_url("http://fooUrl");
526 std::string presentation_id("presentationId");
527 service_ptr_->JoinSession(
528 presentation_url,
529 presentation_id,
530 base::Bind(
531 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError,
532 base::Unretained(this)));
533 base::RunLoop run_loop;
534 base::Callback<void(const PresentationError&)> error_cb;
535 EXPECT_CALL(mock_delegate_, JoinSession(
536 _, _, Eq(presentation_url), Eq(presentation_id), _, _))
537 .WillOnce(DoAll(
538 InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
539 SaveArg<5>(&error_cb)));
540 run_loop.Run();
541 error_cb.Run(PresentationError(PRESENTATION_ERROR_UNKNOWN, "Error message"));
542 SaveQuitClosureAndRunLoop();
545 TEST_F(PresentationServiceImplTest, StartSessionInProgress) {
546 std::string presentation_url1("http://fooUrl");
547 std::string presentation_id1("presentationId1");
548 std::string presentation_url2("http://barUrl");
549 std::string presentation_id2("presentationId2");
550 service_ptr_->StartSession(
551 presentation_url1,
552 presentation_id1,
553 base::Bind(
554 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackSuccess,
555 base::Unretained(this)));
556 service_ptr_->StartSession(
557 presentation_url2,
558 presentation_id2,
559 base::Bind(
560 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackSuccess,
561 base::Unretained(this)));
562 base::RunLoop run_loop;
563 base::Callback<void(const PresentationSessionInfo&)> success_cb;
564 EXPECT_CALL(mock_delegate_, StartSession(
565 _, _, Eq(presentation_url1), Eq(presentation_id1), _, _))
566 .WillOnce(DoAll(
567 InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
568 SaveArg<4>(&success_cb)));
569 run_loop.Run();
571 // Running the callback means the first request is done. It should now
572 // move on to the queued request.
573 EXPECT_CALL(mock_delegate_, StartSession(
574 _, _, Eq(presentation_url2), Eq(presentation_id2), _, _))
575 .Times(1);
576 success_cb.Run(PresentationSessionInfo(presentation_url1, presentation_id1));
577 SaveQuitClosureAndRunLoop();
580 } // namespace content