blob: 3551af7cc69dc135c14cb0ea14b8fc65744a2f00 [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/media_router/browser/media_router_dialog_controller.h"
#include <memory>
#include "base/functional/bind.h"
#include "build/build_config.h"
#include "components/media_router/browser/media_router_metrics.h"
#include "components/media_router/browser/presentation/start_presentation_context.h"
#include "components/media_router/common/media_route.h"
#include "components/media_router/common/media_source.h"
#include "components/media_router/common/mojom/media_router.mojom.h"
#include "components/media_router/common/route_request_result.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_ANDROID)
#include "components/media_router/browser/android/media_router_dialog_controller_android.h"
#endif
using ::testing::_;
using ::testing::Return;
namespace media_router {
class TestMediaRouterDialogController : public MediaRouterDialogController {
public:
explicit TestMediaRouterDialogController(content::WebContents* initiator)
: MediaRouterDialogController(initiator) {}
~TestMediaRouterDialogController() override = default;
bool IsShowingMediaRouterDialog() const override { return has_dialog_; }
void CreateMediaRouterDialog(
MediaRouterDialogActivationLocation activation_location) override {
has_dialog_ = true;
}
void CloseMediaRouterDialog() override { has_dialog_ = false; }
private:
bool has_dialog_ = false;
};
class MockWebContentsDelegate : public content::WebContentsDelegate {
public:
MockWebContentsDelegate() = default;
~MockWebContentsDelegate() override = default;
MOCK_METHOD1(ActivateContents, void(content::WebContents* web_contents));
};
class MediaRouterDialogControllerTest
: public content::RenderViewHostTestHarness {
public:
MOCK_METHOD3(RequestSuccess,
void(const blink::mojom::PresentationInfo&,
mojom::RoutePresentationConnectionPtr,
const MediaRoute&));
MOCK_METHOD1(RequestError,
void(const blink::mojom::PresentationError& error));
protected:
MediaRouterDialogControllerTest() = default;
~MediaRouterDialogControllerTest() override = default;
void SetUp() override {
content::RenderViewHostTestHarness::SetUp();
web_contents_delegate_ = std::make_unique<MockWebContentsDelegate>();
web_contents()->SetDelegate(web_contents_delegate_.get());
dialog_controller_ =
std::make_unique<TestMediaRouterDialogController>(web_contents());
}
void TearDown() override {
dialog_controller_.reset();
web_contents_delegate_.reset();
content::RenderViewHostTestHarness::TearDown();
}
bool ShowMediaRouterDialogForPresentation() {
return dialog_controller_->ShowMediaRouterDialogForPresentation(
std::make_unique<StartPresentationContext>(
content::PresentationRequest(
{1, 2},
{GURL("http://example.com"), GURL("http://example2.com")},
url::Origin::Create(GURL("http://google.com"))),
base::BindOnce(&MediaRouterDialogControllerTest::RequestSuccess,
base::Unretained(this)),
base::BindOnce(&MediaRouterDialogControllerTest::RequestError,
base::Unretained(this))));
}
std::unique_ptr<TestMediaRouterDialogController> dialog_controller_;
std::unique_ptr<MockWebContentsDelegate> web_contents_delegate_;
};
#if BUILDFLAG(IS_ANDROID)
// The non-Android implementation is tested in
// MediaRouterDialogControllerViewsTest.
TEST_F(MediaRouterDialogControllerTest, CreateForWebContents) {
MediaRouterDialogController::SetGetOrCreate(
base::BindRepeating([](content::WebContents* web_contents) {
DCHECK(web_contents);
MediaRouterDialogController* controller = nullptr;
MediaRouterDialogControllerAndroid::CreateForWebContents(web_contents);
controller =
MediaRouterDialogControllerAndroid::FromWebContents(web_contents);
return controller;
}));
MediaRouterDialogController* dialog_controller =
MediaRouterDialogController::GetOrCreateForWebContents(web_contents());
ASSERT_NE(dialog_controller, nullptr);
// Returns the same value the second time.
ASSERT_EQ(
dialog_controller,
MediaRouterDialogController::GetOrCreateForWebContents(web_contents()));
}
#endif
TEST_F(MediaRouterDialogControllerTest, ShowAndHideDialog) {
EXPECT_CALL(*web_contents_delegate_, ActivateContents(web_contents()));
EXPECT_TRUE(dialog_controller_->ShowMediaRouterDialog(
MediaRouterDialogActivationLocation::TOOLBAR));
EXPECT_TRUE(dialog_controller_->IsShowingMediaRouterDialog());
// If a dialog is already shown, ShowMediaRouterDialog() should return false.
EXPECT_CALL(*web_contents_delegate_, ActivateContents(web_contents()));
EXPECT_FALSE(dialog_controller_->ShowMediaRouterDialog(
MediaRouterDialogActivationLocation::TOOLBAR));
dialog_controller_->HideMediaRouterDialog();
EXPECT_FALSE(dialog_controller_->IsShowingMediaRouterDialog());
// Once the dialog is hidden, ShowMediaRouterDialog() should return true
// again.
EXPECT_CALL(*web_contents_delegate_, ActivateContents(web_contents()));
EXPECT_TRUE(dialog_controller_->ShowMediaRouterDialog(
MediaRouterDialogActivationLocation::TOOLBAR));
}
TEST_F(MediaRouterDialogControllerTest, ShowDialogForPresentation) {
EXPECT_CALL(*web_contents_delegate_, ActivateContents(web_contents()));
EXPECT_TRUE(ShowMediaRouterDialogForPresentation());
EXPECT_TRUE(dialog_controller_->IsShowingMediaRouterDialog());
// If a dialog is already shown, ShowMediaRouterDialogForPresentation() should
// return false.
EXPECT_FALSE(ShowMediaRouterDialogForPresentation());
// The error callback is invoked automatically if StartPresentationContext is
// destroyed without a response.
EXPECT_CALL(*this, RequestError(_)).Times(1);
}
TEST_F(MediaRouterDialogControllerTest, StartPresentationContext) {
auto context = std::make_unique<StartPresentationContext>(
content::PresentationRequest(
{1, 2}, {GURL("http://example.com"), GURL("http://example2.com")},
url::Origin::Create(GURL("http://google.com"))),
base::BindOnce(&MediaRouterDialogControllerTest::RequestSuccess,
base::Unretained(this)),
base::BindOnce(&MediaRouterDialogControllerTest::RequestError,
base::Unretained(this)));
MediaRoute route("routeId", MediaSource::ForTab(1), "sinkId", "Description",
false);
auto result = RouteRequestResult::FromSuccess(route, "presentationId");
EXPECT_CALL(*this, RequestSuccess(_, _, _)).Times(1);
EXPECT_CALL(*this, RequestError(_)).Times(0);
context->HandleRouteResponse(nullptr, *result);
}
} // namespace media_router