Commit 00f4bfdf authored by Takumi Fujimoto's avatar Takumi Fujimoto Committed by Commit Bot

[Media Router] Update integration and E2E tests to use the test API

Update the tests to use the test UI API, which is implemented using the
Views Cast dialog, replacing the use of the WebUI dialog. Some changes
are made to the test UI API to better suit the needs of the tests.

This re-enables many tests that were previously disabled for being flaky.

Local file casting tests (5 test cases) are disabled in this CL, and
will be implemented in a later CL:
DISABLED_OpenLocalMediaFileInCurrentTab
DISABLED_OpenLocalMediaFileInNewTab
DISABLED_OpenLocalMediaFileFailsAndShowsIssue
DISABLED_OpenLocalMediaFileFullscreen
DISABLED_OpenLocalMediaFileCastFailNoFullscreen

The following tests are still flaky, so they are marked MANUAL and will
be run only on the private waterfall until they are fixed:
MediaRouterIntegrationBrowserTest.MANUAL_Fail_NoProvider
MediaRouterIntegrationBrowserTest.MANUAL_Dialog_Basic
MediaRouterIntegrationBrowserTest.MANUAL_Dialog_RouteCreationTimedOut
MediaRouterIntegrationOneUABrowserTest.MANUAL_SendAndOnMessage
MediaRouterIntegrationOneUABrowserTest.MANUAL_ReceiverCloseConnection

Bug: 900248
Change-Id: Ie328fd1c4b606a7f8291d8d22b7d83a89f1ee666
Reviewed-on: https://chromium-review.googlesource.com/c/1338226
Commit-Queue: Takumi Fujimoto <takumif@chromium.org>
Reviewed-by: default avatarmark a. foltz <mfoltz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611479}
parent 80bfd587
...@@ -253,7 +253,7 @@ bool MediaRouterUIBase::CreateRoute(const MediaSink::Id& sink_id, ...@@ -253,7 +253,7 @@ bool MediaRouterUIBase::CreateRoute(const MediaSink::Id& sink_id,
params = GetRouteParameters(sink_id, cast_mode); params = GetRouteParameters(sink_id, cast_mode);
} }
if (!params) { if (!params) {
SendIssueForUnableToCast(cast_mode); SendIssueForUnableToCast(cast_mode, sink_id);
return false; return false;
} }
...@@ -406,6 +406,10 @@ void MediaRouterUIBase::OnRouteResponseReceived( ...@@ -406,6 +406,10 @@ void MediaRouterUIBase::OnRouteResponseReceived(
} }
current_route_request_.reset(); current_route_request_.reset();
if (result.result_code() == RouteRequestResult::TIMED_OUT) {
SendIssueForRouteTimeout(cast_mode, sink_id,
presentation_request_source_name);
}
} }
void MediaRouterUIBase::HandleCreateSessionRequestRouteResponse( void MediaRouterUIBase::HandleCreateSessionRequestRouteResponse(
...@@ -582,6 +586,7 @@ GURL MediaRouterUIBase::GetFrameURL() const { ...@@ -582,6 +586,7 @@ GURL MediaRouterUIBase::GetFrameURL() const {
void MediaRouterUIBase::SendIssueForRouteTimeout( void MediaRouterUIBase::SendIssueForRouteTimeout(
MediaCastMode cast_mode, MediaCastMode cast_mode,
const MediaSink::Id& sink_id,
const base::string16& presentation_request_source_name) { const base::string16& presentation_request_source_name) {
std::string issue_title; std::string issue_title;
switch (cast_mode) { switch (cast_mode) {
...@@ -606,11 +611,14 @@ void MediaRouterUIBase::SendIssueForRouteTimeout( ...@@ -606,11 +611,14 @@ void MediaRouterUIBase::SendIssueForRouteTimeout(
break; break;
} }
AddIssue(IssueInfo(issue_title, IssueInfo::Action::DISMISS, IssueInfo issue_info(issue_title, IssueInfo::Action::DISMISS,
IssueInfo::Severity::NOTIFICATION)); IssueInfo::Severity::NOTIFICATION);
issue_info.sink_id = sink_id;
AddIssue(issue_info);
} }
void MediaRouterUIBase::SendIssueForUnableToCast(MediaCastMode cast_mode) { void MediaRouterUIBase::SendIssueForUnableToCast(MediaCastMode cast_mode,
const MediaSink::Id& sink_id) {
// For a generic error, claim a tab error unless it was specifically desktop // For a generic error, claim a tab error unless it was specifically desktop
// mirroring. // mirroring.
std::string issue_title = std::string issue_title =
...@@ -619,8 +627,10 @@ void MediaRouterUIBase::SendIssueForUnableToCast(MediaCastMode cast_mode) { ...@@ -619,8 +627,10 @@ void MediaRouterUIBase::SendIssueForUnableToCast(MediaCastMode cast_mode) {
IDS_MEDIA_ROUTER_ISSUE_UNABLE_TO_CAST_DESKTOP) IDS_MEDIA_ROUTER_ISSUE_UNABLE_TO_CAST_DESKTOP)
: l10n_util::GetStringUTF8( : l10n_util::GetStringUTF8(
IDS_MEDIA_ROUTER_ISSUE_CREATE_ROUTE_TIMEOUT_FOR_TAB); IDS_MEDIA_ROUTER_ISSUE_CREATE_ROUTE_TIMEOUT_FOR_TAB);
AddIssue(IssueInfo(issue_title, IssueInfo::Action::DISMISS, IssueInfo issue_info(issue_title, IssueInfo::Action::DISMISS,
IssueInfo::Severity::WARNING)); IssueInfo::Severity::WARNING);
issue_info.sink_id = sink_id;
AddIssue(issue_info);
} }
IssueManager* MediaRouterUIBase::GetIssueManager() { IssueManager* MediaRouterUIBase::GetIssueManager() {
......
...@@ -197,10 +197,13 @@ class MediaRouterUIBase ...@@ -197,10 +197,13 @@ class MediaRouterUIBase
// Creates and sends an issue if route creation timed out. // Creates and sends an issue if route creation timed out.
void SendIssueForRouteTimeout( void SendIssueForRouteTimeout(
MediaCastMode cast_mode, MediaCastMode cast_mode,
const MediaSink::Id& sink_id,
const base::string16& presentation_request_source_name); const base::string16& presentation_request_source_name);
// Creates and sends an issue if casting fails for any other reason. // Creates and sends an issue if casting fails for any reason other than
void SendIssueForUnableToCast(MediaCastMode cast_mode); // timeout.
void SendIssueForUnableToCast(MediaCastMode cast_mode,
const MediaSink::Id& sink_id);
// Returns the IssueManager associated with |router_|. // Returns the IssueManager associated with |router_|.
IssueManager* GetIssueManager(); IssueManager* GetIssueManager();
......
...@@ -225,6 +225,11 @@ void CastDialogView::RemoveObserver(Observer* observer) { ...@@ -225,6 +225,11 @@ void CastDialogView::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
void CastDialogView::KeepShownForTesting() {
keep_shown_for_testing_ = true;
set_close_on_deactivate(false);
}
// static // static
void CastDialogView::ShowDialog(views::View* anchor_view, void CastDialogView::ShowDialog(views::View* anchor_view,
views::BubbleBorder::Arrow anchor_position, views::BubbleBorder::Arrow anchor_position,
...@@ -382,21 +387,22 @@ void CastDialogView::SinkPressed(size_t index) { ...@@ -382,21 +387,22 @@ void CastDialogView::SinkPressed(size_t index) {
selected_sink_index_ = index; selected_sink_index_ = index;
const UIMediaSink& sink = sink_buttons_.at(index)->sink(); const UIMediaSink& sink = sink_buttons_.at(index)->sink();
if (sink.route) { if (sink.route) {
controller_->StopCasting(sink.route->media_route_id());
metrics_.OnStopCasting(sink.route->is_local()); metrics_.OnStopCasting(sink.route->is_local());
// StopCasting() may trigger a model update and invalidate |sink|.
controller_->StopCasting(sink.route->media_route_id());
} else { } else {
base::Optional<MediaCastMode> cast_mode = GetCastModeToUse(sink); base::Optional<MediaCastMode> cast_mode = GetCastModeToUse(sink);
if (cast_mode) { if (cast_mode) {
// Starting local file casting may open a new tab synchronously on the UI // Starting local file casting may open a new tab synchronously on the UI
// thread, which deactivates the dialog. So we must prevent it from // thread, which deactivates the dialog. So we must prevent it from
// closing and getting destroyed. // closing and getting destroyed.
if (cast_mode == LOCAL_FILE) if (cast_mode.value() == LOCAL_FILE)
set_close_on_deactivate(false); set_close_on_deactivate(false);
controller_->StartCasting(sink.id, cast_mode.value()); controller_->StartCasting(sink.id, cast_mode.value());
// Re-enable close on deactivate so the user can click elsewhere to close // Re-enable close on deactivate so the user can click elsewhere to close
// the dialog. // the dialog.
if (cast_mode == LOCAL_FILE) if (cast_mode.value() == LOCAL_FILE)
set_close_on_deactivate(true); set_close_on_deactivate(!keep_shown_for_testing_);
metrics_.OnStartCasting(base::Time::Now(), index); metrics_.OnStartCasting(base::Time::Now(), index);
} }
} }
...@@ -454,7 +460,7 @@ void CastDialogView::RecordSinkCount() { ...@@ -454,7 +460,7 @@ void CastDialogView::RecordSinkCount() {
void CastDialogView::OnFilePickerClosed(const ui::SelectedFileInfo* file_info) { void CastDialogView::OnFilePickerClosed(const ui::SelectedFileInfo* file_info) {
// Re-enable the setting to close the dialog when it loses focus. // Re-enable the setting to close the dialog when it loses focus.
set_close_on_deactivate(true); set_close_on_deactivate(!keep_shown_for_testing_);
if (file_info) { if (file_info) {
#if defined(OS_WIN) #if defined(OS_WIN)
local_file_name_ = file_info->display_name; local_file_name_ = file_info->display_name;
......
...@@ -100,6 +100,11 @@ class CastDialogView : public views::BubbleDialogDelegateView, ...@@ -100,6 +100,11 @@ class CastDialogView : public views::BubbleDialogDelegateView,
void AddObserver(Observer* observer); void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer); void RemoveObserver(Observer* observer);
// If the dialog loses focus during a test and closes, the test can
// fail unexpectedly. This method prevents that by keeping the dialog from
// closing on blur.
void KeepShownForTesting();
// Called by tests. // Called by tests.
const std::vector<CastDialogSinkButton*>& sink_buttons_for_test() const { const std::vector<CastDialogSinkButton*>& sink_buttons_for_test() const {
return sink_buttons_; return sink_buttons_;
...@@ -226,6 +231,9 @@ class CastDialogView : public views::BubbleDialogDelegateView, ...@@ -226,6 +231,9 @@ class CastDialogView : public views::BubbleDialogDelegateView,
base::ObserverList<Observer> observers_; base::ObserverList<Observer> observers_;
// When this is set to true, the dialog does not close on blur.
bool keep_shown_for_testing_ = false;
base::WeakPtrFactory<CastDialogView> weak_factory_; base::WeakPtrFactory<CastDialogView> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CastDialogView); DISALLOW_COPY_AND_ASSIGN(CastDialogView);
......
...@@ -70,25 +70,15 @@ CastToolbarButton::CastToolbarButton( ...@@ -70,25 +70,15 @@ CastToolbarButton::CastToolbarButton(
ToolbarButton::Init(); ToolbarButton::Init();
IssuesObserver::Init(); IssuesObserver::Init();
MediaRouterActionController* controller =
MediaRouterUIService::Get(profile_)->action_controller();
controller->AddObserver(this);
SetVisible(controller->ShouldEnableAction());
}
CastToolbarButton::~CastToolbarButton() { DCHECK(GetActionController());
MediaRouterUIService::Get(profile_)->action_controller()->RemoveObserver( GetActionController()->AddObserver(this);
this); SetVisible(GetActionController()->ShouldEnableAction());
} }
void CastToolbarButton::UpdateIcon() { CastToolbarButton::~CastToolbarButton() {
const gfx::VectorIcon& icon = GetCurrentIcon(); if (GetActionController())
SetImage(views::Button::STATE_NORMAL, GetActionController()->RemoveObserver(this);
gfx::CreateVectorIcon(icon, GetIconColor(&icon)));
// This icon is smaller than the touchable-UI expected 24dp, so we need to pad
// the insets to match.
SetLayoutInsetDelta(
gfx::Insets(ui::MaterialDesignController::touch_ui() ? 4 : 0));
} }
const gfx::VectorIcon& CastToolbarButton::GetCurrentIcon() const { const gfx::VectorIcon& CastToolbarButton::GetCurrentIcon() const {
...@@ -150,21 +140,15 @@ void CastToolbarButton::OnRoutesUpdated( ...@@ -150,21 +140,15 @@ void CastToolbarButton::OnRoutesUpdated(
} }
bool CastToolbarButton::OnMousePressed(const ui::MouseEvent& event) { bool CastToolbarButton::OnMousePressed(const ui::MouseEvent& event) {
if (event.IsRightMouseButton()) { if (event.IsRightMouseButton() && GetActionController())
MediaRouterUIService::Get(profile_) GetActionController()->KeepIconOnRightMousePressed();
->action_controller()
->KeepIconOnRightMousePressed();
}
return ToolbarButton::OnMousePressed(event); return ToolbarButton::OnMousePressed(event);
} }
void CastToolbarButton::OnMouseReleased(const ui::MouseEvent& event) { void CastToolbarButton::OnMouseReleased(const ui::MouseEvent& event) {
ToolbarButton::OnMouseReleased(event); ToolbarButton::OnMouseReleased(event);
if (event.IsRightMouseButton()) { if (event.IsRightMouseButton() && GetActionController())
MediaRouterUIService::Get(profile_) GetActionController()->MaybeHideIconOnRightMouseReleased();
->action_controller()
->MaybeHideIconOnRightMouseReleased();
}
} }
void CastToolbarButton::ButtonPressed(views::Button* sender, void CastToolbarButton::ButtonPressed(views::Button* sender,
...@@ -181,4 +165,18 @@ void CastToolbarButton::ButtonPressed(views::Button* sender, ...@@ -181,4 +165,18 @@ void CastToolbarButton::ButtonPressed(views::Button* sender,
} }
} }
void CastToolbarButton::UpdateIcon() {
const gfx::VectorIcon& icon = GetCurrentIcon();
SetImage(views::Button::STATE_NORMAL,
gfx::CreateVectorIcon(icon, GetIconColor(&icon)));
// This icon is smaller than the touchable-UI expected 24dp, so we need to pad
// the insets to match.
SetLayoutInsetDelta(
gfx::Insets(ui::MaterialDesignController::touch_ui() ? 4 : 0));
}
MediaRouterActionController* CastToolbarButton::GetActionController() const {
return MediaRouterUIService::Get(profile_)->action_controller();
}
} // namespace media_router } // namespace media_router
...@@ -70,6 +70,8 @@ class CastToolbarButton : public ToolbarButton, ...@@ -70,6 +70,8 @@ class CastToolbarButton : public ToolbarButton,
private: private:
const gfx::VectorIcon& GetCurrentIcon() const; const gfx::VectorIcon& GetCurrentIcon() const;
MediaRouterActionController* GetActionController() const;
Browser* const browser_; Browser* const browser_;
Profile* const profile_; Profile* const profile_;
......
...@@ -65,6 +65,8 @@ void MediaRouterDialogControllerViews::CreateMediaRouterDialog() { ...@@ -65,6 +65,8 @@ void MediaRouterDialogControllerViews::CreateMediaRouterDialog() {
dialog_creation_time); dialog_creation_time);
} }
CastDialogView::GetCurrentDialogWidget()->AddObserver(this); CastDialogView::GetCurrentDialogWidget()->AddObserver(this);
if (dialog_creation_callback_)
dialog_creation_callback_.Run();
} }
void MediaRouterDialogControllerViews::CloseMediaRouterDialog() { void MediaRouterDialogControllerViews::CloseMediaRouterDialog() {
...@@ -76,8 +78,11 @@ bool MediaRouterDialogControllerViews::IsShowingMediaRouterDialog() const { ...@@ -76,8 +78,11 @@ bool MediaRouterDialogControllerViews::IsShowingMediaRouterDialog() const {
} }
void MediaRouterDialogControllerViews::Reset() { void MediaRouterDialogControllerViews::Reset() {
// If |ui_| is null, Reset() has already been called.
if (ui_) {
MediaRouterDialogControllerImplBase::Reset(); MediaRouterDialogControllerImplBase::Reset();
ui_.reset(); ui_.reset();
}
} }
void MediaRouterDialogControllerViews::OnWidgetClosing(views::Widget* widget) { void MediaRouterDialogControllerViews::OnWidgetClosing(views::Widget* widget) {
...@@ -90,6 +95,11 @@ void MediaRouterDialogControllerViews::OnWidgetDestroying( ...@@ -90,6 +95,11 @@ void MediaRouterDialogControllerViews::OnWidgetDestroying(
widget->RemoveObserver(this); widget->RemoveObserver(this);
} }
void MediaRouterDialogControllerViews::SetDialogCreationCallbackForTesting(
base::RepeatingClosure callback) {
dialog_creation_callback_ = std::move(callback);
}
MediaRouterDialogControllerViews::MediaRouterDialogControllerViews( MediaRouterDialogControllerViews::MediaRouterDialogControllerViews(
content::WebContents* web_contents) content::WebContents* web_contents)
: MediaRouterDialogControllerImplBase(web_contents) {} : MediaRouterDialogControllerImplBase(web_contents) {}
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.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 "chrome/browser/ui/views/media_router/media_router_views_ui.h" #include "chrome/browser/ui/views/media_router/media_router_views_ui.h"
#include "ui/views/widget/widget_observer.h" #include "ui/views/widget/widget_observer.h"
...@@ -35,6 +36,9 @@ class MediaRouterDialogControllerViews ...@@ -35,6 +36,9 @@ class MediaRouterDialogControllerViews
void OnWidgetClosing(views::Widget* widget) override; void OnWidgetClosing(views::Widget* widget) override;
void OnWidgetDestroying(views::Widget* widget) override; void OnWidgetDestroying(views::Widget* widget) override;
// Sets a callback to be called whenever a dialog is created.
void SetDialogCreationCallbackForTesting(base::RepeatingClosure callback);
private: private:
friend class content::WebContentsUserData<MediaRouterDialogControllerViews>; friend class content::WebContentsUserData<MediaRouterDialogControllerViews>;
...@@ -47,6 +51,8 @@ class MediaRouterDialogControllerViews ...@@ -47,6 +51,8 @@ class MediaRouterDialogControllerViews
// closed. // closed.
std::unique_ptr<MediaRouterViewsUI> ui_; std::unique_ptr<MediaRouterViewsUI> ui_;
base::RepeatingClosure dialog_creation_callback_;
DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogControllerViews); DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogControllerViews);
}; };
......
...@@ -102,7 +102,7 @@ bool MediaRouterUI::ConnectRoute(const MediaSink::Id& sink_id, ...@@ -102,7 +102,7 @@ bool MediaRouterUI::ConnectRoute(const MediaSink::Id& sink_id,
base::Optional<RouteParameters> params = base::Optional<RouteParameters> params =
GetRouteParameters(sink_id, MediaCastMode::PRESENTATION); GetRouteParameters(sink_id, MediaCastMode::PRESENTATION);
if (!params) { if (!params) {
SendIssueForUnableToCast(MediaCastMode::PRESENTATION); SendIssueForUnableToCast(MediaCastMode::PRESENTATION, sink_id);
return false; return false;
} }
GetIssueManager()->ClearNonBlockingIssues(); GetIssueManager()->ClearNonBlockingIssues();
...@@ -315,8 +315,6 @@ void MediaRouterUI::OnRouteResponseReceived( ...@@ -315,8 +315,6 @@ void MediaRouterUI::OnRouteResponseReceived(
route_request_id, sink_id, cast_mode, presentation_request_source_name, route_request_id, sink_id, cast_mode, presentation_request_source_name,
result); result);
handler_->OnCreateRouteResponseReceived(sink_id, result.route()); handler_->OnCreateRouteResponseReceived(sink_id, result.route());
if (result.result_code() == RouteRequestResult::TIMED_OUT)
SendIssueForRouteTimeout(cast_mode, presentation_request_source_name);
} }
void MediaRouterUI::HandleCreateSessionRequestRouteResponse( void MediaRouterUI::HandleCreateSessionRequestRouteResponse(
......
...@@ -42,7 +42,7 @@ void MediaRouterBaseBrowserTest::SetUp() { ...@@ -42,7 +42,7 @@ void MediaRouterBaseBrowserTest::SetUp() {
ParseCommandLine(); ParseCommandLine();
// The integration and E2E tests depend on the WebUI Cast dialog, so the Views // The integration and E2E tests depend on the WebUI Cast dialog, so the Views
// dialog must be disabled. // dialog must be disabled.
feature_list_.InitAndDisableFeature(features::kViewsCastDialog); feature_list_.InitAndEnableFeature(features::kViewsCastDialog);
ExtensionBrowserTest::SetUp(); ExtensionBrowserTest::SetUp();
} }
......
...@@ -81,7 +81,7 @@ void MediaRouterE2EBrowserTest::CreateMediaRoute( ...@@ -81,7 +81,7 @@ void MediaRouterE2EBrowserTest::CreateMediaRoute(
observer_.reset(new TestMediaSinksObserver(media_router_, source, origin)); observer_.reset(new TestMediaSinksObserver(media_router_, source, origin));
observer_->Init(); observer_->Init();
DVLOG(1) << "Receiver name: " << receiver(); DVLOG(1) << "Receiver name: " << receiver_;
// Wait for MediaSinks compatible with |source| to be discovered. // Wait for MediaSinks compatible with |source| to be discovered.
ASSERT_TRUE(ConditionalWait( ASSERT_TRUE(ConditionalWait(
base::TimeDelta::FromSeconds(30), base::TimeDelta::FromSeconds(1), base::TimeDelta::FromSeconds(30), base::TimeDelta::FromSeconds(1),
...@@ -89,7 +89,7 @@ void MediaRouterE2EBrowserTest::CreateMediaRoute( ...@@ -89,7 +89,7 @@ void MediaRouterE2EBrowserTest::CreateMediaRoute(
base::Unretained(this)))); base::Unretained(this))));
const auto& sink_map = observer_->sink_map; const auto& sink_map = observer_->sink_map;
const auto it = sink_map.find(receiver()); const auto it = sink_map.find(receiver_);
const MediaSink& sink = it->second; const MediaSink& sink = it->second;
// The callback will set route_id_ when invoked. // The callback will set route_id_ when invoked.
...@@ -112,7 +112,7 @@ void MediaRouterE2EBrowserTest::StopMediaRoute() { ...@@ -112,7 +112,7 @@ void MediaRouterE2EBrowserTest::StopMediaRoute() {
} }
bool MediaRouterE2EBrowserTest::IsSinkDiscovered() const { bool MediaRouterE2EBrowserTest::IsSinkDiscovered() const {
return base::ContainsKey(observer_->sink_map, receiver()); return base::ContainsKey(observer_->sink_map, receiver_);
} }
bool MediaRouterE2EBrowserTest::IsRouteCreated() const { bool MediaRouterE2EBrowserTest::IsRouteCreated() const {
......
...@@ -29,22 +29,15 @@ IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, ...@@ -29,22 +29,15 @@ IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest,
content::WebContents* web_contents = content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents(); browser()->tab_strip_model()->GetActiveWebContents();
content::WebContents* dialog_contents = OpenMRDialog(web_contents); test_ui_->ShowDialog();
ASSERT_TRUE(dialog_contents); test_ui_->WaitForSinkAvailable(receiver_);
// Wait util the dialog finishes rendering.
WaitUntilDialogFullyLoaded(dialog_contents);
// Get the media router UI
MediaRouterUI* media_router_ui = GetMediaRouterUI(dialog_contents);
// Mock out file dialog operations, as those can't be simulated. // Mock out file dialog operations, as those can't be simulated.
FileDialogSelectsFile(media_router_ui, file_url); FileDialogSelectsFile(file_url);
// Open the Cast mode list.
ClickHeader(dialog_contents);
// Click on the desired mode. // Click on the desired mode.
ClickCastMode(dialog_contents, MediaCastMode::LOCAL_FILE); test_ui_->ChooseSourceType(CastDialogView::kLocalFile);
WaitUntilSinkDiscoveredOnUI(); test_ui_->WaitForSinkAvailable(receiver_);
ChooseSink(web_contents, receiver()); test_ui_->StartCasting(receiver_);
// Play the file for 10 seconds. // Play the file for 10 seconds.
Wait(base::TimeDelta::FromSeconds(10)); Wait(base::TimeDelta::FromSeconds(10));
...@@ -61,9 +54,8 @@ IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, ...@@ -61,9 +54,8 @@ IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest,
&is_fullscreen)); &is_fullscreen));
ASSERT_TRUE(is_fullscreen); ASSERT_TRUE(is_fullscreen);
if (IsDialogClosed(web_contents)) test_ui_->WaitForSink(receiver_);
OpenMRDialog(web_contents); test_ui_->StopCasting(receiver_);
CloseRouteOnUI();
// Wait 15s for Chromecast to back to home screen and ready to use status. // Wait 15s for Chromecast to back to home screen and ready to use status.
Wait(base::TimeDelta::FromSeconds(15)); Wait(base::TimeDelta::FromSeconds(15));
} }
...@@ -71,23 +63,18 @@ IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, ...@@ -71,23 +63,18 @@ IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, MANUAL_MirrorHTML5Video) { IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, MANUAL_MirrorHTML5Video) {
content::WebContents* web_contents = content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents(); browser()->tab_strip_model()->GetActiveWebContents();
test_ui_ = MediaRouterUiForTest::GetOrCreateForWebContents(web_contents);
content::WebContents* dialog_contents = OpenMRDialog(web_contents); test_ui_->ShowDialog();
ASSERT_TRUE(dialog_contents);
// Wait until the dialog finishes rendering. // Wait until the dialog finishes rendering.
WaitUntilDialogFullyLoaded(dialog_contents); test_ui_->WaitForSinkAvailable(receiver_);
WaitUntilSinkDiscoveredOnUI(); test_ui_->StartCasting(receiver_);
ChooseSink(web_contents, receiver());
// Mirror tab for 10s. // Mirror tab for 10s.
Wait(base::TimeDelta::FromSeconds(10)); Wait(base::TimeDelta::FromSeconds(10));
if (IsDialogClosed(web_contents))
dialog_contents = OpenMRDialog(web_contents);
WaitUntilDialogFullyLoaded(dialog_contents);
// Check the mirroring session has started successfully. // Check the mirroring session has started successfully.
ASSERT_TRUE(!GetRouteId(receiver()).empty()); ASSERT_FALSE(test_ui_->GetRouteIdForSink(receiver_).empty());
OpenMediaPage(); OpenMediaPage();
// Play the video on loop and wait 5s for it to play smoothly. // Play the video on loop and wait 5s for it to play smoothly.
...@@ -101,16 +88,18 @@ IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, MANUAL_MirrorHTML5Video) { ...@@ -101,16 +88,18 @@ IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, MANUAL_MirrorHTML5Video) {
"webkitRequestFullScreen();"; "webkitRequestFullScreen();";
ExecuteScript(web_contents, script); ExecuteScript(web_contents, script);
Wait(base::TimeDelta::FromSeconds(5)); Wait(base::TimeDelta::FromSeconds(5));
if (IsDialogClosed(web_contents)) if (!test_ui_->IsDialogShown())
dialog_contents = OpenMRDialog(web_contents); test_ui_->ShowDialog();
WaitUntilDialogFullyLoaded(dialog_contents);
// Check the mirroring session is still live. // Check the mirroring session is still live.
ASSERT_TRUE(!GetRouteId(receiver()).empty()); ASSERT_FALSE(test_ui_->GetRouteIdForSink(receiver_).empty());
Wait(base::TimeDelta::FromSeconds(20)); Wait(base::TimeDelta::FromSeconds(20));
if (IsDialogClosed(web_contents)) if (!test_ui_->IsDialogShown())
OpenMRDialog(web_contents); test_ui_->ShowDialog();
CloseRouteOnUI(); test_ui_->WaitForSink(receiver_);
test_ui_->StopCasting(receiver_);
test_ui_->WaitUntilNoRoutes();
test_ui_->HideDialog();
} }
} // namespace media_router } // namespace media_router
...@@ -16,14 +16,11 @@ ...@@ -16,14 +16,11 @@
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/media_router/media_cast_mode.h" #include "chrome/browser/ui/media_router/media_cast_mode.h"
#include "chrome/browser/ui/media_router/media_router_file_dialog.h" #include "chrome/browser/ui/media_router/media_router_file_dialog.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/browser_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_ui.h"
#include "chrome/common/media_router/issue.h" #include "chrome/common/media_router/issue.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h" #include "chrome/test/base/ui_test_utils.h"
...@@ -63,66 +60,6 @@ const char kSendMessageAndExpectResponseScript[] = ...@@ -63,66 +60,6 @@ const char kSendMessageAndExpectResponseScript[] =
"sendMessageAndExpectResponse('%s');"; "sendMessageAndExpectResponse('%s');";
const char kSendMessageAndExpectConnectionCloseOnErrorScript[] = const char kSendMessageAndExpectConnectionCloseOnErrorScript[] =
"sendMessageAndExpectConnectionCloseOnError()"; "sendMessageAndExpectConnectionCloseOnError()";
const char kChooseSinkScript[] =
"var sinks = Array.from(document.getElementById('media-router-container')."
" shadowRoot.getElementById('sink-list').getElementsByTagName('span'));"
"var sink = sinks.find(sink => sink.textContent.trim() == '%s');"
"if (sink) {"
" sink.click();"
"}";
const char kClickCastModeScript[] =
"var mediaRouterContainer ="
" document.getElementById('media-router-container');"
"var modes = Array.from(mediaRouterContainer"
" .shadowRoot"
" .getElementById('cast-mode-list')"
" .getElementsByTagName('span'));"
"var mode = modes.find(mode => {"
" return mode.textContent.trim() == mediaRouterContainer"
" .castModeList.find(mode => mode.type == %d).description;"
" });"
"if (mode) {"
" mode.click();"
"}";
const char kCloseRouteScript[] =
"window.document.getElementById('media-router-container').shadowRoot."
" getElementById('route-details').shadowRoot.getElementById("
" 'close-route-button').click()";
const char kClickDialog[] =
"window.document.getElementById('media-router-container').click();";
const char kClickHeader[] =
"window.document.getElementById('media-router-container').shadowRoot"
".getElementById('container-header').shadowRoot"
".getElementById('header-text').click();";
const char kGetSinkIdScript[] =
"var sinks = window.document.getElementById('media-router-container')."
" allSinks;"
"var sink = sinks.find(sink => sink.name == '%s');"
"window.domAutomationController.send(sink ? sink.id : '');";
const char kGetRouteIdScript[] =
"var routes = window.document.getElementById('media-router-container')."
" routeList;"
"var route = routes.find(route => route.sinkId == '%s');"
"window.domAutomationController.send(route ? route.id : '');";
const char kFindSinkScript[] =
"var sinkList = document.getElementById('media-router-container')."
" shadowRoot.getElementById('sink-list');"
"if (!sinkList) {"
" window.domAutomationController.send(false);"
"} else {"
" var sinks = Array.from(sinkList.getElementsByTagName('span'));"
" var result = sinks.some(sink => sink.textContent.trim() == '%s');"
" window.domAutomationController.send(result);"
"}";
const char kCheckDialogLoadedScript[] =
"var container = document.getElementById('media-router-container');"
"/** Wait until media router container is not undefined and "
"* deviceMissingUrl is not undefined, "
"* once deviceMissingUrl is not undefined, which means "
"* the dialog is fully loaded."
"*/"
"window.domAutomationController.send(!!container && "
" !!container.deviceMissingUrl);";
std::string GetStartedConnectionId(WebContents* web_contents) { std::string GetStartedConnectionId(WebContents* web_contents) {
std::string session_id; std::string session_id;
...@@ -141,7 +78,7 @@ std::string GetDefaultRequestSessionId(WebContents* web_contents) { ...@@ -141,7 +78,7 @@ std::string GetDefaultRequestSessionId(WebContents* web_contents) {
return session_id; return session_id;
} }
// File Dialog which fails on open // File Dialog which fails on open.
class TestFailMediaRouterFileDialog : public MediaRouterFileDialog { class TestFailMediaRouterFileDialog : public MediaRouterFileDialog {
public: public:
TestFailMediaRouterFileDialog(MediaRouterFileDialogDelegate* delegate, TestFailMediaRouterFileDialog(MediaRouterFileDialogDelegate* delegate,
...@@ -193,6 +130,13 @@ void MediaRouterIntegrationBrowserTest::SetUpInProcessBrowserTestFixture() { ...@@ -193,6 +130,13 @@ void MediaRouterIntegrationBrowserTest::SetUpInProcessBrowserTestFixture() {
policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
} }
void MediaRouterIntegrationBrowserTest::SetUpOnMainThread() {
MediaRouterBaseBrowserTest::SetUpOnMainThread();
// Dialogs created while MediaRouterUiForTest exists will not close on blur.
test_ui_ =
MediaRouterUiForTest::GetOrCreateForWebContents(GetActiveWebContents());
}
void MediaRouterIntegrationBrowserTest::ExecuteJavaScriptAPI( void MediaRouterIntegrationBrowserTest::ExecuteJavaScriptAPI(
WebContents* web_contents, WebContents* web_contents,
const std::string& script) { const std::string& script) {
...@@ -221,11 +165,11 @@ void MediaRouterIntegrationBrowserTest::StartSessionAndAssertNotFoundError() { ...@@ -221,11 +165,11 @@ void MediaRouterIntegrationBrowserTest::StartSessionAndAssertNotFoundError() {
OpenTestPage(FILE_PATH_LITERAL("basic_test.html")); OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
WebContents* web_contents = GetActiveWebContents(); WebContents* web_contents = GetActiveWebContents();
CHECK(web_contents); CHECK(web_contents);
StartSession(web_contents); ExecuteJavaScriptAPI(web_contents, kStartSessionScript);
// Wait for any sinks to be displayed. // Wait to simulate the user waiting for any sinks to be displayed.
Wait(base::TimeDelta::FromSeconds(1)); Wait(base::TimeDelta::FromSeconds(1));
GetControllerForShownDialog(web_contents)->HideMediaRouterDialog(); test_ui_->HideDialog();
CheckStartFailed(web_contents, "NotFoundError", "No screens found."); CheckStartFailed(web_contents, "NotFoundError", "No screens found.");
} }
...@@ -235,19 +179,20 @@ MediaRouterIntegrationBrowserTest::StartSessionWithTestPageAndSink() { ...@@ -235,19 +179,20 @@ MediaRouterIntegrationBrowserTest::StartSessionWithTestPageAndSink() {
WebContents* web_contents = GetActiveWebContents(); WebContents* web_contents = GetActiveWebContents();
CHECK(web_contents); CHECK(web_contents);
ExecuteJavaScriptAPI(web_contents, kWaitSinkScript); ExecuteJavaScriptAPI(web_contents, kWaitSinkScript);
StartSession(web_contents); ExecuteJavaScriptAPI(web_contents, kStartSessionScript);
test_ui_->WaitForDialogShown();
return web_contents; return web_contents;
} }
WebContents* WebContents*
MediaRouterIntegrationBrowserTest::StartSessionWithTestPageAndChooseSink() { MediaRouterIntegrationBrowserTest::StartSessionWithTestPageAndChooseSink() {
WebContents* web_contents = StartSessionWithTestPageAndSink(); WebContents* web_contents = StartSessionWithTestPageAndSink();
WaitUntilSinkDiscoveredOnUI(); test_ui_->WaitForSinkAvailable(receiver_);
ChooseSink(web_contents, receiver_); test_ui_->StartCasting(receiver_);
// TODO(takumif): Remove the HideDialog() call once the dialog can close
// itself automatically after casting.
test_ui_->HideDialog();
// Wait a few seconds for MediaRouter to receive updates containing the
// created route.
Wait(base::TimeDelta::FromSeconds(3));
return web_contents; return web_contents;
} }
...@@ -258,22 +203,15 @@ void MediaRouterIntegrationBrowserTest::OpenDialogAndCastFile( ...@@ -258,22 +203,15 @@ void MediaRouterIntegrationBrowserTest::OpenDialogAndCastFile(
: SetTestData(FILE_PATH_LITERAL("local_media_sink_route_fail.json")); : SetTestData(FILE_PATH_LITERAL("local_media_sink_route_fail.json"));
GURL file_url = net::FilePathToFileURL( GURL file_url = net::FilePathToFileURL(
media::GetTestDataFilePath("butterfly-853x480.webm")); media::GetTestDataFilePath("butterfly-853x480.webm"));
// Open the dialog, waits for it to load test_ui_->ShowDialog();
WebContents* dialog_contents = OpenMRDialog(GetActiveWebContents());
// Get the media router UI
MediaRouterUI* media_router_ui = GetMediaRouterUI(dialog_contents);
// Mock out file dialog operations, as those can't be simulated. // Mock out file dialog operations, as those can't be simulated.
FileDialogSelectsFile(media_router_ui, file_url); FileDialogSelectsFile(file_url);
// Open the Cast mode list.
ClickHeader(dialog_contents);
// Click on the desired mode. // Click on the desired mode.
ClickCastMode(dialog_contents, MediaCastMode::LOCAL_FILE); test_ui_->ChooseSourceType(CastDialogView::kLocalFile);
// Wait for the sinks to load. // Wait for the sinks to load.
WaitUntilSinkDiscoveredOnUI(); test_ui_->WaitForSinkAvailable(receiver_);
// Click on sink. // Click on sink.
ChooseSink(GetActiveWebContents(), receiver_); test_ui_->StartCasting(receiver_);
// Give casting a few seconds to go through.
Wait(base::TimeDelta::FromSeconds(3));
// Expect that the current tab has the file open in it. // Expect that the current tab has the file open in it.
ASSERT_EQ(file_url, GetActiveWebContents()->GetURL()); ASSERT_EQ(file_url, GetActiveWebContents()->GetURL());
} }
...@@ -282,18 +220,13 @@ void MediaRouterIntegrationBrowserTest::OpenDialogAndCastFileFails() { ...@@ -282,18 +220,13 @@ void MediaRouterIntegrationBrowserTest::OpenDialogAndCastFileFails() {
SetTestData(FILE_PATH_LITERAL("local_media_sink.json")); SetTestData(FILE_PATH_LITERAL("local_media_sink.json"));
GURL file_url = net::FilePathToFileURL( GURL file_url = net::FilePathToFileURL(
media::GetTestDataFilePath("butterfly-853x480.webm")); media::GetTestDataFilePath("butterfly-853x480.webm"));
// Open the dialog, waits for it to load test_ui_->ShowDialog();
WebContents* dialog_contents = OpenMRDialog(GetActiveWebContents());
// Get the media router UI
MediaRouterUI* media_router_ui = GetMediaRouterUI(dialog_contents);
// Mock out file dialog opperations, as those can't be simulated. // Mock out file dialog opperations, as those can't be simulated.
FileDialogSelectFails(media_router_ui, IssueInfo()); FileDialogSelectFails(IssueInfo());
// Open the Cast mode list.
ClickHeader(dialog_contents);
// Click on the desired mode. // Click on the desired mode.
ClickCastMode(dialog_contents, MediaCastMode::LOCAL_FILE); test_ui_->ChooseSourceType(CastDialogView::kLocalFile);
// Wait for the issue to appear. // Wait for the issue to appear.
WaitUntilIssue(); test_ui_->WaitForAnyIssue();
} }
void MediaRouterIntegrationBrowserTest::OpenTestPage( void MediaRouterIntegrationBrowserTest::OpenTestPage(
...@@ -309,6 +242,10 @@ void MediaRouterIntegrationBrowserTest::OpenTestPageInNewTab( ...@@ -309,6 +242,10 @@ void MediaRouterIntegrationBrowserTest::OpenTestPageInNewTab(
browser(), GetTestPageUrl(full_path), browser(), GetTestPageUrl(full_path),
WindowOpenDisposition::NEW_FOREGROUND_TAB, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
// Opening a new tab creates new WebContents, so we must re-configure the
// test UI for it.
test_ui_ =
MediaRouterUiForTest::GetOrCreateForWebContents(GetActiveWebContents());
} }
GURL MediaRouterIntegrationBrowserTest::GetTestPageUrl( GURL MediaRouterIntegrationBrowserTest::GetTestPageUrl(
...@@ -316,34 +253,6 @@ GURL MediaRouterIntegrationBrowserTest::GetTestPageUrl( ...@@ -316,34 +253,6 @@ GURL MediaRouterIntegrationBrowserTest::GetTestPageUrl(
return net::FilePathToFileURL(full_path); return net::FilePathToFileURL(full_path);
} }
void MediaRouterIntegrationBrowserTest::StartSession(
WebContents* web_contents) {
test_navigation_observer_.reset(
new content::TestNavigationObserver(web_contents, 1));
test_navigation_observer_->StartWatchingNewWebContents();
ExecuteJavaScriptAPI(web_contents, kStartSessionScript);
test_navigation_observer_->Wait();
test_navigation_observer_->StopWatchingNewWebContents();
}
void MediaRouterIntegrationBrowserTest::ChooseSink(
WebContents* web_contents,
const std::string& sink_name) {
WebContents* dialog_contents = GetMRDialog(web_contents);
std::string script = base::StringPrintf(
kChooseSinkScript, sink_name.c_str());
// Execute javascript to choose sink, but don't wait until it finishes.
dialog_contents->GetMainFrame()->ExecuteJavaScriptWithUserGestureForTests(
base::UTF8ToUTF16(script));
}
void MediaRouterIntegrationBrowserTest::ClickCastMode(
WebContents* dialog_contents,
MediaCastMode mode) {
std::string script = base::StringPrintf(kClickCastModeScript, mode);
ASSERT_TRUE(content::ExecuteScript(dialog_contents, script));
}
void MediaRouterIntegrationBrowserTest::CheckStartFailed( void MediaRouterIntegrationBrowserTest::CheckStartFailed(
WebContents* web_contents, WebContents* web_contents,
const std::string& error_name, const std::string& error_name,
...@@ -354,52 +263,6 @@ void MediaRouterIntegrationBrowserTest::CheckStartFailed( ...@@ -354,52 +263,6 @@ void MediaRouterIntegrationBrowserTest::CheckStartFailed(
ExecuteJavaScriptAPI(web_contents, script); ExecuteJavaScriptAPI(web_contents, script);
} }
void MediaRouterIntegrationBrowserTest::ClickDialog() {
WebContents* web_contents = GetActiveWebContents();
WebContents* dialog_contents = GetMRDialog(web_contents);
ASSERT_TRUE(content::ExecuteScript(dialog_contents, kClickDialog));
}
void MediaRouterIntegrationBrowserTest::ClickHeader(
WebContents* dialog_contents) {
ASSERT_TRUE(content::ExecuteScript(dialog_contents, kClickHeader));
}
WebContents* MediaRouterIntegrationBrowserTest::GetMRDialog(
WebContents* web_contents) {
MediaRouterDialogControllerWebUIImpl* controller =
MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents(
web_contents);
WebContents* dialog_contents = controller->GetMediaRouterDialog();
CHECK(dialog_contents);
WaitUntilDialogFullyLoaded(dialog_contents);
return dialog_contents;
}
bool MediaRouterIntegrationBrowserTest::IsDialogClosed(
WebContents* web_contents) {
MediaRouterDialogControllerWebUIImpl* controller =
MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents(
web_contents);
return !controller->GetMediaRouterDialog();
}
void MediaRouterIntegrationBrowserTest::WaitUntilDialogClosed(
WebContents* web_contents) {
ASSERT_TRUE(ConditionalWait(
base::TimeDelta::FromSeconds(5), base::TimeDelta::FromSeconds(1),
base::Bind(&MediaRouterIntegrationBrowserTest::IsDialogClosed,
base::Unretained(this), web_contents)));
}
void MediaRouterIntegrationBrowserTest::CheckDialogRemainsOpen(
WebContents* web_contents) {
ASSERT_FALSE(ConditionalWait(
base::TimeDelta::FromSeconds(5), base::TimeDelta::FromSeconds(1),
base::Bind(&MediaRouterIntegrationBrowserTest::IsDialogClosed,
base::Unretained(this), web_contents)));
}
void MediaRouterIntegrationBrowserTest::SetTestData( void MediaRouterIntegrationBrowserTest::SetTestData(
base::FilePath::StringPieceType test_data_file) { base::FilePath::StringPieceType test_data_file) {
base::FilePath full_path = GetResourceFile(test_data_file); base::FilePath full_path = GetResourceFile(test_data_file);
...@@ -421,23 +284,6 @@ void MediaRouterIntegrationBrowserTest::SetTestData( ...@@ -421,23 +284,6 @@ void MediaRouterIntegrationBrowserTest::SetTestData(
test_data_str.c_str())); test_data_str.c_str()));
} }
WebContents* MediaRouterIntegrationBrowserTest::OpenMRDialog(
WebContents* web_contents) {
MediaRouterDialogControllerWebUIImpl* controller =
MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents(
web_contents);
test_navigation_observer_.reset(
new content::TestNavigationObserver(web_contents, 1));
test_navigation_observer_->StartWatchingNewWebContents();
CHECK(controller->ShowMediaRouterDialog());
test_navigation_observer_->Wait();
test_navigation_observer_->StopWatchingNewWebContents();
WebContents* dialog_contents = controller->GetMediaRouterDialog();
CHECK(dialog_contents);
WaitUntilDialogFullyLoaded(dialog_contents);
return dialog_contents;
}
base::FilePath MediaRouterIntegrationBrowserTest::GetResourceFile( base::FilePath MediaRouterIntegrationBrowserTest::GetResourceFile(
base::FilePath::StringPieceType relative_path) const { base::FilePath::StringPieceType relative_path) const {
base::FilePath base_dir; base::FilePath base_dir;
...@@ -481,110 +327,22 @@ void MediaRouterIntegrationBrowserTest::ExecuteScript( ...@@ -481,110 +327,22 @@ void MediaRouterIntegrationBrowserTest::ExecuteScript(
} }
bool MediaRouterIntegrationBrowserTest::IsRouteCreatedOnUI() { bool MediaRouterIntegrationBrowserTest::IsRouteCreatedOnUI() {
return !GetRouteId(receiver()).empty(); return !test_ui_->GetRouteIdForSink(receiver_).empty();
}
std::string MediaRouterIntegrationBrowserTest::GetRouteId(
const std::string& sink_name) {
WebContents* web_contents = GetActiveWebContents();
WebContents* dialog_contents = GetMRDialog(web_contents);
std::string script = base::StringPrintf(kGetSinkIdScript, sink_name.c_str());
std::string sink_id = ExecuteScriptAndExtractString(dialog_contents, script);
DVLOG(0) << "sink id: " << sink_id;
script = base::StringPrintf(kGetRouteIdScript, sink_id.c_str());
std::string route_id = ExecuteScriptAndExtractString(dialog_contents, script);
DVLOG(0) << "route id: " << route_id;
return route_id;
}
void MediaRouterIntegrationBrowserTest::WaitUntilRouteCreated() {
ASSERT_TRUE(ConditionalWait(
base::TimeDelta::FromSeconds(10), base::TimeDelta::FromSeconds(1),
base::Bind(&MediaRouterIntegrationBrowserTest::IsRouteCreatedOnUI,
base::Unretained(this))));
} }
bool MediaRouterIntegrationBrowserTest::IsUIShowingIssue() { bool MediaRouterIntegrationBrowserTest::IsUIShowingIssue() {
WebContents* web_contents = GetActiveWebContents(); std::string issue_text = test_ui_->GetIssueTextForSink(receiver_);
WebContents* dialog_contents = GetMRDialog(web_contents); return !issue_text.empty();
std::string script = base::StringPrintf(
"domAutomationController.send(window.document.getElementById("
"'media-router-container').issue != undefined)");
bool has_issue = false;
CHECK(content::ExecuteScriptAndExtractBool(dialog_contents, script,
&has_issue));
return has_issue;
}
void MediaRouterIntegrationBrowserTest::WaitUntilIssue() {
ASSERT_TRUE(ConditionalWait(
base::TimeDelta::FromSeconds(30), base::TimeDelta::FromSeconds(1),
base::Bind(&MediaRouterIntegrationBrowserTest::IsUIShowingIssue,
base::Unretained(this))));
}
std::string MediaRouterIntegrationBrowserTest::GetIssueTitle() {
WebContents* web_contents = GetActiveWebContents();
WebContents* dialog_contents = GetMRDialog(web_contents);
std::string script = base::StringPrintf(
"domAutomationController.send(window.document.getElementById("
"'media-router-container').issue.title)");
return ExecuteScriptAndExtractString(dialog_contents, script);
} }
bool MediaRouterIntegrationBrowserTest::IsRouteClosedOnUI() { bool MediaRouterIntegrationBrowserTest::IsRouteClosedOnUI() {
// After execute js script to close route on UI, the dialog will dispear // After execute js script to close route on UI, the dialog will dispear
// after 3s. But sometimes it takes more than 3s to close the route, so // after 3s. But sometimes it takes more than 3s to close the route, so
// we need to re-open the dialog if it is closed. // we need to re-open the dialog if it is closed.
WebContents* web_contents = GetActiveWebContents(); if (!test_ui_->IsDialogShown())
MediaRouterDialogControllerWebUIImpl* controller = test_ui_->ShowDialog();
MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents( test_ui_->WaitForSink(receiver_);
web_contents); return test_ui_->GetRouteIdForSink(receiver_).empty();
WebContents* dialog_contents = controller->GetMediaRouterDialog();
if (!dialog_contents) {
VLOG(0) << "Media router dialog was closed, reopen it again.";
OpenMRDialog(web_contents);
}
return GetRouteId(receiver()).empty();
}
void MediaRouterIntegrationBrowserTest::CloseRouteOnUI() {
WebContents* web_contents = GetActiveWebContents();
WebContents* dialog_contents = GetMRDialog(web_contents);
ASSERT_TRUE(content::ExecuteScript(dialog_contents, kCloseRouteScript));
ASSERT_TRUE(ConditionalWait(
base::TimeDelta::FromSeconds(10), base::TimeDelta::FromSeconds(1),
base::Bind(&MediaRouterIntegrationBrowserTest::IsRouteClosedOnUI,
base::Unretained(this))));
}
bool MediaRouterIntegrationBrowserTest::IsSinkDiscoveredOnUI() {
WebContents* web_contents = GetActiveWebContents();
WebContents* dialog_contents = GetMRDialog(web_contents);
std::string script = base::StringPrintf(kFindSinkScript, receiver().c_str());
return ExecuteScriptAndExtractBool(dialog_contents, script);
}
void MediaRouterIntegrationBrowserTest::WaitUntilSinkDiscoveredOnUI() {
DVLOG(0) << "Receiver name: " << receiver_;
// Wait for sink to show up in UI.
ASSERT_TRUE(ConditionalWait(
base::TimeDelta::FromSeconds(30), base::TimeDelta::FromSeconds(1),
base::Bind(&MediaRouterIntegrationBrowserTest::IsSinkDiscoveredOnUI,
base::Unretained(this))));
}
bool MediaRouterIntegrationBrowserTest::IsDialogLoaded(
WebContents* dialog_contents) {
return ExecuteScriptAndExtractBool(dialog_contents, kCheckDialogLoadedScript);
}
void MediaRouterIntegrationBrowserTest::WaitUntilDialogFullyLoaded(
WebContents* dialog_contents) {
ASSERT_TRUE(ConditionalWait(
base::TimeDelta::FromSeconds(30), base::TimeDelta::FromSeconds(1),
base::Bind(&MediaRouterIntegrationBrowserTest::IsDialogLoaded,
base::Unretained(this), dialog_contents)));
} }
void MediaRouterIntegrationBrowserTest::ParseCommandLine() { void MediaRouterIntegrationBrowserTest::ParseCommandLine() {
...@@ -606,49 +364,26 @@ void MediaRouterIntegrationBrowserTest::CheckSessionValidity( ...@@ -606,49 +364,26 @@ void MediaRouterIntegrationBrowserTest::CheckSessionValidity(
EXPECT_EQ(session_id, default_request_session_id); EXPECT_EQ(session_id, default_request_session_id);
} }
MediaRouterDialogControllerWebUIImpl*
MediaRouterIntegrationBrowserTest::GetControllerForShownDialog(
WebContents* web_contents) {
MediaRouterDialogControllerWebUIImpl* controller =
MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents(
web_contents);
EXPECT_TRUE(controller->IsShowingMediaRouterDialog());
return controller;
}
WebContents* MediaRouterIntegrationBrowserTest::GetActiveWebContents() { WebContents* MediaRouterIntegrationBrowserTest::GetActiveWebContents() {
return browser()->tab_strip_model()->GetActiveWebContents(); return browser()->tab_strip_model()->GetActiveWebContents();
} }
MediaRouterUI* MediaRouterIntegrationBrowserTest::GetMediaRouterUI( void MediaRouterIntegrationBrowserTest::FileDialogSelectsFile(GURL file_url) {
content::WebContents* dialog_contents) { // TODO(https://crbug.com/900248): Implement this.
content::WebUI* web_ui = dialog_contents->GetWebUI(); NOTIMPLEMENTED();
CHECK(web_ui) << "Error getting MediaRouterUI, no WebUI at all";
return static_cast<MediaRouterUI*>(web_ui->GetController());
}
void MediaRouterIntegrationBrowserTest::FileDialogSelectsFile(
MediaRouterUI* media_router_ui,
GURL file_url) {
// Ensure that the media_router_ui is set
DCHECK(media_router_ui);
media_router_ui->InitForTest(
std::make_unique<TestMediaRouterFileDialog>(media_router_ui, file_url));
} }
void MediaRouterIntegrationBrowserTest::FileDialogSelectFails( void MediaRouterIntegrationBrowserTest::FileDialogSelectFails(
MediaRouterUI* media_router_ui,
const IssueInfo& issue) { const IssueInfo& issue) {
// Ensure that the media_router_ui is set // TODO(https://crbug.com/900248): Implement this.
DCHECK(media_router_ui); NOTIMPLEMENTED();
media_router_ui->InitForTest(
std::make_unique<TestFailMediaRouterFileDialog>(media_router_ui, issue));
} }
void MediaRouterIntegrationBrowserTest::RunBasicTest() { void MediaRouterIntegrationBrowserTest::RunBasicTest() {
WebContents* web_contents = StartSessionWithTestPageAndChooseSink(); WebContents* web_contents = StartSessionWithTestPageAndChooseSink();
CheckSessionValidity(web_contents); CheckSessionValidity(web_contents);
ExecuteJavaScriptAPI(web_contents, kTerminateSessionScript); ExecuteJavaScriptAPI(web_contents, kTerminateSessionScript);
test_ui_->WaitUntilNoRoutes();
} }
void MediaRouterIntegrationBrowserTest::RunSendMessageTest( void MediaRouterIntegrationBrowserTest::RunSendMessageTest(
...@@ -690,6 +425,7 @@ void MediaRouterIntegrationBrowserTest::RunReconnectSessionTest() { ...@@ -690,6 +425,7 @@ void MediaRouterIntegrationBrowserTest::RunReconnectSessionTest() {
ASSERT_EQ(session_id, reconnected_session_id); ASSERT_EQ(session_id, reconnected_session_id);
ExecuteJavaScriptAPI(web_contents, kTerminateSessionScript); ExecuteJavaScriptAPI(web_contents, kTerminateSessionScript);
test_ui_->WaitUntilNoRoutes();
} }
void MediaRouterIntegrationBrowserTest::SetEnableMediaRouter(bool enable) { void MediaRouterIntegrationBrowserTest::SetEnableMediaRouter(bool enable) {
...@@ -698,8 +434,7 @@ void MediaRouterIntegrationBrowserTest::SetEnableMediaRouter(bool enable) { ...@@ -698,8 +434,7 @@ void MediaRouterIntegrationBrowserTest::SetEnableMediaRouter(bool enable) {
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
std::make_unique<base::Value>(enable), nullptr); std::make_unique<base::Value>(enable), nullptr);
provider_.UpdateChromePolicy(policy); provider_.UpdateChromePolicy(policy);
base::RunLoop loop; base::RunLoop().RunUntilIdle();
loop.RunUntilIdle();
} }
void MediaRouterIntegrationBrowserTest::RunReconnectSessionSameTabTest() { void MediaRouterIntegrationBrowserTest::RunReconnectSessionSameTabTest() {
...@@ -718,15 +453,14 @@ void MediaRouterIntegrationBrowserTest::RunReconnectSessionSameTabTest() { ...@@ -718,15 +453,14 @@ void MediaRouterIntegrationBrowserTest::RunReconnectSessionSameTabTest() {
ASSERT_EQ(session_id, reconnected_session_id); ASSERT_EQ(session_id, reconnected_session_id);
} }
// TODO(crbug.com/822337): Flaky on Linux_CFI bot. IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, Basic) {
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, MANUAL_Basic) {
RunBasicTest(); RunBasicTest();
} }
// Tests that creating a route with a local file opens the file in a new tab. // Tests that creating a route with a local file opens the file in a new tab.
// TODO(crbug.com/818767): Fails when run with Chromium component. // TODO(https://crbug.com/900248): Make this test pass with the Views dialog.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
MANUAL_OpenLocalMediaFileInCurrentTab) { DISABLED_OpenLocalMediaFileInCurrentTab) {
// Start at a new tab, the file should open in the same tab. // Start at a new tab, the file should open in the same tab.
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
// Make sure there is 1 tab. // Make sure there is 1 tab.
...@@ -737,20 +471,18 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, ...@@ -737,20 +471,18 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
// Expect that no new tab has been opened. // Expect that no new tab has been opened.
ASSERT_EQ(1, browser()->tab_strip_model()->count()); ASSERT_EQ(1, browser()->tab_strip_model()->count());
// Open the dialog again to check for a route. test_ui_->ShowDialog();
OpenMRDialog(GetActiveWebContents());
// Wait for a route to be created. // Wait for a route to be created.
WaitUntilRouteCreated(); test_ui_->WaitForAnyRoute();
} }
// TODO(crbug.com/849216): Disabled due to crashes and timeouts.
//
// Tests that creating a route with a local file opens the file in a new tab. // Tests that creating a route with a local file opens the file in a new tab.
// TODO(https://crbug.com/900248): Make this test pass with the Views dialog.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
DISABLED_OpenLocalMediaFileInNewTab) { DISABLED_OpenLocalMediaFileInNewTab) {
// Start at a tab with content in it, the file will open in a new tab. // Start at a tab with content in it, the file will open in a new tab.
ui_test_utils::NavigateToURL(browser(), GURL("http://google.com")); ui_test_utils::NavigateToURL(browser(), GURL("https://google.com"));
// Make sure there is 1 tab. // Make sure there is 1 tab.
ASSERT_EQ(1, browser()->tab_strip_model()->count()); ASSERT_EQ(1, browser()->tab_strip_model()->count());
...@@ -759,25 +491,25 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, ...@@ -759,25 +491,25 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
// Expect that a new tab has been opened. // Expect that a new tab has been opened.
ASSERT_EQ(2, browser()->tab_strip_model()->count()); ASSERT_EQ(2, browser()->tab_strip_model()->count());
// Open the dialog again to check for a route. test_ui_->ShowDialog();
OpenMRDialog(GetActiveWebContents());
// Wait for a route to be created. // Wait for a route to be created.
WaitUntilRouteCreated(); test_ui_->WaitForAnyRoute();
} }
// Tests that failing to create a route with a local file shows an issue. // Tests that failing to create a route with a local file shows an issue.
// TODO(https://crbug.com/900248): Make this test pass with the Views dialog.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
OpenLocalMediaFileFailsAndShowsIssue) { DISABLED_OpenLocalMediaFileFailsAndShowsIssue) {
OpenDialogAndCastFileFails(); OpenDialogAndCastFileFails();
// Expect that the issue is showing. // Expect that the issue is showing.
ASSERT_TRUE(IsUIShowingIssue()); ASSERT_TRUE(IsUIShowingIssue());
} }
// Tests that creating a route with a local file opens in fullscreen. // Tests that creating a route with a local file opens in fullscreen.
// TODO(crbug.com/822029): Fails on msan; fix and re-enable. // TODO(https://crbug.com/900248): Make this test pass with the Views dialog.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
MANUAL_OpenLocalMediaFileFullscreen) { DISABLED_OpenLocalMediaFileFullscreen) {
// Start at a new tab, the file should open in the same tab. // Start at a new tab, the file should open in the same tab.
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
// Make sure there is 1 tab. // Make sure there is 1 tab.
...@@ -799,8 +531,9 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, ...@@ -799,8 +531,9 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
} }
// Tests that failed route creation of local file does not enter fullscreen. // Tests that failed route creation of local file does not enter fullscreen.
// TODO(https://crbug.com/900248): Make this test pass with the Views dialog.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
OpenLocalMediaFileCastFailNoFullscreen) { DISABLED_OpenLocalMediaFileCastFailNoFullscreen) {
// Start at a new tab, the file should open in the same tab. // Start at a new tab, the file should open in the same tab.
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
// Make sure there is 1 tab. // Make sure there is 1 tab.
...@@ -836,8 +569,9 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, Fail_SendMessage) { ...@@ -836,8 +569,9 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, Fail_SendMessage) {
RunFailToSendMessageTest(); RunFailToSendMessageTest();
} }
// TODO(https://crbug.com/822231): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
DISABLED_Fail_NoProvider) { MANUAL_Fail_NoProvider) {
SetTestData(FILE_PATH_LITERAL("no_provider.json")); SetTestData(FILE_PATH_LITERAL("no_provider.json"));
WebContents* web_contents = StartSessionWithTestPageAndChooseSink(); WebContents* web_contents = StartSessionWithTestPageAndChooseSink();
CheckStartFailed(web_contents, "UnknownError", CheckStartFailed(web_contents, "UnknownError",
...@@ -850,20 +584,12 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, Fail_CreateRoute) { ...@@ -850,20 +584,12 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, Fail_CreateRoute) {
CheckStartFailed(web_contents, "UnknownError", "Unknown sink"); CheckStartFailed(web_contents, "UnknownError", "Unknown sink");
} }
// TODO(crbug.com/822231): Flaky in Chromium waterfall. IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, ReconnectSession) {
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
MANUAL_ReconnectSession) {
RunReconnectSessionTest(); RunReconnectSessionTest();
} }
// Flaky on Linux MSAN. https://crbug.com/840165
#if defined(OS_LINUX) && defined(MEMORY_SANITIZER)
#define MAYBE_Fail_ReconnectSession DISABLED_Fail_ReconnectSession
#else
#define MAYBE_Fail_ReconnectSession Fail_ReconnectSession
#endif
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
MAYBE_Fail_ReconnectSession) { Fail_ReconnectSession) {
WebContents* web_contents = StartSessionWithTestPageAndChooseSink(); WebContents* web_contents = StartSessionWithTestPageAndChooseSink();
CheckSessionValidity(web_contents); CheckSessionValidity(web_contents);
std::string session_id(GetStartedConnectionId(web_contents)); std::string session_id(GetStartedConnectionId(web_contents));
...@@ -880,7 +606,7 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, ...@@ -880,7 +606,7 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, Fail_StartCancelled) { IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, Fail_StartCancelled) {
WebContents* web_contents = StartSessionWithTestPageAndSink(); WebContents* web_contents = StartSessionWithTestPageAndSink();
GetControllerForShownDialog(web_contents)->HideMediaRouterDialog(); test_ui_->HideDialog();
CheckStartFailed(web_contents, "NotAllowedError", "Dialog closed."); CheckStartFailed(web_contents, "NotAllowedError", "Dialog closed.");
} }
...@@ -914,21 +640,21 @@ Browser* MediaRouterIntegrationIncognitoBrowserTest::browser() { ...@@ -914,21 +640,21 @@ Browser* MediaRouterIntegrationIncognitoBrowserTest::browser() {
return incognito_browser_; return incognito_browser_;
} }
// Test is flaky on Linux. (https://crbug.com/853167) IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationIncognitoBrowserTest, Basic) {
#if defined(OS_LINUX)
#define MAYBE_Basic DISABLED_Basic
#else
#define MAYBE_Basic Basic
#endif
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationIncognitoBrowserTest,
MAYBE_Basic) {
RunBasicTest(); RunBasicTest();
// If we tear down before route observers are notified of route termination,
// MediaRouter will create another TerminateRoute() request which will have a
// dangling Mojo callback at shutdown. So we must wait for the update.
test_ui_->WaitUntilNoRoutes();
} }
// TODO(crbug.com/822300): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationIncognitoBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationIncognitoBrowserTest,
MANUAL_ReconnectSession) { ReconnectSession) {
RunReconnectSessionTest(); RunReconnectSessionTest();
// If we tear down before route observers are notified of route termination,
// MediaRouter will create another TerminateRoute() request which will have a
// dangling Mojo callback at shutdown. So we must wait for the update.
test_ui_->WaitUntilNoRoutes();
} }
} // namespace media_router } // namespace media_router
...@@ -14,14 +14,13 @@ ...@@ -14,14 +14,13 @@
#include "chrome/browser/ui/media_router/media_cast_mode.h" #include "chrome/browser/ui/media_router/media_cast_mode.h"
#include "chrome/browser/ui/toolbar/media_router_action.h" #include "chrome/browser/ui/toolbar/media_router_action.h"
#include "chrome/test/media_router/media_router_base_browsertest.h" #include "chrome/test/media_router/media_router_base_browsertest.h"
#include "chrome/test/media_router/media_router_ui_for_test.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "content/public/test/browser_test_utils.h" #include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_navigation_observer.h"
namespace media_router { namespace media_router {
class MediaRouterDialogControllerWebUIImpl;
class MediaRouterUI;
struct IssueInfo; struct IssueInfo;
class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest { class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest {
...@@ -33,23 +32,11 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest { ...@@ -33,23 +32,11 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest {
// InProcessBrowserTest Overrides // InProcessBrowserTest Overrides
void TearDownOnMainThread() override; void TearDownOnMainThread() override;
void SetUpInProcessBrowserTestFixture() override; void SetUpInProcessBrowserTestFixture() override;
void SetUpOnMainThread() override;
// MediaRouterBaseBrowserTest Overrides // MediaRouterBaseBrowserTest Overrides
void ParseCommandLine() override; void ParseCommandLine() override;
// Simulate user action to choose one sink in the popup dialog.
// |web_contents|: The web contents of the test page which invokes the popup
// dialog.
// |sink_name|: The sink's human readable name.
void ChooseSink(content::WebContents* web_contents,
const std::string& sink_name);
// Simulate user action to choose the local media cast mode in the popup
// dialog. This will not work unless the dialog is in the choose cast mode
// view. |dialog_contents|: The web contents of the popup dialog.
// |cast_mode_text|: The cast mode's dialog name.
void ClickCastMode(content::WebContents* dialog_contents, MediaCastMode mode);
// Checks that the request initiated from |web_contents| to start presentation // Checks that the request initiated from |web_contents| to start presentation
// failed with expected |error_name| and |error_message_substring|. // failed with expected |error_name| and |error_message_substring|.
void CheckStartFailed(content::WebContents* web_contents, void CheckStartFailed(content::WebContents* web_contents,
...@@ -67,12 +54,6 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest { ...@@ -67,12 +54,6 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest {
static std::string ExecuteScriptAndExtractString( static std::string ExecuteScriptAndExtractString(
const content::ToRenderFrameHost& adapter, const std::string& script); const content::ToRenderFrameHost& adapter, const std::string& script);
void ClickDialog();
// Clicks on the header of the dialog. If in sinks view, will change to cast
// mode view, if in cast mode view, will change to sinks view.
void ClickHeader(content::WebContents* dialog_contents);
static bool ExecuteScriptAndExtractBool( static bool ExecuteScriptAndExtractBool(
const content::ToRenderFrameHost& adapter, const content::ToRenderFrameHost& adapter,
const std::string& script); const std::string& script);
...@@ -80,17 +61,6 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest { ...@@ -80,17 +61,6 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest {
static void ExecuteScript(const content::ToRenderFrameHost& adapter, static void ExecuteScript(const content::ToRenderFrameHost& adapter,
const std::string& script); const std::string& script);
// Get the chrome modal dialog.
// |web_contents|: The web contents of the test page which invokes the popup
// dialog.
content::WebContents* GetMRDialog(content::WebContents* web_contents);
// Checks that the chrome modal dialog does not exist.
bool IsDialogClosed(content::WebContents* web_contents);
void WaitUntilDialogClosed(content::WebContents* web_contents);
void CheckDialogRemainsOpen(content::WebContents* web_contents);
// Opens "basic_test.html" and asserts that attempting to start a presentation // Opens "basic_test.html" and asserts that attempting to start a presentation
// fails with NotFoundError due to no sinks available. // fails with NotFoundError due to no sinks available.
void StartSessionAndAssertNotFoundError(); void StartSessionAndAssertNotFoundError();
...@@ -121,76 +91,30 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest { ...@@ -121,76 +91,30 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest {
void SetTestData(base::FilePath::StringPieceType test_data_file); void SetTestData(base::FilePath::StringPieceType test_data_file);
// Start presentation and wait until the pop dialog shows up.
// |web_contents|: The web contents of the test page which invokes the popup
// dialog.
void StartSession(content::WebContents* web_contents);
// Open the chrome modal dialog.
// |web_contents|: The web contents of the test page which invokes the popup
// dialog.
content::WebContents* OpenMRDialog(content::WebContents* web_contents);
bool IsRouteCreatedOnUI(); bool IsRouteCreatedOnUI();
bool IsRouteClosedOnUI(); bool IsRouteClosedOnUI();
bool IsSinkDiscoveredOnUI();
// Close route through clicking 'Stop casting' button in route details dialog.
void CloseRouteOnUI();
// Wait for the route to show up in the UI with a timeout. Fails if the
// route did not show up before the timeout.
void WaitUntilRouteCreated();
// Wait until there is an issue showing in the UI.
void WaitUntilIssue();
// Returns true if there is an issue showing in the UI. // Returns true if there is an issue showing in the UI.
bool IsUIShowingIssue(); bool IsUIShowingIssue();
// Returns the title of issue showing in UI. It is an error to call this if
// there are no issues showing in UI.
std::string GetIssueTitle();
// Returns the route ID for the specific sink. // Returns the route ID for the specific sink.
std::string GetRouteId(const std::string& sink_id); std::string GetRouteId(const std::string& sink_id);
// Wait for the specific sink shows up in UI with a timeout. Fails if the sink
// doesn't show up before the timeout.
void WaitUntilSinkDiscoveredOnUI();
// Checks if media router dialog is fully loaded.
bool IsDialogLoaded(content::WebContents* dialog_contents);
// Wait until media router dialog is fully loaded.
void WaitUntilDialogFullyLoaded(content::WebContents* dialog_contents);
// Checks that the presentation started for |web_contents| has connected and // Checks that the presentation started for |web_contents| has connected and
// is the default presentation. // is the default presentation.
void CheckSessionValidity(content::WebContents* web_contents); void CheckSessionValidity(content::WebContents* web_contents);
// Checks that a Media Router dialog is shown for |web_contents|, and returns
// its controller.
MediaRouterDialogControllerWebUIImpl* GetControllerForShownDialog(
content::WebContents* web_contents);
// Returns the active WebContents for the current window. // Returns the active WebContents for the current window.
content::WebContents* GetActiveWebContents(); content::WebContents* GetActiveWebContents();
// Gets the MediaRouterUI that is associated with the open dialog.
// This is needed to bypass potential issues that may arise when trying to
// test code that uses the native file dialog.
MediaRouterUI* GetMediaRouterUI(content::WebContents* media_router_dialog);
// Sets the MediaRouterFileDialog to act like a valid file was selected on // Sets the MediaRouterFileDialog to act like a valid file was selected on
// opening the dialog. // opening the dialog.
void FileDialogSelectsFile(MediaRouterUI* media_router_ui, GURL file_url); void FileDialogSelectsFile(GURL file_url);
// Sets the MediaRouterFileDialog to act like a bad file was selected on // Sets the MediaRouterFileDialog to act like a bad file was selected on
// opening the dialog. // opening the dialog.
void FileDialogSelectFails(MediaRouterUI* media_router_ui, void FileDialogSelectFails(const IssueInfo& issue);
const IssueInfo& issue);
// Runs a basic test in which a presentation is created through the // Runs a basic test in which a presentation is created through the
// MediaRouter dialog, then terminated. // MediaRouter dialog, then terminated.
...@@ -213,11 +137,15 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest { ...@@ -213,11 +137,15 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest {
// Sets whether media router is enabled. // Sets whether media router is enabled.
void SetEnableMediaRouter(bool enable); void SetEnableMediaRouter(bool enable);
std::string receiver() const { return receiver_; } // Test API for manipulating the UI.
MediaRouterUiForTest* test_ui_ = nullptr;
// Enabled features // Enabled features.
base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedFeatureList scoped_feature_list_;
// Name of the test receiver to use.
std::string receiver_;
private: private:
// Get the full path of the resource file. // Get the full path of the resource file.
// |relative_path|: The relative path to // |relative_path|: The relative path to
...@@ -228,14 +156,11 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest { ...@@ -228,14 +156,11 @@ class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest {
std::unique_ptr<content::TestNavigationObserver> test_navigation_observer_; std::unique_ptr<content::TestNavigationObserver> test_navigation_observer_;
policy::MockConfigurationPolicyProvider provider_; policy::MockConfigurationPolicyProvider provider_;
// Fields
std::string receiver_;
}; };
class MediaRouterIntegrationIncognitoBrowserTest class MediaRouterIntegrationIncognitoBrowserTest
: public MediaRouterIntegrationBrowserTest { : public MediaRouterIntegrationBrowserTest {
public: protected:
void InstallAndEnableMRExtension() override; void InstallAndEnableMRExtension() override;
void UninstallMRExtension() override; void UninstallMRExtension() override;
Browser* browser() override; Browser* browser() override;
......
...@@ -17,150 +17,37 @@ ...@@ -17,150 +17,37 @@
namespace media_router { namespace media_router {
namespace { // TODO(https://crbug.com/822231): Flaky in Chromium waterfall.
const char kTestSinkName[] = "test-sink-1"; IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, MANUAL_Dialog_Basic) {
}
// Disabled due to flakiness: https://crbug.com/873912.
#if defined(OS_CHROMEOS) && defined(MEMORY_SANITIZER)
#define MAYBE_Dialog_Basic DISABLED_Dialog_Basic
#else
#define MAYBE_Dialog_Basic Dialog_Basic
#endif
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, MAYBE_Dialog_Basic) {
OpenTestPage(FILE_PATH_LITERAL("basic_test.html")); OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
content::WebContents* web_contents = test_ui_->ShowDialog();
browser()->tab_strip_model()->GetActiveWebContents(); test_ui_->WaitForSinkAvailable(receiver_);
content::WebContents* dialog_contents = OpenMRDialog(web_contents); test_ui_->StartCasting(receiver_);
WaitUntilSinkDiscoveredOnUI(); test_ui_->WaitForAnyRoute();
// Verify the sink list.
std::string sink_length_script = base::StringPrintf( if (!test_ui_->IsDialogShown())
"domAutomationController.send(" test_ui_->ShowDialog();
"window.document.getElementById('media-router-container')."
"sinksToShow_.length)"); ASSERT_EQ("Test Route", test_ui_->GetStatusTextForSink(receiver_));
ASSERT_GT(ExecuteScriptAndExtractInt(dialog_contents, sink_length_script), 0);
LOG(INFO) << "Choose Sink"; test_ui_->StopCasting(receiver_);
ChooseSink(web_contents, kTestSinkName); test_ui_->WaitUntilNoRoutes();
// TODO(takumif): Remove the HideDialog() call once the dialog can close on
// Linux and Windows bots run browser tests without a physical display, which // its own.
// is causing flaky event dispatching of mouseenter and mouseleave events. This test_ui_->HideDialog();
// causes the dialog to sometimes close prematurely even though a mouseenter
// event is explicitly dispatched in the test.
// Here, we still dispatch the mouseenter event for OSX, but close
// the dialog and reopen it on Linux and Windows.
// The test succeeds fine when run with a physical display.
// http://crbug.com/577943 http://crbug.com/591779
#if defined(OS_MACOSX)
// Simulate keeping the mouse on the dialog to prevent it from automatically
// closing after the route has been created. Then, check that the dialog
// remains open.
std::string mouse_enter_script = base::StringPrintf(
"window.document.getElementById('media-router-container')"
" .dispatchEvent(new Event('mouseenter'));");
ASSERT_TRUE(content::ExecuteScript(dialog_contents, mouse_enter_script));
#endif
WaitUntilRouteCreated();
#if defined(OS_MACOSX)
CheckDialogRemainsOpen(web_contents);
#elif defined(OS_LINUX) || defined(OS_WIN)
Wait(base::TimeDelta::FromSeconds(5));
LOG(INFO) << "Waiting for dialog to be closed";
WaitUntilDialogClosed(web_contents);
LOG(INFO) << "Reopen MR dialog";
dialog_contents = OpenMRDialog(web_contents);
#endif
LOG(INFO) << "Check route details dialog";
std::string route_script;
// Verify the route details is not undefined.
route_script = base::StringPrintf(
"domAutomationController.send("
"window.document.getElementById('media-router-container').shadowRoot."
"getElementById('route-details') != undefined)");
ASSERT_TRUE(ConditionalWait(
base::TimeDelta::FromSeconds(30), base::TimeDelta::FromSeconds(1),
base::Bind(
&MediaRouterIntegrationBrowserTest::ExecuteScriptAndExtractBool,
dialog_contents, route_script)));
route_script = base::StringPrintf(
"domAutomationController.send("
"window.document.getElementById('media-router-container').currentView_ "
"== media_router.MediaRouterView.ROUTE_DETAILS)");
ASSERT_TRUE(ExecuteScriptAndExtractBool(dialog_contents, route_script));
// Verify the route details page.
route_script = base::StringPrintf(
"domAutomationController.send("
"window.document.getElementById('media-router-container').shadowRoot."
"getElementById('route-details').shadowRoot.getElementById("
"'route-description').innerText)");
std::string route_information = ExecuteScriptAndExtractString(
dialog_contents, route_script);
ASSERT_EQ("Test Route", route_information);
std::string sink_script;
// Verify the container header is not undefined.
sink_script = base::StringPrintf(
"domAutomationController.send("
"window.document.getElementById('media-router-container').shadowRoot."
"getElementById('container-header') != undefined)");
LOG(INFO) << "Checking container-header";
ASSERT_TRUE(ConditionalWait(
base::TimeDelta::FromSeconds(30), base::TimeDelta::FromSeconds(1),
base::Bind(
&MediaRouterIntegrationBrowserTest::ExecuteScriptAndExtractBool,
dialog_contents, sink_script)));
sink_script = base::StringPrintf(
"domAutomationController.send("
"window.document.getElementById('media-router-container').shadowRoot."
"getElementById('container-header').shadowRoot.getElementById("
"'header-text').innerText)");
std::string sink_name = ExecuteScriptAndExtractString(
dialog_contents, sink_script);
ASSERT_EQ(kTestSinkName, sink_name);
LOG(INFO) << "Finish verification";
#if defined(OS_MACOSX)
// Simulate moving the mouse off the dialog. Confirm that the dialog closes
// automatically after the route is closed.
// In tests, it sometimes takes too long to CloseRouteOnUI() to finish so
// the timer started when the route is initially closed times out before the
// mouseleave event is dispatched. In that case, the dialog remains open.
std::string mouse_leave_script = base::StringPrintf(
"window.document.getElementById('media-router-container')"
" .dispatchEvent(new Event('mouseleave'));");
ASSERT_TRUE(content::ExecuteScript(dialog_contents, mouse_leave_script));
#endif
LOG(INFO) << "Closing route on UI";
CloseRouteOnUI();
#if defined(OS_MACOSX)
LOG(INFO) << "Waiting for dialog to be closed";
WaitUntilDialogClosed(web_contents);
#endif
LOG(INFO) << "Closed dialog, end of test";
} }
// TODO(crbug.com/822301): Flaky in Chromium waterfall. // TODO(https://crbug.com/822231): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
MANUAL_Dialog_RouteCreationTimedOut) { MANUAL_Dialog_RouteCreationTimedOut) {
SetTestData(FILE_PATH_LITERAL("route_creation_timed_out.json")); SetTestData(FILE_PATH_LITERAL("route_creation_timed_out.json"));
OpenTestPage(FILE_PATH_LITERAL("basic_test.html")); OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
content::WebContents* web_contents = test_ui_->ShowDialog();
browser()->tab_strip_model()->GetActiveWebContents(); test_ui_->WaitForSinkAvailable(receiver_);
content::WebContents* dialog_contents = OpenMRDialog(web_contents);
// Verify the sink list.
std::string sink_length_script = base::StringPrintf(
"domAutomationController.send("
"window.document.getElementById('media-router-container')."
"sinksToShow_.length)");
ASSERT_GT(ExecuteScriptAndExtractInt(dialog_contents, sink_length_script), 0);
base::TimeTicks start_time(base::TimeTicks::Now()); base::TimeTicks start_time(base::TimeTicks::Now());
ChooseSink(web_contents, kTestSinkName); test_ui_->StartCasting(receiver_);
WaitUntilIssue(); test_ui_->WaitForAnyIssue();
base::TimeDelta elapsed(base::TimeTicks::Now() - start_time); base::TimeDelta elapsed(base::TimeTicks::Now() - start_time);
// The hardcoded timeout route creation timeout for the UI. // The hardcoded timeout route creation timeout for the UI.
...@@ -170,7 +57,7 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, ...@@ -170,7 +57,7 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
EXPECT_GE(elapsed, expected_timeout); EXPECT_GE(elapsed, expected_timeout);
EXPECT_LE(elapsed - expected_timeout, base::TimeDelta::FromSeconds(5)); EXPECT_LE(elapsed - expected_timeout, base::TimeDelta::FromSeconds(5));
std::string issue_title = GetIssueTitle(); std::string issue_title = test_ui_->GetIssueTextForSink(receiver_);
// TODO(imcheng): Fix host name for file schemes (crbug.com/560576). // TODO(imcheng): Fix host name for file schemes (crbug.com/560576).
ASSERT_EQ( ASSERT_EQ(
l10n_util::GetStringFUTF8(IDS_MEDIA_ROUTER_ISSUE_CREATE_ROUTE_TIMEOUT, l10n_util::GetStringFUTF8(IDS_MEDIA_ROUTER_ISSUE_CREATE_ROUTE_TIMEOUT,
...@@ -178,7 +65,8 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, ...@@ -178,7 +65,8 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
issue_title); issue_title);
// Route will still get created, it just takes longer than usual. // Route will still get created, it just takes longer than usual.
WaitUntilRouteCreated(); test_ui_->WaitForAnyRoute();
test_ui_->HideDialog();
} }
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
...@@ -191,33 +79,22 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, ...@@ -191,33 +79,22 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
// Enable media routing and open media router dialog. // Enable media routing and open media router dialog.
SetEnableMediaRouter(true); SetEnableMediaRouter(true);
OpenTestPage(FILE_PATH_LITERAL("basic_test.html")); OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
content::WebContents* web_contents = test_ui_->ShowDialog();
browser()->tab_strip_model()->GetActiveWebContents(); ASSERT_TRUE(test_ui_->IsDialogShown());
OpenMRDialog(web_contents); test_ui_->HideDialog();
MediaRouterDialogControllerWebUIImpl* controller =
MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents(
web_contents);
ASSERT_TRUE(controller->IsShowingMediaRouterDialog());
} }
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
DisableMediaRoutingWhenDialogIsOpened) { DisableMediaRoutingWhenDialogIsOpened) {
// Open media router dialog. // Open media router dialog.
OpenTestPage(FILE_PATH_LITERAL("basic_test.html")); OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
content::WebContents* web_contents = test_ui_->ShowDialog();
browser()->tab_strip_model()->GetActiveWebContents(); ASSERT_TRUE(test_ui_->IsDialogShown());
OpenMRDialog(web_contents);
MediaRouterDialogControllerWebUIImpl* controller =
MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents(
web_contents);
ASSERT_TRUE(controller->IsShowingMediaRouterDialog());
// Disable media routing. // Disable media routing.
SetEnableMediaRouter(false); SetEnableMediaRouter(false);
ASSERT_FALSE(controller->IsShowingMediaRouterDialog()); ASSERT_FALSE(test_ui_->IsDialogShown());
} }
} // namespace media_router } // namespace media_router
...@@ -41,18 +41,17 @@ class MediaRouterIntegrationOneUABrowserTest ...@@ -41,18 +41,17 @@ class MediaRouterIntegrationOneUABrowserTest
} }
}; };
// TODO(crbug.com/822231): Flaky in Chromium waterfall. IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest, Basic) {
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest, MANUAL_Basic) {
RunBasicTest(); RunBasicTest();
} }
// TODO(crbug.com/822216): Flaky in Chromium waterfall. // TODO(https://crbug.com/822231): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
MANUAL_SendAndOnMessage) { MANUAL_SendAndOnMessage) {
RunSendMessageTest("foo"); RunSendMessageTest("foo");
} }
// TODO(crbug.com/821717): Flaky in Chromium waterfall. // TODO(https://crbug.com/822231): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
MANUAL_ReceiverCloseConnection) { MANUAL_ReceiverCloseConnection) {
WebContents* web_contents = StartSessionWithTestPageAndChooseSink(); WebContents* web_contents = StartSessionWithTestPageAndChooseSink();
...@@ -60,21 +59,18 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest, ...@@ -60,21 +59,18 @@ IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
ExecuteJavaScriptAPI(web_contents, kInitiateCloseFromReceiverPageScript); ExecuteJavaScriptAPI(web_contents, kInitiateCloseFromReceiverPageScript);
} }
// TODO(crbug.com/824889): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
MANUAL_Fail_SendMessage) { Fail_SendMessage) {
RunFailToSendMessageTest(); RunFailToSendMessageTest();
} }
// TODO(crbug.com/821717): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
MANUAL_ReconnectSession) { ReconnectSession) {
RunReconnectSessionTest(); RunReconnectSessionTest();
} }
// TODO(crbug.com/821717): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
MANUAL_ReconnectSessionSameTab) { ReconnectSessionSameTab) {
RunReconnectSessionSameTabTest(); RunReconnectSessionSameTabTest();
} }
...@@ -87,28 +83,23 @@ class MediaRouterIntegrationOneUANoReceiverBrowserTest ...@@ -87,28 +83,23 @@ class MediaRouterIntegrationOneUANoReceiverBrowserTest
} }
}; };
// TODO(crbug.com/822179,822337): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest,
MANUAL_Basic) { Basic) {
RunBasicTest(); RunBasicTest();
} }
// TODO(crbug.com/821717): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest,
MANUAL_Fail_SendMessage) { Fail_SendMessage) {
RunFailToSendMessageTest(); RunFailToSendMessageTest();
} }
// TODO(crbug.com/822231): Flaky in Chromium waterfall.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest,
MANUAL_ReconnectSession) { ReconnectSession) {
RunReconnectSessionTest(); RunReconnectSessionTest();
} }
// TODO(crbug.com/826016): Crashes on ASAN.
// TODO(crbug.com/834681): Crashes elsewhere too, flakily.
IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest, IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest,
MANUAL_ReconnectSessionSameTab) { ReconnectSessionSameTab) {
RunReconnectSessionSameTabTest(); RunReconnectSessionSameTabTest();
} }
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include "chrome/test/media_router/media_router_ui_for_test.h" #include "chrome/test/media_router/media_router_ui_for_test.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/browser/media/router/media_router_factory.h"
#include "chrome/browser/media/router/media_routes_observer.h"
#include "chrome/browser/ui/views/media_router/cast_dialog_sink_button.h" #include "chrome/browser/ui/views/media_router/cast_dialog_sink_button.h"
#include "chrome/browser/ui/views/media_router/cast_dialog_view.h" #include "chrome/browser/ui/views/media_router/cast_dialog_view.h"
#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"
...@@ -30,6 +32,24 @@ ui::MouseEvent CreateMouseReleasedEvent() { ...@@ -30,6 +32,24 @@ ui::MouseEvent CreateMouseReleasedEvent() {
ui::EF_LEFT_MOUSE_BUTTON, 0); ui::EF_LEFT_MOUSE_BUTTON, 0);
} }
// Routes observer that calls a callback once there are no routes.
class NoRoutesObserver : public MediaRoutesObserver {
public:
NoRoutesObserver(MediaRouter* router, base::OnceClosure callback)
: MediaRoutesObserver(router), callback_(std::move(callback)) {}
~NoRoutesObserver() override = default;
void OnRoutesUpdated(
const std::vector<MediaRoute>& routes,
const std::vector<MediaRoute::Id>& joinable_route_ids) override {
if (callback_ && routes.empty())
std::move(callback_).Run();
}
private:
base::OnceClosure callback_;
};
} // namespace } // namespace
// static // static
...@@ -80,15 +100,15 @@ void MediaRouterUiForTest::ChooseSourceType( ...@@ -80,15 +100,15 @@ void MediaRouterUiForTest::ChooseSourceType(
dialog_view->sources_menu_model_for_test()->ActivatedAt(source_index); dialog_view->sources_menu_model_for_test()->ActivatedAt(source_index);
} }
void MediaRouterUiForTest::StartCasting(const MediaSink::Id& sink_id) { void MediaRouterUiForTest::StartCasting(const std::string& sink_name) {
CastDialogSinkButton* sink_button = GetSinkButton(sink_id); CastDialogSinkButton* sink_button = GetSinkButton(sink_name);
sink_button->OnMousePressed(CreateMousePressedEvent()); sink_button->OnMousePressed(CreateMousePressedEvent());
sink_button->OnMouseReleased(CreateMouseReleasedEvent()); sink_button->OnMouseReleased(CreateMouseReleasedEvent());
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
void MediaRouterUiForTest::StopCasting(const MediaSink::Id& sink_id) { void MediaRouterUiForTest::StopCasting(const std::string& sink_name) {
CastDialogSinkButton* sink_button = GetSinkButton(sink_id); CastDialogSinkButton* sink_button = GetSinkButton(sink_name);
sink_button->icon_view()->OnMousePressed(CreateMousePressedEvent()); sink_button->icon_view()->OnMousePressed(CreateMousePressedEvent());
sink_button->icon_view()->OnMouseReleased(CreateMouseReleasedEvent()); sink_button->icon_view()->OnMouseReleased(CreateMouseReleasedEvent());
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
...@@ -109,8 +129,12 @@ void MediaRouterUiForTest::StopCasting() { ...@@ -109,8 +129,12 @@ void MediaRouterUiForTest::StopCasting() {
NOTREACHED() << "Sink was not found"; NOTREACHED() << "Sink was not found";
} }
void MediaRouterUiForTest::WaitForSink(const MediaSink::Id& sink_id) { void MediaRouterUiForTest::WaitForSink(const std::string& sink_name) {
ObserveDialog(WatchType::kSink, sink_id); ObserveDialog(WatchType::kSink, sink_name);
}
void MediaRouterUiForTest::WaitForSinkAvailable(const std::string& sink_name) {
ObserveDialog(WatchType::kSinkAvailable, sink_name);
} }
void MediaRouterUiForTest::WaitForAnyIssue() { void MediaRouterUiForTest::WaitForAnyIssue() {
...@@ -121,37 +145,53 @@ void MediaRouterUiForTest::WaitForAnyRoute() { ...@@ -121,37 +145,53 @@ void MediaRouterUiForTest::WaitForAnyRoute() {
ObserveDialog(WatchType::kAnyRoute); ObserveDialog(WatchType::kAnyRoute);
} }
void MediaRouterUiForTest::WaitForDialogClosed() { void MediaRouterUiForTest::WaitForDialogShown() {
ObserveDialog(WatchType::kDialogClosed); CHECK(!watch_sink_name_);
CHECK(!watch_callback_);
CHECK_EQ(watch_type_, WatchType::kNone);
if (IsDialogShown())
return;
base::RunLoop run_loop;
watch_callback_ = run_loop.QuitClosure();
watch_type_ = WatchType::kDialogShown;
run_loop.Run();
}
void MediaRouterUiForTest::WaitForDialogHidden() {
ObserveDialog(WatchType::kDialogHidden);
} }
std::string MediaRouterUiForTest::GetSinkName( void MediaRouterUiForTest::WaitUntilNoRoutes() {
const MediaSink::Id& sink_id) const { base::RunLoop run_loop;
CastDialogSinkButton* sink_button = GetSinkButton(sink_id); NoRoutesObserver no_routes_observer(
return base::UTF16ToUTF8(sink_button->sink().friendly_name); MediaRouterFactory::GetApiForBrowserContext(
web_contents_->GetBrowserContext()),
run_loop.QuitClosure());
run_loop.Run();
} }
MediaRoute::Id MediaRouterUiForTest::GetRouteIdForSink( MediaRoute::Id MediaRouterUiForTest::GetRouteIdForSink(
const MediaSink::Id& sink_id) const { const std::string& sink_name) const {
CastDialogSinkButton* sink_button = GetSinkButton(sink_id); CastDialogSinkButton* sink_button = GetSinkButton(sink_name);
if (!sink_button->sink().route) { if (!sink_button->sink().route) {
NOTREACHED() << "Route not found for sink " << sink_id; NOTREACHED() << "Route not found for sink " << sink_name;
return ""; return "";
} }
return sink_button->sink().route->media_route_id(); return sink_button->sink().route->media_route_id();
} }
std::string MediaRouterUiForTest::GetStatusTextForSink( std::string MediaRouterUiForTest::GetStatusTextForSink(
const MediaSink::Id& sink_id) const { const std::string& sink_name) const {
CastDialogSinkButton* sink_button = GetSinkButton(sink_id); CastDialogSinkButton* sink_button = GetSinkButton(sink_name);
return base::UTF16ToUTF8(sink_button->sink().status_text); return base::UTF16ToUTF8(sink_button->sink().status_text);
} }
std::string MediaRouterUiForTest::GetIssueTextForSink( std::string MediaRouterUiForTest::GetIssueTextForSink(
const MediaSink::Id& sink_id) const { const std::string& sink_name) const {
CastDialogSinkButton* sink_button = GetSinkButton(sink_id); CastDialogSinkButton* sink_button = GetSinkButton(sink_name);
if (!sink_button->sink().issue) { if (!sink_button->sink().issue) {
NOTREACHED() << "Issue not found for sink " << sink_id; NOTREACHED() << "Issue not found for sink " << sink_name;
return ""; return "";
} }
return sink_button->sink().issue->info().title; return sink_button->sink().issue->info().title;
...@@ -161,11 +201,17 @@ MediaRouterUiForTest::MediaRouterUiForTest(content::WebContents* web_contents) ...@@ -161,11 +201,17 @@ MediaRouterUiForTest::MediaRouterUiForTest(content::WebContents* web_contents)
: web_contents_(web_contents), : web_contents_(web_contents),
dialog_controller_( dialog_controller_(
MediaRouterDialogControllerViews::GetOrCreateForWebContents( MediaRouterDialogControllerViews::GetOrCreateForWebContents(
web_contents)) {} web_contents)),
weak_factory_(this) {
dialog_controller_->SetDialogCreationCallbackForTesting(base::BindRepeating(
&MediaRouterUiForTest::OnDialogCreated, weak_factory_.GetWeakPtr()));
}
void MediaRouterUiForTest::OnDialogModelUpdated(CastDialogView* dialog_view) { void MediaRouterUiForTest::OnDialogModelUpdated(CastDialogView* dialog_view) {
if (!watch_callback_ || watch_type_ == WatchType::kDialogClosed) if (!watch_callback_ || watch_type_ == WatchType::kDialogShown ||
watch_type_ == WatchType::kDialogHidden) {
return; return;
}
const std::vector<CastDialogSinkButton*>& sink_buttons = const std::vector<CastDialogSinkButton*>& sink_buttons =
dialog_view->sink_buttons_for_test(); dialog_view->sink_buttons_for_test();
...@@ -173,27 +219,34 @@ void MediaRouterUiForTest::OnDialogModelUpdated(CastDialogView* dialog_view) { ...@@ -173,27 +219,34 @@ void MediaRouterUiForTest::OnDialogModelUpdated(CastDialogView* dialog_view) {
[&, this](CastDialogSinkButton* sink_button) { [&, this](CastDialogSinkButton* sink_button) {
switch (watch_type_) { switch (watch_type_) {
case WatchType::kSink: case WatchType::kSink:
return sink_button->sink().id == *watch_sink_id_; return sink_button->sink().friendly_name ==
base::UTF8ToUTF16(*watch_sink_name_);
case WatchType::kSinkAvailable:
return sink_button->sink().friendly_name ==
base::UTF8ToUTF16(*watch_sink_name_) &&
sink_button->sink().state ==
UIMediaSinkState::AVAILABLE;
case WatchType::kAnyIssue: case WatchType::kAnyIssue:
return sink_button->sink().issue.has_value(); return sink_button->sink().issue.has_value();
case WatchType::kAnyRoute: case WatchType::kAnyRoute:
return sink_button->sink().route.has_value(); return sink_button->sink().route.has_value();
case WatchType::kNone: case WatchType::kNone:
case WatchType::kDialogClosed: case WatchType::kDialogShown:
case WatchType::kDialogHidden:
NOTREACHED() << "Invalid WatchType"; NOTREACHED() << "Invalid WatchType";
return false; return false;
} }
}) != sink_buttons.end()) { }) != sink_buttons.end()) {
std::move(*watch_callback_).Run(); std::move(*watch_callback_).Run();
watch_callback_.reset(); watch_callback_.reset();
watch_sink_id_.reset(); watch_sink_name_.reset();
watch_type_ = WatchType::kNone; watch_type_ = WatchType::kNone;
dialog_view->RemoveObserver(this); dialog_view->RemoveObserver(this);
} }
} }
void MediaRouterUiForTest::OnDialogWillClose(CastDialogView* dialog_view) { void MediaRouterUiForTest::OnDialogWillClose(CastDialogView* dialog_view) {
if (watch_type_ == WatchType::kDialogClosed) { if (watch_type_ == WatchType::kDialogHidden) {
std::move(*watch_callback_).Run(); std::move(*watch_callback_).Run();
watch_callback_.reset(); watch_callback_.reset();
watch_type_ = WatchType::kNone; watch_type_ = WatchType::kNone;
...@@ -203,18 +256,28 @@ void MediaRouterUiForTest::OnDialogWillClose(CastDialogView* dialog_view) { ...@@ -203,18 +256,28 @@ void MediaRouterUiForTest::OnDialogWillClose(CastDialogView* dialog_view) {
dialog_view->RemoveObserver(this); dialog_view->RemoveObserver(this);
} }
void MediaRouterUiForTest::OnDialogCreated() {
if (watch_type_ == WatchType::kDialogShown) {
std::move(*watch_callback_).Run();
watch_callback_.reset();
watch_type_ = WatchType::kNone;
}
CastDialogView::GetInstance()->KeepShownForTesting();
}
CastDialogSinkButton* MediaRouterUiForTest::GetSinkButton( CastDialogSinkButton* MediaRouterUiForTest::GetSinkButton(
const MediaSink::Id& sink_id) const { const std::string& sink_name) const {
CastDialogView* dialog_view = CastDialogView::GetInstance(); CastDialogView* dialog_view = CastDialogView::GetInstance();
CHECK(dialog_view); CHECK(dialog_view);
const std::vector<CastDialogSinkButton*>& sink_buttons = const std::vector<CastDialogSinkButton*>& sink_buttons =
dialog_view->sink_buttons_for_test(); dialog_view->sink_buttons_for_test();
auto it = std::find_if(sink_buttons.begin(), sink_buttons.end(), auto it = std::find_if(sink_buttons.begin(), sink_buttons.end(),
[sink_id](CastDialogSinkButton* sink_button) { [sink_name](CastDialogSinkButton* sink_button) {
return sink_button->sink().id == sink_id; return sink_button->sink().friendly_name ==
base::UTF8ToUTF16(sink_name);
}); });
if (it == sink_buttons.end()) { if (it == sink_buttons.end()) {
NOTREACHED() << "Sink button not found for sink ID: " << sink_id; NOTREACHED() << "Sink button not found for sink: " << sink_name;
return nullptr; return nullptr;
} else { } else {
return *it; return *it;
...@@ -223,12 +286,12 @@ CastDialogSinkButton* MediaRouterUiForTest::GetSinkButton( ...@@ -223,12 +286,12 @@ CastDialogSinkButton* MediaRouterUiForTest::GetSinkButton(
void MediaRouterUiForTest::ObserveDialog( void MediaRouterUiForTest::ObserveDialog(
WatchType watch_type, WatchType watch_type,
base::Optional<MediaSink::Id> sink_id) { base::Optional<std::string> sink_name) {
CHECK(!watch_sink_id_); CHECK(!watch_sink_name_);
CHECK(!watch_callback_); CHECK(!watch_callback_);
CHECK_EQ(watch_type_, WatchType::kNone); CHECK_EQ(watch_type_, WatchType::kNone);
base::RunLoop run_loop; base::RunLoop run_loop;
watch_sink_id_ = std::move(sink_id); watch_sink_name_ = std::move(sink_name);
watch_callback_ = run_loop.QuitClosure(); watch_callback_ = run_loop.QuitClosure();
watch_type_ = watch_type; watch_type_ = watch_type;
......
...@@ -7,8 +7,10 @@ ...@@ -7,8 +7,10 @@
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "chrome/browser/ui/views/media_router/cast_dialog_view.h" #include "chrome/browser/ui/views/media_router/cast_dialog_view.h"
#include "chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h"
#include "chrome/common/media_router/media_sink.h" #include "chrome/common/media_router/media_sink.h"
#include "chrome/common/media_router/media_source.h" #include "chrome/common/media_router/media_source.h"
#include "content/public/browser/web_contents_user_data.h" #include "content/public/browser/web_contents_user_data.h"
...@@ -19,8 +21,6 @@ class WebContents; ...@@ -19,8 +21,6 @@ class WebContents;
namespace media_router { namespace media_router {
class MediaRouterDialogControllerViews;
class MediaRouterUiForTest class MediaRouterUiForTest
: public content::WebContentsUserData<MediaRouterUiForTest>, : public content::WebContentsUserData<MediaRouterUiForTest>,
public CastDialogView::Observer { public CastDialogView::Observer {
...@@ -39,31 +39,41 @@ class MediaRouterUiForTest ...@@ -39,31 +39,41 @@ class MediaRouterUiForTest
// These methods require that the dialog is shown and the specified sink is // These methods require that the dialog is shown and the specified sink is
// shown in the dialog. // shown in the dialog.
void StartCasting(const MediaSink::Id& sink_id); void StartCasting(const std::string& sink_name);
void StopCasting(const MediaSink::Id& sink_id); void StopCasting(const std::string& sink_name);
// Stops casting to the first active sink found on the sink list. Requires // Stops casting to the first active sink found on the sink list. Requires
// that such a sink exists. // that such a sink exists.
void StopCasting(); void StopCasting();
// Waits until . Requires that the dialog is shown. // Waits until a condition is met. Requires that the dialog is shown.
void WaitForSink(const MediaSink::Id& sink_id); void WaitForSink(const std::string& sink_name);
void WaitForSinkAvailable(const std::string& sink_name);
void WaitForAnyIssue(); void WaitForAnyIssue();
void WaitForAnyRoute(); void WaitForAnyRoute();
void WaitForDialogClosed(); void WaitForDialogShown();
void WaitForDialogHidden();
void WaitUntilNoRoutes();
// These methods require that the dialog is shown, and the sink specified by // These methods require that the dialog is shown, and the sink specified by
// |sink_id| is in the dialog. // |sink_name| is in the dialog.
std::string GetSinkName(const MediaSink::Id& sink_id) const; MediaRoute::Id GetRouteIdForSink(const std::string& sink_name) const;
MediaRoute::Id GetRouteIdForSink(const MediaSink::Id& sink_id) const; std::string GetStatusTextForSink(const std::string& sink_name) const;
std::string GetStatusTextForSink(const MediaSink::Id& sink_id) const; std::string GetIssueTextForSink(const std::string& sink_name) const;
std::string GetIssueTextForSink(const MediaSink::Id& sink_id) const;
content::WebContents* web_contents() const { return web_contents_; } content::WebContents* web_contents() const { return web_contents_; }
private: private:
friend class content::WebContentsUserData<MediaRouterUiForTest>; friend class content::WebContentsUserData<MediaRouterUiForTest>;
enum class WatchType { kNone, kSink, kAnyIssue, kAnyRoute, kDialogClosed }; enum class WatchType {
kNone,
kSink, // Sink is found in any state.
kSinkAvailable, // Sink is found in the "Available" state.
kAnyIssue,
kAnyRoute,
kDialogShown,
kDialogHidden
};
explicit MediaRouterUiForTest(content::WebContents* web_contents); explicit MediaRouterUiForTest(content::WebContents* web_contents);
...@@ -71,21 +81,26 @@ class MediaRouterUiForTest ...@@ -71,21 +81,26 @@ class MediaRouterUiForTest
void OnDialogModelUpdated(CastDialogView* dialog_view) override; void OnDialogModelUpdated(CastDialogView* dialog_view) override;
void OnDialogWillClose(CastDialogView* dialog_view) override; void OnDialogWillClose(CastDialogView* dialog_view) override;
CastDialogSinkButton* GetSinkButton(const MediaSink::Id& sink_id) const; // Called by MediaRouterDialogControllerViews.
void OnDialogCreated();
CastDialogSinkButton* GetSinkButton(const std::string& sink_name) const;
// Registers itself as an observer to the dialog, and waits until an event // Registers itself as an observer to the dialog, and waits until an event
// of |watch_type| is observed. |sink_id| should be set only if observing for // of |watch_type| is observed. |sink_name| should be set only if observing
// a sink. // for a sink.
void ObserveDialog(WatchType watch_type, void ObserveDialog(WatchType watch_type,
base::Optional<MediaSink::Id> sink_id = base::nullopt); base::Optional<std::string> sink_name = base::nullopt);
content::WebContents* web_contents_; content::WebContents* web_contents_;
MediaRouterDialogControllerViews* dialog_controller_; MediaRouterDialogControllerViews* dialog_controller_;
base::Optional<MediaSink::Id> watch_sink_id_; base::Optional<std::string> watch_sink_name_;
base::Optional<base::OnceClosure> watch_callback_; base::Optional<base::OnceClosure> watch_callback_;
WatchType watch_type_ = WatchType::kNone; WatchType watch_type_ = WatchType::kNone;
base::WeakPtrFactory<MediaRouterUiForTest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaRouterUiForTest); DISALLOW_COPY_AND_ASSIGN(MediaRouterUiForTest);
}; };
......
...@@ -120,7 +120,7 @@ function checkStartFailed(expectedErrorName, expectedErrorMessageSubstring) { ...@@ -120,7 +120,7 @@ function checkStartFailed(expectedErrorName, expectedErrorMessageSubstring) {
sendResult(false, 'start() unexpectedly succeeded.'); sendResult(false, 'start() unexpectedly succeeded.');
}).catch(function(e) { }).catch(function(e) {
if (expectedErrorName != e.name) { if (expectedErrorName != e.name) {
sendResult(false, 'Got unexpected error: ' + e.name); sendResult(false, 'Got unexpected error. ' + e.name + ': ' + e.message);
} else if (e.message.indexOf(expectedErrorMessageSubstring) == -1) { } else if (e.message.indexOf(expectedErrorMessageSubstring) == -1) {
sendResult(false, sendResult(false,
'Error message is not correct, it should contain "' + 'Error message is not correct, it should contain "' +
...@@ -219,6 +219,12 @@ function sendMessageAndExpectResponse(message) { ...@@ -219,6 +219,12 @@ function sendMessageAndExpectResponse(message) {
sendResult(false, 'startedConnection does not exist.'); sendResult(false, 'startedConnection does not exist.');
return; return;
} }
if (startedConnection.state != 'connected') {
sendResult(false,
`Expected the connection state to be connected but it was \
${startedConnection.state}`);
return;
}
startedConnection.onmessage = function(receivedMessage) { startedConnection.onmessage = function(receivedMessage) {
var expectedResponse = 'Pong: ' + message; var expectedResponse = 'Pong: ' + message;
var actualResponse = receivedMessage.data; var actualResponse = receivedMessage.data;
...@@ -241,6 +247,12 @@ function initiateCloseFromReceiverPage() { ...@@ -241,6 +247,12 @@ function initiateCloseFromReceiverPage() {
sendResult(false, 'startedConnection does not exist.'); sendResult(false, 'startedConnection does not exist.');
return; return;
} }
if (startedConnection.state != 'connected') {
sendResult(false,
`Expected the connection state to be connected but it was \
${startedConnection.state}`);
return;
}
startedConnection.onclose = (event) => { startedConnection.onclose = (event) => {
const reason = event.reason; const reason = event.reason;
if (reason != 'closed') { if (reason != 'closed') {
......
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