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/location.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/run_loop.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/test/test_timeouts.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "content/browser/presentation/presentation_service_impl.h"
12 #include "content/public/browser/presentation_service_delegate.h"
13 #include "content/public/browser/presentation_session.h"
14 #include "content/public/common/presentation_constants.h"
15 #include "content/test/test_render_frame_host.h"
16 #include "content/test/test_render_view_host.h"
17 #include "content/test/test_web_contents.h"
18 #include "mojo/public/cpp/bindings/interface_ptr.h"
19 #include "testing/gmock/include/gmock/gmock.h"
23 using ::testing::InvokeWithoutArgs
;
24 using ::testing::Mock
;
25 using ::testing::Return
;
26 using ::testing::SaveArg
;
32 // Matches mojo structs.
33 MATCHER_P(Equals
, expected
, "") {
34 return expected
.Equals(arg
);
37 const char kPresentationId
[] = "presentationId";
38 const char kPresentationUrl
[] = "http://foo.com/index.html";
40 bool ArePresentationSessionsEqual(
41 const presentation::PresentationSessionInfo
& expected
,
42 const presentation::PresentationSessionInfo
& actual
) {
43 return expected
.url
== actual
.url
&& expected
.id
== actual
.id
;
46 bool ArePresentationSessionMessagesEqual(
47 const presentation::SessionMessage
* expected
,
48 const presentation::SessionMessage
* actual
) {
49 return expected
->presentation_url
== actual
->presentation_url
&&
50 expected
->presentation_id
== actual
->presentation_id
&&
51 expected
->type
== actual
->type
&&
52 expected
->message
== actual
->message
&&
53 expected
->data
.Equals(actual
->data
);
57 presentation::PresentationSessionInfoPtr info
,
58 presentation::PresentationErrorPtr error
) {
63 class MockPresentationServiceDelegate
: public PresentationServiceDelegate
{
65 MOCK_METHOD3(AddObserver
,
66 void(int render_process_id
,
68 PresentationServiceDelegate::Observer
* observer
));
69 MOCK_METHOD2(RemoveObserver
,
70 void(int render_process_id
, int render_frame_id
));
71 MOCK_METHOD3(AddScreenAvailabilityListener
,
73 int render_process_id
,
75 PresentationScreenAvailabilityListener
* listener
));
76 MOCK_METHOD3(RemoveScreenAvailabilityListener
,
78 int render_process_id
,
80 PresentationScreenAvailabilityListener
* listener
));
83 int render_process_id
,
85 MOCK_METHOD3(SetDefaultPresentationUrl
,
87 int render_process_id
,
89 const std::string
& default_presentation_url
));
90 MOCK_METHOD5(StartSession
,
92 int render_process_id
,
94 const std::string
& presentation_url
,
95 const PresentationSessionSuccessCallback
& success_cb
,
96 const PresentationSessionErrorCallback
& error_cb
));
97 MOCK_METHOD6(JoinSession
,
99 int render_process_id
,
101 const std::string
& presentation_url
,
102 const std::string
& presentation_id
,
103 const PresentationSessionSuccessCallback
& success_cb
,
104 const PresentationSessionErrorCallback
& error_cb
));
105 MOCK_METHOD3(CloseSession
,
106 void(int render_process_id
,
108 const std::string
& presentation_id
));
109 MOCK_METHOD3(ListenForSessionMessages
,
111 int render_process_id
,
113 const PresentationSessionMessageCallback
& message_cb
));
114 MOCK_METHOD4(SendMessageRawPtr
,
116 int render_process_id
,
118 PresentationSessionMessage
* message_request
,
119 const SendMessageCallback
& send_message_cb
));
120 void SendMessage(int render_process_id
,
122 scoped_ptr
<PresentationSessionMessage
> message_request
,
123 const SendMessageCallback
& send_message_cb
) override
{
127 message_request
.release(),
131 ListenForSessionStateChange
,
132 void(int render_process_id
,
134 const content::SessionStateChangedCallback
& state_changed_cb
));
137 class MockPresentationServiceClient
:
138 public presentation::PresentationServiceClient
{
140 MOCK_METHOD1(OnScreenAvailabilityUpdated
, void(bool available
));
141 void OnSessionStateChanged(
142 presentation::PresentationSessionInfoPtr session_info
,
143 presentation::PresentationSessionState new_state
) override
{
144 OnSessionStateChanged(*session_info
, new_state
);
146 MOCK_METHOD2(OnSessionStateChanged
,
147 void(const presentation::PresentationSessionInfo
& session_info
,
148 presentation::PresentationSessionState new_state
));
149 void OnScreenAvailabilityNotSupported() override
{
154 class PresentationServiceImplTest
: public RenderViewHostImplTestHarness
{
156 PresentationServiceImplTest() : default_session_started_count_(0) {}
158 void SetUp() override
{
159 RenderViewHostImplTestHarness::SetUp();
161 auto request
= mojo::GetProxy(&service_ptr_
);
162 EXPECT_CALL(mock_delegate_
, AddObserver(_
, _
, _
)).Times(1);
163 service_impl_
.reset(new PresentationServiceImpl(
164 contents()->GetMainFrame(), contents(), &mock_delegate_
));
165 service_impl_
->Bind(request
.Pass());
167 presentation::PresentationServiceClientPtr client_ptr
;
168 client_binding_
.reset(
169 new mojo::Binding
<presentation::PresentationServiceClient
>(
170 &mock_client_
, mojo::GetProxy(&client_ptr
)));
171 service_impl_
->SetClient(client_ptr
.Pass());
174 void TearDown() override
{
175 service_ptr_
.reset();
176 if (service_impl_
.get()) {
177 EXPECT_CALL(mock_delegate_
, RemoveObserver(_
, _
)).Times(1);
178 service_impl_
.reset();
180 RenderViewHostImplTestHarness::TearDown();
183 void ListenForScreenAvailabilityAndWait(bool delegate_success
) {
184 base::RunLoop run_loop
;
185 // This will call to |service_impl_| via mojo. Process the message
187 // The callback shouldn't be invoked since there is no availability
189 EXPECT_CALL(mock_delegate_
, AddScreenAvailabilityListener(_
, _
, _
))
191 InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
192 Return(delegate_success
)));
193 service_ptr_
->ListenForScreenAvailability();
196 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_
));
199 void RunLoopFor(base::TimeDelta duration
) {
200 base::RunLoop run_loop
;
201 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
202 FROM_HERE
, run_loop
.QuitClosure(), duration
);
206 void SaveQuitClosureAndRunLoop() {
207 base::RunLoop run_loop
;
208 run_loop_quit_closure_
= run_loop
.QuitClosure();
210 run_loop_quit_closure_
.Reset();
213 void SimulateScreenAvailabilityChangeAndWait(bool available
) {
214 auto* listener
= service_impl_
->screen_availability_listener_
.get();
215 ASSERT_TRUE(listener
);
217 base::RunLoop run_loop
;
218 EXPECT_CALL(mock_client_
, OnScreenAvailabilityUpdated(available
))
219 .WillOnce(InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
220 listener
->OnScreenAvailabilityChanged(available
);
225 EXPECT_CALL(mock_delegate_
, Reset(_
, _
)).Times(1);
228 void ExpectCleanState() {
229 EXPECT_TRUE(service_impl_
->default_presentation_url_
.empty());
230 EXPECT_FALSE(service_impl_
->screen_availability_listener_
.get());
231 EXPECT_FALSE(service_impl_
->default_session_start_context_
.get());
232 EXPECT_FALSE(service_impl_
->on_session_messages_callback_
.get());
235 void ExpectNewSessionMojoCallbackSuccess(
236 presentation::PresentationSessionInfoPtr info
,
237 presentation::PresentationErrorPtr error
) {
238 EXPECT_FALSE(info
.is_null());
239 EXPECT_TRUE(error
.is_null());
240 if (!run_loop_quit_closure_
.is_null())
241 run_loop_quit_closure_
.Run();
244 void ExpectNewSessionMojoCallbackError(
245 presentation::PresentationSessionInfoPtr info
,
246 presentation::PresentationErrorPtr error
) {
247 EXPECT_TRUE(info
.is_null());
248 EXPECT_FALSE(error
.is_null());
249 if (!run_loop_quit_closure_
.is_null())
250 run_loop_quit_closure_
.Run();
253 void ExpectDefaultSessionStarted(
254 const presentation::PresentationSessionInfo
& expected_session
,
255 presentation::PresentationSessionInfoPtr actual_session
) {
256 ASSERT_TRUE(!actual_session
.is_null());
257 EXPECT_TRUE(ArePresentationSessionsEqual(
258 expected_session
, *actual_session
));
259 ++default_session_started_count_
;
260 if (!run_loop_quit_closure_
.is_null())
261 run_loop_quit_closure_
.Run();
264 void ExpectDefaultSessionNull(
265 presentation::PresentationSessionInfoPtr actual_session
) {
266 EXPECT_TRUE(actual_session
.is_null());
267 ++default_session_started_count_
;
268 if (!run_loop_quit_closure_
.is_null())
269 run_loop_quit_closure_
.Run();
272 void ExpectSessionMessages(
273 mojo::Array
<presentation::SessionMessagePtr
> actual_msgs
) {
274 EXPECT_TRUE(actual_msgs
.size() == expected_msgs_
.size());
275 for (size_t i
= 0; i
< actual_msgs
.size(); ++i
) {
276 EXPECT_TRUE(ArePresentationSessionMessagesEqual(expected_msgs_
[i
].get(),
277 actual_msgs
[i
].get()));
279 if (!run_loop_quit_closure_
.is_null())
280 run_loop_quit_closure_
.Run();
283 void ExpectSendMessageMojoCallback(bool success
) {
284 EXPECT_TRUE(success
);
285 EXPECT_FALSE(service_impl_
->send_message_callback_
);
286 if (!run_loop_quit_closure_
.is_null())
287 run_loop_quit_closure_
.Run();
290 void RunListenForSessionMessages(std::string
& text_msg
,
291 std::vector
<uint8_t>& binary_data
) {
294 expected_msgs_
= mojo::Array
<presentation::SessionMessagePtr
>::New(2);
295 expected_msgs_
[0] = presentation::SessionMessage::New();
296 expected_msgs_
[0]->presentation_url
= kPresentationUrl
;
297 expected_msgs_
[0]->presentation_id
= kPresentationId
;
298 expected_msgs_
[0]->type
=
299 presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_TEXT
;
300 expected_msgs_
[0]->message
= text_msg
;
301 expected_msgs_
[1] = presentation::SessionMessage::New();
302 expected_msgs_
[1]->presentation_url
= kPresentationUrl
;
303 expected_msgs_
[1]->presentation_id
= kPresentationId
;
304 expected_msgs_
[1]->type
= presentation::PresentationMessageType::
305 PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER
;
306 expected_msgs_
[1]->data
= mojo::Array
<uint8_t>::From(binary_data
);
308 service_ptr_
->ListenForSessionMessages(
309 base::Bind(&PresentationServiceImplTest::ExpectSessionMessages
,
310 base::Unretained(this)));
312 base::RunLoop run_loop
;
313 base::Callback
<void(scoped_ptr
<ScopedVector
<PresentationSessionMessage
>>)>
315 EXPECT_CALL(mock_delegate_
, ListenForSessionMessages(_
, _
, _
))
316 .WillOnce(DoAll(InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
317 SaveArg
<2>(&message_cb
)));
320 scoped_ptr
<ScopedVector
<PresentationSessionMessage
>> messages(
321 new ScopedVector
<PresentationSessionMessage
>());
323 content::PresentationSessionMessage::CreateStringMessage(
324 kPresentationUrl
, kPresentationId
,
325 scoped_ptr
<std::string
>(new std::string(text_msg
))));
327 content::PresentationSessionMessage::CreateArrayBufferMessage(
328 kPresentationUrl
, kPresentationId
,
329 scoped_ptr
<std::vector
<uint8_t>>(
330 new std::vector
<uint8_t>(binary_data
))));
331 message_cb
.Run(messages
.Pass());
332 SaveQuitClosureAndRunLoop();
335 MockPresentationServiceDelegate mock_delegate_
;
337 scoped_ptr
<PresentationServiceImpl
> service_impl_
;
338 mojo::InterfacePtr
<presentation::PresentationService
> service_ptr_
;
340 MockPresentationServiceClient mock_client_
;
341 scoped_ptr
<mojo::Binding
<presentation::PresentationServiceClient
>>
344 base::Closure run_loop_quit_closure_
;
345 int default_session_started_count_
;
346 mojo::Array
<presentation::SessionMessagePtr
> expected_msgs_
;
349 TEST_F(PresentationServiceImplTest
, ListenForScreenAvailability
) {
350 ListenForScreenAvailabilityAndWait(true);
352 SimulateScreenAvailabilityChangeAndWait(true);
353 SimulateScreenAvailabilityChangeAndWait(false);
354 SimulateScreenAvailabilityChangeAndWait(true);
357 TEST_F(PresentationServiceImplTest
, Reset
) {
358 ListenForScreenAvailabilityAndWait(true);
361 service_impl_
->Reset();
365 TEST_F(PresentationServiceImplTest
, DidNavigateThisFrame
) {
366 ListenForScreenAvailabilityAndWait(true);
369 service_impl_
->DidNavigateAnyFrame(
370 contents()->GetMainFrame(),
371 content::LoadCommittedDetails(),
372 content::FrameNavigateParams());
376 TEST_F(PresentationServiceImplTest
, DidNavigateOtherFrame
) {
377 ListenForScreenAvailabilityAndWait(true);
379 // TODO(imcheng): How to get a different RenderFrameHost?
380 service_impl_
->DidNavigateAnyFrame(
382 content::LoadCommittedDetails(),
383 content::FrameNavigateParams());
385 // Availability is reported and callback is invoked since it was not
387 SimulateScreenAvailabilityChangeAndWait(true);
390 TEST_F(PresentationServiceImplTest
, ThisRenderFrameDeleted
) {
391 ListenForScreenAvailabilityAndWait(true);
395 // Since the frame matched the service, |service_impl_| will be deleted.
396 PresentationServiceImpl
* service
= service_impl_
.release();
397 EXPECT_CALL(mock_delegate_
, RemoveObserver(_
, _
)).Times(1);
398 service
->RenderFrameDeleted(contents()->GetMainFrame());
401 TEST_F(PresentationServiceImplTest
, OtherRenderFrameDeleted
) {
402 ListenForScreenAvailabilityAndWait(true);
404 // TODO(imcheng): How to get a different RenderFrameHost?
405 service_impl_
->RenderFrameDeleted(nullptr);
407 // Availability is reported and callback should be invoked since listener
408 // has not been deleted.
409 SimulateScreenAvailabilityChangeAndWait(true);
412 TEST_F(PresentationServiceImplTest
, DelegateFails
) {
413 ListenForScreenAvailabilityAndWait(false);
414 ASSERT_FALSE(service_impl_
->screen_availability_listener_
.get());
417 TEST_F(PresentationServiceImplTest
, SetDefaultPresentationUrl
) {
418 std::string
url1("http://fooUrl");
419 EXPECT_CALL(mock_delegate_
,
420 SetDefaultPresentationUrl(_
, _
, Eq(url1
)))
422 service_impl_
->SetDefaultPresentationURL(url1
);
423 EXPECT_EQ(url1
, service_impl_
->default_presentation_url_
);
425 // Now there should be a listener for DPU = |url1|.
426 ListenForScreenAvailabilityAndWait(true);
427 auto* listener
= service_impl_
->screen_availability_listener_
.get();
428 ASSERT_TRUE(listener
);
429 EXPECT_EQ(url1
, listener
->GetPresentationUrl());
431 std::string
url2("http://barUrl");
432 // Sets different DPU.
433 // Adds listener for url2 and removes listener for url1.
436 AddScreenAvailabilityListener(_
, _
, _
))
437 .WillOnce(Return(true));
440 RemoveScreenAvailabilityListener(_
, _
, _
))
442 EXPECT_CALL(mock_delegate_
,
443 SetDefaultPresentationUrl(_
, _
, Eq(url2
)))
445 service_impl_
->SetDefaultPresentationURL(url2
);
446 EXPECT_EQ(url2
, service_impl_
->default_presentation_url_
);
448 listener
= service_impl_
->screen_availability_listener_
.get();
449 ASSERT_TRUE(listener
);
450 EXPECT_EQ(url2
, listener
->GetPresentationUrl());
453 TEST_F(PresentationServiceImplTest
, SetSameDefaultPresentationUrl
) {
454 EXPECT_CALL(mock_delegate_
,
455 SetDefaultPresentationUrl(_
, _
, Eq(kPresentationUrl
)))
457 service_impl_
->SetDefaultPresentationURL(kPresentationUrl
);
458 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_
));
459 EXPECT_EQ(kPresentationUrl
, service_impl_
->default_presentation_url_
);
461 // Same URL as before; no-ops.
462 service_impl_
->SetDefaultPresentationURL(kPresentationUrl
);
463 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_
));
464 EXPECT_EQ(kPresentationUrl
, service_impl_
->default_presentation_url_
);
467 TEST_F(PresentationServiceImplTest
, StartSessionSuccess
) {
468 service_ptr_
->StartSession(
471 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackSuccess
,
472 base::Unretained(this)));
473 base::RunLoop run_loop
;
474 base::Callback
<void(const PresentationSessionInfo
&)> success_cb
;
475 EXPECT_CALL(mock_delegate_
, StartSession(_
, _
, Eq(kPresentationUrl
), _
, _
))
477 InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
478 SaveArg
<3>(&success_cb
)));
480 success_cb
.Run(PresentationSessionInfo(kPresentationUrl
, kPresentationId
));
481 SaveQuitClosureAndRunLoop();
484 TEST_F(PresentationServiceImplTest
, StartSessionError
) {
485 service_ptr_
->StartSession(
488 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError
,
489 base::Unretained(this)));
490 base::RunLoop run_loop
;
491 base::Callback
<void(const PresentationError
&)> error_cb
;
492 EXPECT_CALL(mock_delegate_
, StartSession(_
, _
, Eq(kPresentationUrl
), _
, _
))
494 InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
495 SaveArg
<4>(&error_cb
)));
497 error_cb
.Run(PresentationError(PRESENTATION_ERROR_UNKNOWN
, "Error message"));
498 SaveQuitClosureAndRunLoop();
501 TEST_F(PresentationServiceImplTest
, JoinSessionSuccess
) {
502 service_ptr_
->JoinSession(
506 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackSuccess
,
507 base::Unretained(this)));
508 base::RunLoop run_loop
;
509 base::Callback
<void(const PresentationSessionInfo
&)> success_cb
;
510 EXPECT_CALL(mock_delegate_
, JoinSession(
511 _
, _
, Eq(kPresentationUrl
), Eq(kPresentationId
), _
, _
))
513 InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
514 SaveArg
<4>(&success_cb
)));
516 success_cb
.Run(PresentationSessionInfo(kPresentationUrl
, kPresentationId
));
517 SaveQuitClosureAndRunLoop();
520 TEST_F(PresentationServiceImplTest
, JoinSessionError
) {
521 service_ptr_
->JoinSession(
525 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError
,
526 base::Unretained(this)));
527 base::RunLoop run_loop
;
528 base::Callback
<void(const PresentationError
&)> error_cb
;
529 EXPECT_CALL(mock_delegate_
, JoinSession(
530 _
, _
, Eq(kPresentationUrl
), Eq(kPresentationId
), _
, _
))
532 InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
533 SaveArg
<5>(&error_cb
)));
535 error_cb
.Run(PresentationError(PRESENTATION_ERROR_UNKNOWN
, "Error message"));
536 SaveQuitClosureAndRunLoop();
539 TEST_F(PresentationServiceImplTest
, CloseSession
) {
540 service_ptr_
->CloseSession(kPresentationUrl
, kPresentationId
);
541 base::RunLoop run_loop
;
542 EXPECT_CALL(mock_delegate_
, CloseSession(_
, _
, Eq(kPresentationId
)))
543 .WillOnce(InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
547 TEST_F(PresentationServiceImplTest
, ListenForSessionMessages
) {
548 std::string
text_msg("123");
549 std::vector
<uint8_t> binary_data(3, '\1');
550 RunListenForSessionMessages(text_msg
, binary_data
);
553 TEST_F(PresentationServiceImplTest
, ListenForSessionMessagesWithEmptyMsg
) {
554 std::string
text_msg("");
555 std::vector
<uint8_t> binary_data
{};
556 RunListenForSessionMessages(text_msg
, binary_data
);
559 TEST_F(PresentationServiceImplTest
, ReceiveSessionMessagesAfterReset
) {
560 std::string
text_msg("123");
561 expected_msgs_
= mojo::Array
<presentation::SessionMessagePtr
>();
562 service_ptr_
->ListenForSessionMessages(
563 base::Bind(&PresentationServiceImplTest::ExpectSessionMessages
,
564 base::Unretained(this)));
566 base::RunLoop run_loop
;
567 base::Callback
<void(scoped_ptr
<ScopedVector
<PresentationSessionMessage
>>)>
569 EXPECT_CALL(mock_delegate_
, ListenForSessionMessages(_
, _
, _
))
570 .WillOnce(DoAll(InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
571 SaveArg
<2>(&message_cb
)));
574 scoped_ptr
<ScopedVector
<PresentationSessionMessage
>> messages(
575 new ScopedVector
<PresentationSessionMessage
>());
576 messages
->push_back(content::PresentationSessionMessage::CreateStringMessage(
577 kPresentationUrl
, kPresentationId
,
578 scoped_ptr
<std::string
>(new std::string(text_msg
))));
580 service_impl_
->Reset();
581 message_cb
.Run(messages
.Pass());
582 SaveQuitClosureAndRunLoop();
585 TEST_F(PresentationServiceImplTest
, StartSessionInProgress
) {
586 std::string
presentation_url1("http://fooUrl");
587 std::string
presentation_url2("http://barUrl");
588 service_ptr_
->StartSession(presentation_url1
,
589 base::Bind(&DoNothing
));
590 // This request should fail immediately, since there is already a StartSession
592 service_ptr_
->StartSession(
595 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError
,
596 base::Unretained(this)));
597 SaveQuitClosureAndRunLoop();
600 TEST_F(PresentationServiceImplTest
, ListenForDefaultSessionStart
) {
601 presentation::PresentationSessionInfo expected_session
;
602 expected_session
.url
= kPresentationUrl
;
603 expected_session
.id
= kPresentationId
;
604 service_ptr_
->ListenForDefaultSessionStart(
605 base::Bind(&PresentationServiceImplTest::ExpectDefaultSessionStarted
,
606 base::Unretained(this),
608 RunLoopFor(base::TimeDelta::FromMilliseconds(50));
609 service_impl_
->OnDefaultPresentationStarted(
610 content::PresentationSessionInfo(kPresentationUrl
, kPresentationId
));
611 SaveQuitClosureAndRunLoop();
612 EXPECT_EQ(1, default_session_started_count_
);
615 TEST_F(PresentationServiceImplTest
, ListenForDefaultSessionStartAfterSet
) {
616 // Note that the callback will only pick up presentation_url2/id2 since
617 // ListenForDefaultSessionStart wasn't called yet when the DPU was still
618 // presentation_url1.
619 std::string
presentation_url1("http://fooUrl1");
620 std::string
presentation_id1("presentationId1");
621 std::string
presentation_url2("http://fooUrl2");
622 std::string
presentation_id2("presentationId2");
623 service_impl_
->OnDefaultPresentationStarted(
624 content::PresentationSessionInfo(presentation_url1
, presentation_id1
));
626 presentation::PresentationSessionInfo expected_session
;
627 expected_session
.url
= presentation_url2
;
628 expected_session
.id
= presentation_id2
;
629 service_ptr_
->ListenForDefaultSessionStart(
630 base::Bind(&PresentationServiceImplTest::ExpectDefaultSessionStarted
,
631 base::Unretained(this),
633 RunLoopFor(base::TimeDelta::FromMilliseconds(50));
634 service_impl_
->OnDefaultPresentationStarted(
635 content::PresentationSessionInfo(presentation_url2
, presentation_id2
));
636 SaveQuitClosureAndRunLoop();
637 EXPECT_EQ(1, default_session_started_count_
);
640 TEST_F(PresentationServiceImplTest
, DefaultSessionStartReset
) {
641 service_ptr_
->ListenForDefaultSessionStart(
642 base::Bind(&PresentationServiceImplTest::ExpectDefaultSessionNull
,
643 base::Unretained(this)));
644 RunLoopFor(TestTimeouts::tiny_timeout());
647 service_impl_
->Reset();
649 SaveQuitClosureAndRunLoop();
650 EXPECT_EQ(1, default_session_started_count_
);
653 TEST_F(PresentationServiceImplTest
, SendStringMessage
) {
654 std::string
message("Test presentation session message");
656 presentation::SessionMessagePtr
message_request(
657 presentation::SessionMessage::New());
658 message_request
->presentation_url
= kPresentationUrl
;
659 message_request
->presentation_id
= kPresentationId
;
660 message_request
->type
= presentation::PresentationMessageType::
661 PRESENTATION_MESSAGE_TYPE_TEXT
;
662 message_request
->message
= message
;
663 service_ptr_
->SendSessionMessage(
664 message_request
.Pass(),
666 &PresentationServiceImplTest::ExpectSendMessageMojoCallback
,
667 base::Unretained(this)));
669 base::RunLoop run_loop
;
670 base::Callback
<void(bool)> send_message_cb
;
671 PresentationSessionMessage
* test_message
= nullptr;
672 EXPECT_CALL(mock_delegate_
, SendMessageRawPtr(
675 InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
676 SaveArg
<2>(&test_message
),
677 SaveArg
<3>(&send_message_cb
)));
680 EXPECT_TRUE(test_message
);
681 EXPECT_EQ(kPresentationUrl
, test_message
->presentation_url
);
682 EXPECT_EQ(kPresentationId
, test_message
->presentation_id
);
683 EXPECT_FALSE(test_message
->is_binary());
684 EXPECT_TRUE(test_message
->message
.get()->size() <=
685 kMaxPresentationSessionMessageSize
);
686 EXPECT_EQ(message
, *(test_message
->message
.get()));
687 EXPECT_FALSE(test_message
->data
);
689 send_message_cb
.Run(true);
690 SaveQuitClosureAndRunLoop();
693 TEST_F(PresentationServiceImplTest
, SendArrayBuffer
) {
694 // Test Array buffer data.
695 const uint8 buffer
[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
696 std::vector
<uint8
> data
;
697 data
.assign(buffer
, buffer
+ sizeof(buffer
));
699 presentation::SessionMessagePtr
message_request(
700 presentation::SessionMessage::New());
701 message_request
->presentation_url
= kPresentationUrl
;
702 message_request
->presentation_id
= kPresentationId
;
703 message_request
->type
= presentation::PresentationMessageType::
704 PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER
;
705 message_request
->data
= mojo::Array
<uint8
>::From(data
);
706 service_ptr_
->SendSessionMessage(
707 message_request
.Pass(),
709 &PresentationServiceImplTest::ExpectSendMessageMojoCallback
,
710 base::Unretained(this)));
712 base::RunLoop run_loop
;
713 base::Callback
<void(bool)> send_message_cb
;
714 PresentationSessionMessage
* test_message
= nullptr;
715 EXPECT_CALL(mock_delegate_
, SendMessageRawPtr(
718 InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
719 SaveArg
<2>(&test_message
),
720 SaveArg
<3>(&send_message_cb
)));
723 EXPECT_TRUE(test_message
);
724 EXPECT_EQ(kPresentationUrl
, test_message
->presentation_url
);
725 EXPECT_EQ(kPresentationId
, test_message
->presentation_id
);
726 EXPECT_TRUE(test_message
->is_binary());
727 EXPECT_EQ(PresentationMessageType::ARRAY_BUFFER
, test_message
->type
);
728 EXPECT_FALSE(test_message
->message
);
729 EXPECT_EQ(data
.size(), test_message
->data
.get()->size());
730 EXPECT_TRUE(test_message
->data
.get()->size() <=
731 kMaxPresentationSessionMessageSize
);
732 EXPECT_EQ(0, memcmp(buffer
, &(*test_message
->data
.get())[0], sizeof(buffer
)));
734 send_message_cb
.Run(true);
735 SaveQuitClosureAndRunLoop();
738 TEST_F(PresentationServiceImplTest
, SendArrayBufferWithExceedingLimit
) {
739 // Create buffer with size exceeding the limit.
740 // Use same size as in content::kMaxPresentationSessionMessageSize.
741 const size_t kMaxBufferSizeInBytes
= 64 * 1024; // 64 KB.
742 uint8 buffer
[kMaxBufferSizeInBytes
+1];
743 memset(buffer
, 0, kMaxBufferSizeInBytes
+1);
744 std::vector
<uint8
> data
;
745 data
.assign(buffer
, buffer
+ sizeof(buffer
));
747 presentation::SessionMessagePtr
message_request(
748 presentation::SessionMessage::New());
749 message_request
->presentation_url
= kPresentationUrl
;
750 message_request
->presentation_id
= kPresentationId
;
751 message_request
->type
= presentation::PresentationMessageType::
752 PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER
;
753 message_request
->data
= mojo::Array
<uint8
>::From(data
);
754 service_ptr_
->SendSessionMessage(
755 message_request
.Pass(),
757 &PresentationServiceImplTest::ExpectSendMessageMojoCallback
,
758 base::Unretained(this)));
760 base::RunLoop run_loop
;
761 base::Callback
<void(bool)> send_message_cb
;
762 PresentationSessionMessage
* test_message
= nullptr;
763 EXPECT_CALL(mock_delegate_
, SendMessageRawPtr(
766 InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
767 SaveArg
<2>(&test_message
),
768 SaveArg
<3>(&send_message_cb
)));
771 EXPECT_FALSE(test_message
);
772 send_message_cb
.Run(true);
773 SaveQuitClosureAndRunLoop();
776 TEST_F(PresentationServiceImplTest
, SendBlobData
) {
777 const uint8 buffer
[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
778 std::vector
<uint8
> data
;
779 data
.assign(buffer
, buffer
+ sizeof(buffer
));
781 presentation::SessionMessagePtr
message_request(
782 presentation::SessionMessage::New());
783 message_request
->presentation_url
= kPresentationUrl
;
784 message_request
->presentation_id
= kPresentationId
;
785 message_request
->type
=
786 presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_BLOB
;
787 message_request
->data
= mojo::Array
<uint8
>::From(data
);
788 service_ptr_
->SendSessionMessage(
789 message_request
.Pass(),
790 base::Bind(&PresentationServiceImplTest::ExpectSendMessageMojoCallback
,
791 base::Unretained(this)));
793 base::RunLoop run_loop
;
794 base::Callback
<void(bool)> send_message_cb
;
795 PresentationSessionMessage
* test_message
= nullptr;
796 EXPECT_CALL(mock_delegate_
, SendMessageRawPtr(_
, _
, _
, _
))
798 InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
),
799 SaveArg
<2>(&test_message
),
800 SaveArg
<3>(&send_message_cb
)));
803 EXPECT_TRUE(test_message
);
804 EXPECT_EQ(kPresentationUrl
, test_message
->presentation_url
);
805 EXPECT_EQ(kPresentationId
, test_message
->presentation_id
);
806 EXPECT_TRUE(test_message
->is_binary());
807 EXPECT_EQ(PresentationMessageType::BLOB
, test_message
->type
);
808 EXPECT_FALSE(test_message
->message
);
809 EXPECT_EQ(data
.size(), test_message
->data
.get()->size());
810 EXPECT_TRUE(test_message
->data
.get()->size() <=
811 kMaxPresentationSessionMessageSize
);
812 EXPECT_EQ(0, memcmp(buffer
, &(*test_message
->data
.get())[0], sizeof(buffer
)));
814 send_message_cb
.Run(true);
815 SaveQuitClosureAndRunLoop();
818 TEST_F(PresentationServiceImplTest
, MaxPendingJoinSessionRequests
) {
819 const char* presentation_url
= "http://fooUrl%d";
820 const char* presentation_id
= "presentationId%d";
821 int num_requests
= PresentationServiceImpl::kMaxNumQueuedSessionRequests
;
823 EXPECT_CALL(mock_delegate_
, JoinSession(_
, _
, _
, _
, _
, _
))
824 .Times(num_requests
);
825 for (; i
< num_requests
; ++i
) {
826 service_ptr_
->JoinSession(
827 base::StringPrintf(presentation_url
, i
),
828 base::StringPrintf(presentation_id
, i
),
829 base::Bind(&DoNothing
));
832 // Exceeded maximum queue size, should invoke mojo callback with error.
833 service_ptr_
->JoinSession(
834 base::StringPrintf(presentation_url
, i
),
835 base::StringPrintf(presentation_id
, i
),
837 &PresentationServiceImplTest::ExpectNewSessionMojoCallbackError
,
838 base::Unretained(this)));
839 SaveQuitClosureAndRunLoop();
842 TEST_F(PresentationServiceImplTest
, ListenForSessionStateChange
) {
843 base::RunLoop run_loop
;
844 EXPECT_CALL(mock_delegate_
, ListenForSessionStateChange(_
, _
, _
))
845 .WillOnce(InvokeWithoutArgs(&run_loop
, &base::RunLoop::Quit
));
846 service_ptr_
->ListenForSessionStateChange();
849 presentation::PresentationSessionInfo session_info
;
850 session_info
.url
= kPresentationUrl
;
851 session_info
.id
= kPresentationId
;
853 EXPECT_CALL(mock_client_
,
854 OnSessionStateChanged(
855 Equals(session_info
),
856 presentation::PRESENTATION_SESSION_STATE_CONNECTED
));
857 service_impl_
->OnSessionStateChanged(
858 content::PresentationSessionInfo(kPresentationUrl
, kPresentationId
),
859 content::PRESENTATION_SESSION_STATE_CONNECTED
);
862 } // namespace content