| Index: content/renderer/presentation/presentation_dispatcher_unittest.cc
|
| diff --git a/content/renderer/presentation/presentation_dispatcher_unittest.cc b/content/renderer/presentation/presentation_dispatcher_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9397f852feda403fd7705c88b7a7412e3ec26875
|
| --- /dev/null
|
| +++ b/content/renderer/presentation/presentation_dispatcher_unittest.cc
|
| @@ -0,0 +1,409 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <memory>
|
| +#include <utility>
|
| +
|
| +#include "base/run_loop.h"
|
| +#include "content/public/test/test_browser_thread_bundle.h"
|
| +#include "content/renderer/presentation/presentation_dispatcher.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationAvailabilityObserver.h"
|
| +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationError.h"
|
| +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationSessionInfo.h"
|
| +#include "third_party/WebKit/public/web/WebArrayBuffer.h"
|
| +
|
| +using ::testing::_;
|
| +using ::testing::Invoke;
|
| +using blink::WebArrayBuffer;
|
| +using blink::WebPresentationAvailabilityCallbacks;
|
| +using blink::WebPresentationAvailabilityObserver;
|
| +using blink::WebPresentationConnectionCallback;
|
| +using blink::WebPresentationError;
|
| +using blink::WebPresentationSessionInfo;
|
| +using blink::WebString;
|
| +using blink::WebURL;
|
| +using blink::WebVector;
|
| +using blink::mojom::PresentationError;
|
| +using blink::mojom::PresentationErrorPtr;
|
| +using blink::mojom::PresentationErrorType;
|
| +using blink::mojom::PresentationService;
|
| +using blink::mojom::PresentationServiceClientPtr;
|
| +using blink::mojom::PresentationSessionInfo;
|
| +using blink::mojom::PresentationSessionInfoPtr;
|
| +using blink::mojom::ConnectionMessage;
|
| +using blink::mojom::ConnectionMessagePtr;
|
| +
|
| +// TODO(crbug.com/576808): Add test cases for the following:
|
| +// - State changes
|
| +// - Messages received
|
| +// - Discarding queued messages when the frame navigates
|
| +// - Screen availability not supported
|
| +// - Default presentation starting
|
| +
|
| +namespace content {
|
| +
|
| +class MockPresentationAvailabilityObserver
|
| + : public WebPresentationAvailabilityObserver {
|
| + public:
|
| + explicit MockPresentationAvailabilityObserver(WebURL url) : url_(url) {}
|
| + ~MockPresentationAvailabilityObserver() override {}
|
| +
|
| + MOCK_METHOD1(availabilityChanged, void(bool is_available));
|
| + const WebURL url() const override { return url_; }
|
| +
|
| + private:
|
| + const WebURL url_;
|
| +};
|
| +
|
| +class MockPresentationService : public PresentationService {
|
| + public:
|
| + void SetClient(PresentationServiceClientPtr client) override {}
|
| + MOCK_METHOD1(SetDefaultPresentationUrls,
|
| + void(const std::vector<GURL>& presentation_urls));
|
| + MOCK_METHOD1(ListenForScreenAvailability, void(const GURL& availability_url));
|
| + MOCK_METHOD1(StopListeningForScreenAvailability,
|
| + void(const GURL& availability_url));
|
| + MOCK_METHOD2(StartSession,
|
| + void(const std::vector<GURL>& presentation_urls,
|
| + const StartSessionCallback& callback));
|
| + MOCK_METHOD3(JoinSession,
|
| + void(const std::vector<GURL>& presentation_urls,
|
| + const base::Optional<std::string>& presentation_id,
|
| + const JoinSessionCallback& callback));
|
| +
|
| + // *Internal method is to work around lack of support for move-only types in
|
| + // GMock.
|
| + void SendConnectionMessage(
|
| + PresentationSessionInfoPtr session_info,
|
| + ConnectionMessagePtr message_request,
|
| + const SendConnectionMessageCallback& callback) override {
|
| + SendConnectionMessageInternal(session_info.get(), message_request.get(),
|
| + callback);
|
| + }
|
| + MOCK_METHOD3(SendConnectionMessageInternal,
|
| + void(PresentationSessionInfo* session_info,
|
| + ConnectionMessage* message_request,
|
| + const SendConnectionMessageCallback& callback));
|
| +
|
| + MOCK_METHOD2(CloseConnection,
|
| + void(const GURL& presentation_url,
|
| + const std::string& presentation_id));
|
| + MOCK_METHOD2(Terminate,
|
| + void(const GURL& presentation_url,
|
| + const std::string& presentation_id));
|
| +
|
| + // *Internal method is to work around lack of support for move-only types in
|
| + // GMock.
|
| + void ListenForConnectionMessages(
|
| + PresentationSessionInfoPtr session_info) override {
|
| + ListenForConnectionMessagesInternal(session_info.get());
|
| + }
|
| + MOCK_METHOD1(ListenForConnectionMessagesInternal,
|
| + void(PresentationSessionInfo* session_info));
|
| +};
|
| +
|
| +class TestWebPresentationConnectionCallback
|
| + : public WebPresentationConnectionCallback {
|
| + public:
|
| + TestWebPresentationConnectionCallback(WebURL url, WebString id)
|
| + : url_(url), id_(id), callback_called_(false) {}
|
| + ~TestWebPresentationConnectionCallback() override {
|
| + EXPECT_TRUE(callback_called_);
|
| + }
|
| +
|
| + void onSuccess(const WebPresentationSessionInfo& info) override {
|
| + callback_called_ = true;
|
| + EXPECT_EQ(info.url, url_);
|
| + EXPECT_EQ(info.id, id_);
|
| + }
|
| +
|
| + private:
|
| + const WebURL url_;
|
| + const WebString id_;
|
| + bool callback_called_;
|
| +};
|
| +
|
| +class TestWebPresentationConnectionErrorCallback
|
| + : public WebPresentationConnectionCallback {
|
| + public:
|
| + TestWebPresentationConnectionErrorCallback(
|
| + WebPresentationError::ErrorType error_type,
|
| + WebString message)
|
| + : error_type_(error_type), message_(message), callback_called_(false) {}
|
| + ~TestWebPresentationConnectionErrorCallback() override {
|
| + EXPECT_TRUE(callback_called_);
|
| + }
|
| +
|
| + void onError(const WebPresentationError& error) override {
|
| + callback_called_ = true;
|
| + EXPECT_EQ(error.errorType, error_type_);
|
| + EXPECT_EQ(error.message, message_);
|
| + }
|
| +
|
| + private:
|
| + const WebPresentationError::ErrorType error_type_;
|
| + const WebString message_;
|
| + bool callback_called_;
|
| +};
|
| +
|
| +class TestPresentationDispatcher : public PresentationDispatcher {
|
| + public:
|
| + explicit TestPresentationDispatcher(
|
| + MockPresentationService* presentation_service)
|
| + : PresentationDispatcher(nullptr),
|
| + mock_presentation_service_(presentation_service) {}
|
| + ~TestPresentationDispatcher() override {}
|
| +
|
| + private:
|
| + void ConnectToPresentationServiceIfNeeded() override {
|
| + if (!mock_binding_) {
|
| + mock_binding_ = base::MakeUnique<mojo::Binding<PresentationService>>(
|
| + mock_presentation_service_,
|
| + mojo::MakeRequest(&presentation_service_));
|
| + }
|
| + }
|
| +
|
| + MockPresentationService* mock_presentation_service_;
|
| + std::unique_ptr<mojo::Binding<PresentationService>> mock_binding_;
|
| +};
|
| +
|
| +class PresentationDispatcherTest : public ::testing::Test {
|
| + public:
|
| + PresentationDispatcherTest()
|
| + : gurl1_(GURL("https://www.example.com/1.html")),
|
| + gurl2_(GURL("https://www.example.com/2.html")),
|
| + gurls_({gurl1_, gurl2_}),
|
| + url1_(WebURL(gurl1_)),
|
| + url2_(WebURL(gurl2_)),
|
| + urls_(WebVector<WebURL>(gurls_)),
|
| + presentation_id_(WebString::fromUTF8("test-id")),
|
| + array_buffer_(WebArrayBuffer::create(4, 1)),
|
| + observer_(url1_),
|
| + dispatcher_(&presentation_service_) {}
|
| + ~PresentationDispatcherTest() override {}
|
| +
|
| + void SetUp() override {
|
| + // Set some test data.
|
| + *array_buffer_data() = 42;
|
| + }
|
| +
|
| + uint8_t* array_buffer_data() {
|
| + return static_cast<uint8_t*>(array_buffer_.data());
|
| + }
|
| +
|
| + protected:
|
| + const GURL gurl1_;
|
| + const GURL gurl2_;
|
| + const std::vector<GURL> gurls_;
|
| + const WebURL url1_;
|
| + const WebURL url2_;
|
| + const WebVector<WebURL> urls_;
|
| + const WebString presentation_id_;
|
| + const WebArrayBuffer array_buffer_;
|
| + MockPresentationAvailabilityObserver observer_;
|
| + MockPresentationService presentation_service_;
|
| + TestPresentationDispatcher dispatcher_;
|
| +
|
| + private:
|
| + content::TestBrowserThreadBundle thread_bundle_;
|
| +};
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestStartSession) {
|
| + base::RunLoop run_loop;
|
| +
|
| + EXPECT_CALL(presentation_service_, StartSession(gurls_, _))
|
| + .WillOnce(Invoke([this](
|
| + const std::vector<GURL>& presentation_urls,
|
| + const PresentationService::StartSessionCallback& callback) {
|
| + PresentationSessionInfoPtr session_info(PresentationSessionInfo::New());
|
| + session_info->url = gurl1_;
|
| + session_info->id = presentation_id_.utf8();
|
| + callback.Run(std::move(session_info), PresentationErrorPtr());
|
| + }));
|
| + dispatcher_.startSession(
|
| + urls_, base::MakeUnique<TestWebPresentationConnectionCallback>(
|
| + url1_, presentation_id_));
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestStartSessionError) {
|
| + WebString error_message = WebString::fromUTF8("Test error message");
|
| + base::RunLoop run_loop;
|
| +
|
| + EXPECT_CALL(presentation_service_, StartSession(gurls_, _))
|
| + .WillOnce(Invoke([this, &error_message](
|
| + const std::vector<GURL>& presentation_urls,
|
| + const PresentationService::StartSessionCallback& callback) {
|
| + PresentationErrorPtr error(PresentationError::New());
|
| + error->error_type = PresentationErrorType::NO_AVAILABLE_SCREENS;
|
| + error->message = error_message.utf8();
|
| + callback.Run(PresentationSessionInfoPtr(), std::move(error));
|
| + }));
|
| + dispatcher_.startSession(
|
| + urls_,
|
| + base::MakeUnique<TestWebPresentationConnectionErrorCallback>(
|
| + WebPresentationError::ErrorTypeNoAvailableScreens, error_message));
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestJoinSessionError) {
|
| + WebString error_message = WebString::fromUTF8("Test error message");
|
| + base::RunLoop run_loop;
|
| +
|
| + EXPECT_CALL(presentation_service_, JoinSession(gurls_, _, _))
|
| + .WillOnce(Invoke([this, &error_message](
|
| + const std::vector<GURL>& presentation_urls,
|
| + const base::Optional<std::string>& presentation_id,
|
| + const PresentationService::JoinSessionCallback& callback) {
|
| + EXPECT_TRUE(presentation_id.has_value());
|
| + EXPECT_EQ(presentation_id_.utf8(), presentation_id.value());
|
| + PresentationErrorPtr error(PresentationError::New());
|
| + error->error_type = PresentationErrorType::NO_AVAILABLE_SCREENS;
|
| + error->message = error_message.utf8();
|
| + callback.Run(PresentationSessionInfoPtr(), std::move(error));
|
| + }));
|
| + dispatcher_.joinSession(
|
| + urls_, presentation_id_,
|
| + base::MakeUnique<TestWebPresentationConnectionErrorCallback>(
|
| + WebPresentationError::ErrorTypeNoAvailableScreens, error_message));
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestJoinSession) {
|
| + base::RunLoop run_loop;
|
| +
|
| + EXPECT_CALL(presentation_service_, JoinSession(gurls_, _, _))
|
| + .WillOnce(Invoke([this](
|
| + const std::vector<GURL>& presentation_urls,
|
| + const base::Optional<std::string>& presentation_id,
|
| + const PresentationService::JoinSessionCallback& callback) {
|
| + EXPECT_TRUE(presentation_id.has_value());
|
| + EXPECT_EQ(presentation_id_.utf8(), presentation_id.value());
|
| + PresentationSessionInfoPtr session_info(PresentationSessionInfo::New());
|
| + session_info->url = gurl1_;
|
| + session_info->id = presentation_id_.utf8();
|
| + callback.Run(std::move(session_info), PresentationErrorPtr());
|
| + }));
|
| + dispatcher_.joinSession(
|
| + urls_, presentation_id_,
|
| + base::MakeUnique<TestWebPresentationConnectionCallback>(
|
| + url1_, presentation_id_));
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestSendString) {
|
| + WebString message = WebString::fromUTF8("test message");
|
| + base::RunLoop run_loop;
|
| + EXPECT_CALL(presentation_service_, SendConnectionMessageInternal(_, _, _))
|
| + .WillOnce(Invoke([this, &message](
|
| + PresentationSessionInfo* session_info,
|
| + ConnectionMessage* message_request,
|
| + const PresentationService::SendConnectionMessageCallback& callback) {
|
| + EXPECT_EQ(gurl1_, session_info->url);
|
| + EXPECT_EQ(presentation_id_.utf8(), session_info->id);
|
| + EXPECT_TRUE(message_request->message.has_value());
|
| + EXPECT_EQ(message.utf8(), message_request->message.value());
|
| + callback.Run(true);
|
| + }));
|
| + dispatcher_.sendString(url1_, presentation_id_, message);
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestSendArrayBuffer) {
|
| + base::RunLoop run_loop;
|
| + EXPECT_CALL(presentation_service_, SendConnectionMessageInternal(_, _, _))
|
| + .WillOnce(Invoke([this](
|
| + PresentationSessionInfo* session_info,
|
| + ConnectionMessage* message_request,
|
| + const PresentationService::SendConnectionMessageCallback& callback) {
|
| + EXPECT_EQ(gurl1_, session_info->url);
|
| + EXPECT_EQ(presentation_id_.utf8(), session_info->id);
|
| + std::vector<uint8_t> data(
|
| + array_buffer_data(),
|
| + array_buffer_data() + array_buffer_.byteLength());
|
| + EXPECT_TRUE(message_request->data.has_value());
|
| + EXPECT_EQ(data, message_request->data.value());
|
| + callback.Run(true);
|
| + }));
|
| + dispatcher_.sendArrayBuffer(url1_, presentation_id_, array_buffer_data(),
|
| + array_buffer_.byteLength());
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestSendBlobData) {
|
| + base::RunLoop run_loop;
|
| + EXPECT_CALL(presentation_service_, SendConnectionMessageInternal(_, _, _))
|
| + .WillOnce(Invoke([this](
|
| + PresentationSessionInfo* session_info,
|
| + ConnectionMessage* message_request,
|
| + const PresentationService::SendConnectionMessageCallback& callback) {
|
| + EXPECT_EQ(gurl1_, session_info->url);
|
| + EXPECT_EQ(presentation_id_.utf8(), session_info->id);
|
| + std::vector<uint8_t> data(
|
| + array_buffer_data(),
|
| + array_buffer_data() + array_buffer_.byteLength());
|
| + EXPECT_TRUE(message_request->data.has_value());
|
| + EXPECT_EQ(data, message_request->data.value());
|
| + callback.Run(true);
|
| + }));
|
| + dispatcher_.sendBlobData(url1_, presentation_id_, array_buffer_data(),
|
| + array_buffer_.byteLength());
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestCloseSession) {
|
| + base::RunLoop run_loop;
|
| + EXPECT_CALL(presentation_service_,
|
| + CloseConnection(gurl1_, presentation_id_.utf8()));
|
| + dispatcher_.closeSession(url1_, presentation_id_);
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestTerminateSession) {
|
| + base::RunLoop run_loop;
|
| + EXPECT_CALL(presentation_service_,
|
| + Terminate(gurl1_, presentation_id_.utf8()));
|
| + dispatcher_.terminateSession(url1_, presentation_id_);
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestListenForScreenAvailability) {
|
| + base::RunLoop run_loop1;
|
| + EXPECT_CALL(presentation_service_, ListenForScreenAvailability(gurl1_));
|
| + dispatcher_.getAvailability(
|
| + url1_, base::MakeUnique<WebPresentationAvailabilityCallbacks>());
|
| + dispatcher_.OnScreenAvailabilityUpdated(url1_, true);
|
| + run_loop1.RunUntilIdle();
|
| +
|
| + base::RunLoop run_loop2;
|
| + EXPECT_CALL(presentation_service_, ListenForScreenAvailability(gurl1_));
|
| + dispatcher_.startListening(&observer_);
|
| + run_loop2.RunUntilIdle();
|
| +
|
| + base::RunLoop run_loop3;
|
| + EXPECT_CALL(observer_, availabilityChanged(false));
|
| + dispatcher_.OnScreenAvailabilityUpdated(url1_, false);
|
| + EXPECT_CALL(observer_, availabilityChanged(true));
|
| + dispatcher_.OnScreenAvailabilityUpdated(url1_, true);
|
| + EXPECT_CALL(presentation_service_,
|
| + StopListeningForScreenAvailability(gurl1_));
|
| + dispatcher_.stopListening(&observer_);
|
| + run_loop3.RunUntilIdle();
|
| +
|
| + // After stopListening(), |observer_| should no longer be notified.
|
| + base::RunLoop run_loop4;
|
| + EXPECT_CALL(observer_, availabilityChanged(false)).Times(0);
|
| + dispatcher_.OnScreenAvailabilityUpdated(url1_, false);
|
| + run_loop4.RunUntilIdle();
|
| +}
|
| +
|
| +TEST_F(PresentationDispatcherTest, TestSetDefaultPresentationUrls) {
|
| + base::RunLoop run_loop;
|
| + EXPECT_CALL(presentation_service_, SetDefaultPresentationUrls(gurls_));
|
| + dispatcher_.setDefaultPresentationUrls(urls_);
|
| + run_loop.RunUntilIdle();
|
| +}
|
| +
|
| +} // namespace content
|
|
|