Commit ca6c2430 authored by Takumi Fujimoto's avatar Takumi Fujimoto Committed by Commit Bot

Show the Harmony Cast Dialog

This CL enables the most basic functionalities: showing and hiding the
dialog, showing sinks and their statuses (no throbber support yet), and
starting and stopping tab mirroring. The dialog is still behind the
ViewsCastDialog feature flag.

- MRDialogControllerViews instantiates MRViewsUI and CastDialogView
  when a dialog is requested, and destroys them when the dialog is
  closed.
- MRViewsUI sends CastDialogModel to CastDialogView whenever sinks or
  routes are updated. It also sends route requests from CastDialogView
  to MediaRouter.

This CL depends on crrev.com/c/1020231.

Bug: 826091
Change-Id: I14ed4811dd7ccdf0144c64b6f079c06d7fc0aa6e
Reviewed-on: https://chromium-review.googlesource.com/1037907
Commit-Queue: Takumi Fujimoto <takumif@chromium.org>
Reviewed-by: default avatarmark a. foltz <mfoltz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558017}
parent 718fd6c0
...@@ -165,12 +165,16 @@ void MediaRouterDialogController::HideMediaRouterDialog() { ...@@ -165,12 +165,16 @@ void MediaRouterDialogController::HideMediaRouterDialog() {
void MediaRouterDialogController::FocusOnMediaRouterDialog( void MediaRouterDialogController::FocusOnMediaRouterDialog(
bool dialog_needs_creation) { bool dialog_needs_creation) {
// Show the WebContents requesting a dialog.
// TODO(takumif): In the case of Views dialog, if the dialog is already shown,
// activating the WebContents makes the dialog lose focus and disappear. The
// dialog needs to be created again in that case.
initiator_->GetDelegate()->ActivateContents(initiator_);
if (dialog_needs_creation) { if (dialog_needs_creation) {
initiator_observer_.reset( initiator_observer_ =
new InitiatorWebContentsObserver(initiator_, this)); std::make_unique<InitiatorWebContentsObserver>(initiator_, this);
CreateMediaRouterDialog(); CreateMediaRouterDialog();
} }
initiator_->GetDelegate()->ActivateContents(initiator_);
} }
void MediaRouterDialogController::Reset() { void MediaRouterDialogController::Reset() {
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#include "chrome/browser/media/router/presentation/presentation_service_delegate_impl.h" #include "chrome/browser/media/router/presentation/presentation_service_delegate_impl.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/media_router/media_router_ui_base.h"
#include "chrome/browser/ui/toolbar/media_router_action.h" #include "chrome/browser/ui/toolbar/media_router_action.h"
#include "chrome/browser/ui/webui/media_router/media_router_ui.h"
#include "chrome/browser/ui/webui/media_router/media_router_ui_service.h" #include "chrome/browser/ui/webui/media_router/media_router_ui_service.h"
using content::WebContents; using content::WebContents;
...@@ -60,7 +60,7 @@ MediaRouterDialogControllerImplBase::MediaRouterDialogControllerImplBase( ...@@ -60,7 +60,7 @@ MediaRouterDialogControllerImplBase::MediaRouterDialogControllerImplBase(
} }
void MediaRouterDialogControllerImplBase::InitializeMediaRouterUI( void MediaRouterDialogControllerImplBase::InitializeMediaRouterUI(
MediaRouterUI* media_router_ui) { MediaRouterUIBase* media_router_ui) {
auto start_presentation_context = std::move(start_presentation_context_); auto start_presentation_context = std::move(start_presentation_context_);
PresentationServiceDelegateImpl* delegate = PresentationServiceDelegateImpl* delegate =
PresentationServiceDelegateImpl::FromWebContents(initiator()); PresentationServiceDelegateImpl::FromWebContents(initiator());
......
...@@ -13,7 +13,7 @@ class MediaRouterActionController; ...@@ -13,7 +13,7 @@ class MediaRouterActionController;
namespace media_router { namespace media_router {
class MediaRouterUI; class MediaRouterUIBase;
// The base class for desktop implementations of MediaRouterDialogController. // The base class for desktop implementations of MediaRouterDialogController.
// This class is not thread safe and must be called on the UI thread. // This class is not thread safe and must be called on the UI thread.
...@@ -39,8 +39,8 @@ class MediaRouterDialogControllerImplBase : public MediaRouterDialogController { ...@@ -39,8 +39,8 @@ class MediaRouterDialogControllerImplBase : public MediaRouterDialogController {
explicit MediaRouterDialogControllerImplBase( explicit MediaRouterDialogControllerImplBase(
content::WebContents* web_contents); content::WebContents* web_contents);
// TODO(crbug.com/826091): Replace MediaRouterUI with MediaRouterUIBase. // Called by subclasses to initialize |media_router_ui| that they use.
void InitializeMediaRouterUI(MediaRouterUI* media_router_ui); void InitializeMediaRouterUI(MediaRouterUIBase* media_router_ui);
private: private:
// |action_| refers to the MediaRouterAction on the toolbar, rather than // |action_| refers to the MediaRouterAction on the toolbar, rather than
......
...@@ -339,7 +339,7 @@ bool MediaRouterUIBase::CreateRoute(const MediaSink::Id& sink_id, ...@@ -339,7 +339,7 @@ bool MediaRouterUIBase::CreateRoute(const MediaSink::Id& sink_id,
return true; return true;
} }
void MediaRouterUIBase::CloseRoute(const MediaRoute::Id& route_id) { void MediaRouterUIBase::TerminateRoute(const MediaRoute::Id& route_id) {
GetMediaRouter()->TerminateRoute(route_id); GetMediaRouter()->TerminateRoute(route_id);
} }
......
...@@ -99,14 +99,15 @@ class MediaRouterUIBase : public QueryResultManager::Observer, ...@@ -99,14 +99,15 @@ class MediaRouterUIBase : public QueryResultManager::Observer,
virtual bool CreateRoute(const MediaSink::Id& sink_id, virtual bool CreateRoute(const MediaSink::Id& sink_id,
MediaCastMode cast_mode); MediaCastMode cast_mode);
// Calls MediaRouter to close the given route. // Calls MediaRouter to terminate the given route.
void CloseRoute(const MediaRoute::Id& route_id); void TerminateRoute(const MediaRoute::Id& route_id);
// Logs a UMA stat for the source that was cast if the result is successful. // Logs a UMA stat for the source that was cast if the result is successful.
void MaybeReportCastingSource(MediaCastMode cast_mode, void MaybeReportCastingSource(MediaCastMode cast_mode,
const RouteRequestResult& result); const RouteRequestResult& result);
// Returns a subset of |sinks_| that should be listed in the dialog. // Returns a subset of |sinks_| that should be listed in the dialog. This
// excludes the wired display that the initiator WebContents is on.
std::vector<MediaSinkWithCastModes> GetEnabledSinks() const; std::vector<MediaSinkWithCastModes> GetEnabledSinks() const;
// Returns a source name that can be shown in the dialog. // Returns a source name that can be shown in the dialog.
......
...@@ -65,13 +65,13 @@ base::string16 CastDialogView::GetWindowTitle() const { ...@@ -65,13 +65,13 @@ base::string16 CastDialogView::GetWindowTitle() const {
base::string16 CastDialogView::GetDialogButtonLabel( base::string16 CastDialogView::GetDialogButtonLabel(
ui::DialogButton button) const { ui::DialogButton button) const {
if (sink_buttons_.empty()) return sink_buttons_.empty()
return base::string16(); ? base::string16()
return sink_buttons_.at(selected_sink_index_)->GetActionText(); : sink_buttons_.at(selected_sink_index_)->GetActionText();
} }
int CastDialogView::GetDialogButtons() const { int CastDialogView::GetDialogButtons() const {
return ui::DIALOG_BUTTON_OK; return sink_buttons_.empty() ? ui::DIALOG_BUTTON_NONE : ui::DIALOG_BUTTON_OK;
} }
bool CastDialogView::Accept() { bool CastDialogView::Accept() {
......
...@@ -5,6 +5,12 @@ ...@@ -5,6 +5,12 @@
#include "chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h" #include "chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h"
#include "chrome/browser/ui/toolbar/media_router_action.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/media_router/cast_dialog_view.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.h" #include "chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.h"
#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_features.h"
...@@ -28,6 +34,8 @@ MediaRouterDialogControllerImplBase::GetOrCreateForWebContents( ...@@ -28,6 +34,8 @@ MediaRouterDialogControllerImplBase::GetOrCreateForWebContents(
MediaRouterDialogControllerViews::~MediaRouterDialogControllerViews() { MediaRouterDialogControllerViews::~MediaRouterDialogControllerViews() {
Reset(); Reset();
if (CastDialogView::GetCurrentDialogWidget())
CastDialogView::GetCurrentDialogWidget()->RemoveObserver(this);
} }
// static // static
...@@ -42,20 +50,41 @@ MediaRouterDialogControllerViews::GetOrCreateForWebContents( ...@@ -42,20 +50,41 @@ MediaRouterDialogControllerViews::GetOrCreateForWebContents(
void MediaRouterDialogControllerViews::CreateMediaRouterDialog() { void MediaRouterDialogControllerViews::CreateMediaRouterDialog() {
MediaRouterDialogControllerImplBase::CreateMediaRouterDialog(); MediaRouterDialogControllerImplBase::CreateMediaRouterDialog();
// TODO(crbug.com/826091): Implement this method.
ui_ = std::make_unique<MediaRouterViewsUI>();
InitializeMediaRouterUI(ui_.get());
Browser* browser = chrome::FindBrowserWithWebContents(initiator());
BrowserActionsContainer* browser_actions =
BrowserView::GetBrowserViewForBrowser(browser)
->toolbar()
->browser_actions();
// |browser_actions| may be null in toolbar-less browser windows.
// TODO(takumif): Show the dialog at the top-middle of the window if the
// toolbar is missing.
if (!browser_actions)
return;
views::View* action_view = browser_actions->GetViewForId(
ComponentToolbarActionsFactory::kMediaRouterActionId);
CastDialogView::ShowDialog(action_view, ui_.get());
CastDialogView::GetCurrentDialogWidget()->AddObserver(this);
} }
void MediaRouterDialogControllerViews::CloseMediaRouterDialog() { void MediaRouterDialogControllerViews::CloseMediaRouterDialog() {
// TODO(crbug.com/826091): Implement this method. CastDialogView::HideDialog();
} }
bool MediaRouterDialogControllerViews::IsShowingMediaRouterDialog() const { bool MediaRouterDialogControllerViews::IsShowingMediaRouterDialog() const {
// TODO(crbug.com/826091): Implement this method. return CastDialogView::IsShowing();
return false;
} }
void MediaRouterDialogControllerViews::Reset() { void MediaRouterDialogControllerViews::Reset() {
MediaRouterDialogControllerImplBase::Reset(); MediaRouterDialogControllerImplBase::Reset();
ui_.reset();
}
void MediaRouterDialogControllerViews::OnWidgetClosing(views::Widget* widget) {
Reset();
} }
MediaRouterDialogControllerViews::MediaRouterDialogControllerViews( MediaRouterDialogControllerViews::MediaRouterDialogControllerViews(
......
...@@ -7,14 +7,16 @@ ...@@ -7,14 +7,16 @@
#include "base/macros.h" #include "base/macros.h"
#include "chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h" #include "chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h"
#include "content/public/browser/web_contents_user_data.h" #include "chrome/browser/ui/views/media_router/media_router_views_ui.h"
#include "ui/views/widget/widget_observer.h"
namespace media_router { namespace media_router {
// A Views implementation of MediaRouterDialogController. // A Views implementation of MediaRouterDialogController.
class MediaRouterDialogControllerViews class MediaRouterDialogControllerViews
: public content::WebContentsUserData<MediaRouterDialogControllerViews>, : public content::WebContentsUserData<MediaRouterDialogControllerViews>,
public MediaRouterDialogControllerImplBase { public MediaRouterDialogControllerImplBase,
public views::WidgetObserver {
public: public:
~MediaRouterDialogControllerViews() override; ~MediaRouterDialogControllerViews() override;
...@@ -27,6 +29,9 @@ class MediaRouterDialogControllerViews ...@@ -27,6 +29,9 @@ class MediaRouterDialogControllerViews
bool IsShowingMediaRouterDialog() const override; bool IsShowingMediaRouterDialog() const override;
void Reset() override; void Reset() override;
// views::WidgetObserver:
void OnWidgetClosing(views::Widget* widget) override;
private: private:
friend class content::WebContentsUserData<MediaRouterDialogControllerViews>; friend class content::WebContentsUserData<MediaRouterDialogControllerViews>;
...@@ -34,6 +39,11 @@ class MediaRouterDialogControllerViews ...@@ -34,6 +39,11 @@ class MediaRouterDialogControllerViews
// an instance. // an instance.
explicit MediaRouterDialogControllerViews(content::WebContents* web_contents); explicit MediaRouterDialogControllerViews(content::WebContents* web_contents);
// Responsible for notifying the dialog view of dialog model updates and
// sending route requests to MediaRouter. Set to nullptr when the dialog is
// closed.
std::unique_ptr<MediaRouterViewsUI> ui_;
DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogControllerViews); DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogControllerViews);
}; };
......
...@@ -4,14 +4,92 @@ ...@@ -4,14 +4,92 @@
#include "chrome/browser/ui/views/media_router/media_router_views_ui.h" #include "chrome/browser/ui/views/media_router/media_router_views_ui.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/media_router/media_sink_with_cast_modes.h"
#include "chrome/browser/ui/media_router/ui_media_sink.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
namespace media_router { namespace media_router {
namespace {
UIMediaSink ConvertToUISink(const MediaSinkWithCastModes& sink,
const MediaRoute* route) {
UIMediaSink ui_sink;
ui_sink.id = sink.sink.id();
ui_sink.friendly_name = base::UTF8ToUTF16(sink.sink.name());
ui_sink.icon_type = sink.sink.icon_type();
if (route) {
ui_sink.status_text = base::UTF8ToUTF16(route->description());
ui_sink.route_id = route->media_route_id();
ui_sink.state = UIMediaSinkState::CONNECTED;
ui_sink.allowed_actions = static_cast<int>(UICastAction::STOP);
} else {
ui_sink.state = UIMediaSinkState::AVAILABLE;
if (base::ContainsKey(sink.cast_modes, PRESENTATION) ||
base::ContainsKey(sink.cast_modes, TAB_MIRROR)) {
ui_sink.allowed_actions |= static_cast<int>(UICastAction::CAST_TAB);
}
if (base::ContainsKey(sink.cast_modes, DESKTOP_MIRROR))
ui_sink.allowed_actions |= static_cast<int>(UICastAction::CAST_DESKTOP);
// TODO(takumif): Add support for local media casting.
}
DCHECK(ui_sink.allowed_actions);
return ui_sink;
}
} // namespace
MediaRouterViewsUI::MediaRouterViewsUI() = default; MediaRouterViewsUI::MediaRouterViewsUI() = default;
MediaRouterViewsUI::~MediaRouterViewsUI() = default; MediaRouterViewsUI::~MediaRouterViewsUI() {
for (CastDialogController::Observer& observer : observers_)
observer.OnControllerInvalidated();
}
void MediaRouterViewsUI::AddObserver(CastDialogController::Observer* observer) {
observers_.AddObserver(observer);
observer->OnModelUpdated(model_);
}
void MediaRouterViewsUI::RemoveObserver(
CastDialogController::Observer* observer) {
observers_.RemoveObserver(observer);
}
void MediaRouterViewsUI::StartCasting(const std::string& sink_id,
MediaCastMode cast_mode) {
CreateRoute(sink_id, cast_mode);
}
void MediaRouterViewsUI::StopCasting(const std::string& route_id) {
TerminateRoute(route_id);
}
void MediaRouterViewsUI::OnRoutesUpdated(
const std::vector<MediaRoute>& routes,
const std::vector<MediaRoute::Id>& joinable_route_ids) {
MediaRouterUIBase::OnRoutesUpdated(routes, joinable_route_ids);
UpdateSinks();
}
void MediaRouterViewsUI::UpdateSinks() { void MediaRouterViewsUI::UpdateSinks() {
// TODO(crbug.com/826091): Implement this method. model_.dialog_header =
l10n_util::GetStringUTF16(IDS_MEDIA_ROUTER_AUTO_CAST_MODE);
model_.media_sinks.clear();
for (const MediaSinkWithCastModes& sink : GetEnabledSinks()) {
auto route_it = std::find_if(
routes().begin(), routes().end(), [&sink](const MediaRoute& route) {
return route.media_sink_id() == sink.sink.id();
});
const MediaRoute* route = route_it == routes().end() ? nullptr : &*route_it;
model_.media_sinks.push_back(ConvertToUISink(sink, route));
}
for (CastDialogController::Observer& observer : observers_)
observer.OnModelUpdated(model_);
} }
} // namespace media_router } // namespace media_router
...@@ -6,20 +6,42 @@ ...@@ -6,20 +6,42 @@
#define CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_MEDIA_ROUTER_VIEWS_UI_H_ #define CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_MEDIA_ROUTER_VIEWS_UI_H_
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h"
#include "chrome/browser/ui/media_router/cast_dialog_controller.h"
#include "chrome/browser/ui/media_router/cast_dialog_model.h"
#include "chrome/browser/ui/media_router/media_router_ui_base.h" #include "chrome/browser/ui/media_router/media_router_ui_base.h"
namespace media_router { namespace media_router {
// Functions as an intermediary between MediaRouter and Views Cast dialog. // Functions as an intermediary between MediaRouter and Views Cast dialog.
class MediaRouterViewsUI : public MediaRouterUIBase { class MediaRouterViewsUI : public MediaRouterUIBase,
public CastDialogController {
public: public:
MediaRouterViewsUI(); MediaRouterViewsUI();
~MediaRouterViewsUI() override; ~MediaRouterViewsUI() override;
// CastDialogController:
void AddObserver(CastDialogController::Observer* observer) override;
void RemoveObserver(CastDialogController::Observer* observer) override;
void StartCasting(const std::string& sink_id,
MediaCastMode cast_mode) override;
void StopCasting(const std::string& route_id) override;
private: private:
FRIEND_TEST_ALL_PREFIXES(MediaRouterViewsUITest, NotifyObserver);
// MediaRouterUIBase: // MediaRouterUIBase:
void OnRoutesUpdated(
const std::vector<MediaRoute>& routes,
const std::vector<MediaRoute::Id>& joinable_route_ids) override;
void UpdateSinks() override; void UpdateSinks() override;
// Contains up-to-date data to show in the dialog.
CastDialogModel model_;
// Observers for dialog model updates.
base::ObserverList<CastDialogController::Observer> observers_;
DISALLOW_COPY_AND_ASSIGN(MediaRouterViewsUI); DISALLOW_COPY_AND_ASSIGN(MediaRouterViewsUI);
}; };
......
// Copyright 2018 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 "chrome/browser/ui/views/media_router/media_router_views_ui.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/media/router/media_sinks_observer.h"
#include "chrome/browser/media/router/test/mock_media_router.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/media_router/cast_dialog_controller.h"
#include "chrome/browser/ui/media_router/media_cast_mode.h"
#include "chrome/common/media_router/media_source_helper.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
using testing::_;
using testing::Invoke;
using testing::WithArg;
namespace media_router {
namespace {
constexpr char kRouteId[] = "route1";
constexpr char kSinkId[] = "sink1";
constexpr char kSinkName[] = "sink name";
constexpr char kSourceId[] = "source1";
} // namespace
class MockControllerObserver : public CastDialogController::Observer {
public:
MOCK_METHOD1(OnModelUpdated, void(const CastDialogModel& model));
MOCK_METHOD0(OnControllerInvalidated, void());
};
// Injects a MediaRouter instance into MediaRouterViewsUI.
class TestMediaRouterViewsUI : public MediaRouterViewsUI {
public:
explicit TestMediaRouterViewsUI(MediaRouter* router) : router_(router) {}
~TestMediaRouterViewsUI() override = default;
MediaRouter* GetMediaRouter() const override { return router_; }
private:
MediaRouter* router_;
DISALLOW_COPY_AND_ASSIGN(TestMediaRouterViewsUI);
};
class MediaRouterViewsUITest : public ChromeRenderViewHostTestHarness {
public:
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
// Store sink observers so that they can be notified in tests.
ON_CALL(mock_router_, RegisterMediaSinksObserver(_))
.WillByDefault(Invoke([this](MediaSinksObserver* observer) {
media_sinks_observers_.push_back(observer);
return true;
}));
SessionTabHelper::CreateForWebContents(web_contents());
ui_ = std::make_unique<TestMediaRouterViewsUI>(&mock_router_);
ui_->InitWithDefaultMediaSource(web_contents(), nullptr);
}
void TearDown() override {
ui_.reset();
ChromeRenderViewHostTestHarness::TearDown();
}
protected:
std::vector<MediaSinksObserver*> media_sinks_observers_;
MockMediaRouter mock_router_;
std::unique_ptr<MediaRouterViewsUI> ui_;
};
TEST_F(MediaRouterViewsUITest, NotifyObserver) {
MockControllerObserver observer;
EXPECT_CALL(observer, OnModelUpdated(_))
.WillOnce(WithArg<0>(Invoke([](const CastDialogModel& model) {
EXPECT_TRUE(model.media_sinks.empty());
})));
ui_->AddObserver(&observer);
MediaSink sink(kSinkId, kSinkName, SinkIconType::CAST_AUDIO);
MediaSinkWithCastModes sink_with_cast_modes(sink);
sink_with_cast_modes.cast_modes = {MediaCastMode::TAB_MIRROR};
EXPECT_CALL(observer, OnModelUpdated(_))
.WillOnce(WithArg<0>(Invoke([&sink](const CastDialogModel& model) {
EXPECT_EQ(1u, model.media_sinks.size());
const UIMediaSink& ui_sink = model.media_sinks[0];
EXPECT_EQ(sink.id(), ui_sink.id);
EXPECT_EQ(base::UTF8ToUTF16(sink.name()), ui_sink.friendly_name);
EXPECT_EQ(UIMediaSinkState::AVAILABLE, ui_sink.state);
EXPECT_EQ(static_cast<int>(UICastAction::CAST_TAB),
ui_sink.allowed_actions);
EXPECT_EQ(sink.icon_type(), ui_sink.icon_type);
})));
ui_->OnResultsUpdated({sink_with_cast_modes});
MediaRoute route(kRouteId, MediaSource(kSourceId), kSinkId, "", true, true);
EXPECT_CALL(observer, OnModelUpdated(_))
.WillOnce(
WithArg<0>(Invoke([&sink, &route](const CastDialogModel& model) {
EXPECT_EQ(1u, model.media_sinks.size());
const UIMediaSink& ui_sink = model.media_sinks[0];
EXPECT_EQ(sink.id(), ui_sink.id);
EXPECT_EQ(UIMediaSinkState::CONNECTED, ui_sink.state);
EXPECT_EQ(static_cast<int>(UICastAction::STOP),
ui_sink.allowed_actions);
EXPECT_EQ(route.media_route_id(), ui_sink.route_id);
})));
ui_->OnRoutesUpdated({route}, {});
EXPECT_CALL(observer, OnControllerInvalidated());
ui_.reset();
}
TEST_F(MediaRouterViewsUITest, StartCasting) {
MediaSource media_source =
MediaSourceForTab(SessionTabHelper::IdForTab(web_contents()).id());
EXPECT_CALL(mock_router_,
CreateRouteInternal(media_source.id(), kSinkId, _, web_contents(),
_, base::TimeDelta::FromSeconds(60), false));
MediaSink sink(kSinkId, kSinkName, SinkIconType::GENERIC);
for (MediaSinksObserver* observer : media_sinks_observers_)
observer->OnSinksUpdated({sink}, std::vector<url::Origin>());
ui_->StartCasting(kSinkId, MediaCastMode::TAB_MIRROR);
}
TEST_F(MediaRouterViewsUITest, StopCasting) {
EXPECT_CALL(mock_router_, TerminateRoute(kRouteId));
ui_->StopCasting(kRouteId);
}
} // namespace media_router
...@@ -698,7 +698,7 @@ void MediaRouterWebUIMessageHandler::OnCloseRoute(const base::ListValue* args) { ...@@ -698,7 +698,7 @@ void MediaRouterWebUIMessageHandler::OnCloseRoute(const base::ListValue* args) {
DVLOG(1) << "Unable to extract args."; DVLOG(1) << "Unable to extract args.";
return; return;
} }
media_router_ui_->CloseRoute(route_id); media_router_ui_->TerminateRoute(route_id);
UMA_HISTOGRAM_BOOLEAN("MediaRouter.Ui.Action.StopRoute", !is_local); UMA_HISTOGRAM_BOOLEAN("MediaRouter.Ui.Action.StopRoute", !is_local);
} }
......
...@@ -4250,6 +4250,7 @@ test("unit_tests") { ...@@ -4250,6 +4250,7 @@ test("unit_tests") {
"../browser/ui/views/hover_button_unittest.cc", "../browser/ui/views/hover_button_unittest.cc",
"../browser/ui/views/media_router/cast_dialog_sink_button_unittest.cc", "../browser/ui/views/media_router/cast_dialog_sink_button_unittest.cc",
"../browser/ui/views/media_router/cast_dialog_view_unittest.cc", "../browser/ui/views/media_router/cast_dialog_view_unittest.cc",
"../browser/ui/views/media_router/media_router_views_ui_unittest.cc",
"../browser/ui/views/page_info/page_info_bubble_view_unittest.cc", "../browser/ui/views/page_info/page_info_bubble_view_unittest.cc",
"../browser/ui/views/payments/payment_request_item_list_unittest.cc", "../browser/ui/views/payments/payment_request_item_list_unittest.cc",
"../browser/ui/views/payments/validating_textfield_unittest.cc", "../browser/ui/views/payments/validating_textfield_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment