blob: 06be78769f9d2137ce8d70ada536cb6ec9124f4e [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/media_router/cast_toolbar_button.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/media/router/chrome_media_router_factory.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/color/chrome_color_id.h"
#include "chrome/browser/ui/media_router/media_router_ui_service.h"
#include "chrome/browser/ui/media_router/media_router_ui_service_factory.h"
#include "chrome/browser/ui/toolbar/media_router_contextual_menu.h"
#include "chrome/browser/ui/toolbar/mock_media_router_action_controller.h"
#include "chrome/test/base/test_browser_window.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/views/chrome_views_test_base.h"
#include "components/media_router/browser/media_router_factory.h"
#include "components/media_router/browser/test/mock_media_router.h"
#include "components/vector_icons/vector_icons.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/theme_provider.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/native_theme/native_theme.h"
using testing::_;
using testing::WithArg;
namespace media_router {
namespace {
std::unique_ptr<KeyedService> BuildUIService(content::BrowserContext* context) {
Profile* profile = Profile::FromBrowserContext(context);
auto controller = std::make_unique<MockMediaRouterActionController>(profile);
return std::make_unique<media_router::MediaRouterUIService>(
profile, std::move(controller));
}
MediaRoute CreateLocalDisplayRoute() {
return MediaRoute("routeId1", MediaSource("source1"), "sinkId1",
"description", true);
}
MediaRoute CreateNonLocalDisplayRoute() {
return MediaRoute("routeId2", MediaSource("source2"), "sinkId2",
"description", false);
}
class MockContextMenuObserver : public MediaRouterContextualMenu::Observer {
public:
MOCK_METHOD0(OnContextMenuShown, void());
MOCK_METHOD0(OnContextMenuHidden, void());
};
} // namespace
class CastToolbarButtonTest : public ChromeViewsTestBase {
public:
CastToolbarButtonTest() = default;
CastToolbarButtonTest(const CastToolbarButtonTest&) = delete;
CastToolbarButtonTest& operator=(const CastToolbarButtonTest&) = delete;
~CastToolbarButtonTest() override = default;
void SetUp() override {
ChromeViewsTestBase::SetUp();
profile_ = std::make_unique<TestingProfile>();
ChromeMediaRouterFactory::GetInstance()->SetTestingFactory(
profile_.get(), base::BindRepeating(&MockMediaRouter::Create));
MediaRouterUIServiceFactory::GetInstance()->SetTestingFactory(
profile_.get(), base::BindRepeating(&BuildUIService));
window_ = std::make_unique<TestBrowserWindow>();
Browser::CreateParams browser_params(profile_.get(), true);
browser_params.window = window_.get();
browser_ = std::unique_ptr<Browser>(Browser::Create(browser_params));
MockMediaRouter* media_router = static_cast<MockMediaRouter*>(
MediaRouterFactory::GetApiForBrowserContext(profile_.get()));
logger_ = std::make_unique<LoggerImpl>();
ON_CALL(*media_router, GetLogger())
.WillByDefault(testing::Return(logger_.get()));
auto context_menu = std::make_unique<MediaRouterContextualMenu>(
browser_.get(), false, &context_menu_observer_);
// Button needs to be in a widget to be able to access ColorProvider.
widget_ = CreateTestWidget();
button_ = widget_->SetContentsView(std::make_unique<CastToolbarButton>(
browser_.get(), media_router, std::move(context_menu)));
const ui::ColorProvider* color_provider = button_->GetColorProvider();
idle_icon_ = gfx::Image(gfx::CreateVectorIcon(
vector_icons::kMediaRouterIdleIcon,
color_provider->GetColor(kColorToolbarButtonIcon)));
warning_icon_ = gfx::Image(gfx::CreateVectorIcon(
vector_icons::kMediaRouterWarningIcon,
color_provider->GetColor(kColorMediaRouterIconWarning)));
active_icon_ = gfx::Image(gfx::CreateVectorIcon(
vector_icons::kMediaRouterActiveIcon,
color_provider->GetColor(kColorMediaRouterIconActive)));
}
void TearDown() override {
widget_.reset();
browser_.reset();
window_.reset();
profile_.reset();
ChromeViewsTestBase::TearDown();
}
protected:
gfx::Image GetIcon() {
return gfx::Image(button_->GetImage(views::Button::STATE_NORMAL));
}
std::unique_ptr<BrowserWindow> window_;
std::unique_ptr<Browser> browser_;
std::unique_ptr<views::Widget> widget_;
raw_ptr<CastToolbarButton> button_ = nullptr; // owned by |widget_|.
MockContextMenuObserver context_menu_observer_;
std::unique_ptr<TestingProfile> profile_;
std::unique_ptr<LoggerImpl> logger_;
gfx::Image idle_icon_;
gfx::Image warning_icon_;
gfx::Image active_icon_;
const std::vector<MediaRoute> local_display_route_list_ = {
CreateLocalDisplayRoute()};
const std::vector<MediaRoute> non_local_display_route_list_ = {
CreateNonLocalDisplayRoute()};
};
TEST_F(CastToolbarButtonTest, ShowAndHideButton) {
ASSERT_FALSE(button_->GetVisible());
button_->ShowIcon();
EXPECT_TRUE(button_->GetVisible());
button_->HideIcon();
EXPECT_FALSE(button_->GetVisible());
}
TEST_F(CastToolbarButtonTest, UpdateIssues) {
button_->UpdateIcon();
EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon()));
button_->OnIssue(
Issue(IssueInfo("title notification", IssueInfo::Action::DISMISS,
IssueInfo::Severity::NOTIFICATION)));
EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon()));
button_->OnIssue(
Issue(IssueInfo("title warning", IssueInfo::Action::LEARN_MORE,
IssueInfo::Severity::WARNING)));
EXPECT_TRUE(gfx::test::AreImagesEqual(warning_icon_, GetIcon()));
button_->OnIssuesCleared();
EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon()));
}
TEST_F(CastToolbarButtonTest, UpdateRoutes) {
button_->UpdateIcon();
EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon()));
button_->OnRoutesUpdated(local_display_route_list_);
EXPECT_TRUE(gfx::test::AreImagesEqual(active_icon_, GetIcon()));
// The idle icon should be shown when we only have non-local and/or
// non-display routes.
button_->OnRoutesUpdated(non_local_display_route_list_);
EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon()));
button_->OnRoutesUpdated({});
EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon_, GetIcon()));
}
} // namespace media_router