// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/media/web_app_system_media_controls.h"
#include <optional>
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread_win.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/media/media_keys_listener_manager_impl.h"
#include "content/browser/media/session/media_session_impl.h"
#include "content/browser/media/web_app_system_media_controls_manager.h"
#include "content/public/common/content_features.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/media_start_stop_observer.h"
#include "content/shell/browser/shell.h"
#include "media/base/media_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
// This test suite tests playing media in a content window and verifies control
// via system media controls controls the expected window. As instanced system
// media controls is developed under kWebAppSystemMediaControls.
// Currently, this test suite only runs on windows.
class WebAppSystemMediaControlsBrowserTest
: public ContentBrowserTest,
public WebAppSystemMediaControlsManagerObserver,
public MediaKeysListenerManagerImplTestObserver {
public:
WebAppSystemMediaControlsBrowserTest() = default;
WebAppSystemMediaControlsBrowserTest(
const WebAppSystemMediaControlsBrowserTest&) = delete;
WebAppSystemMediaControlsBrowserTest& operator=(
const WebAppSystemMediaControlsBrowserTest&) = delete;
~WebAppSystemMediaControlsBrowserTest() override = default;
void SetUpOnMainThread() override {
// Start an HTTPS server that will serve files in from "content/test/data".
https_server_ = std::make_unique<net::EmbeddedTestServer>(
net::EmbeddedTestServer::TYPE_HTTPS);
https_server_->ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(https_server_->Start());
// Also start listening to events from a few different classes.
MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
BrowserMainLoop::GetInstance()->media_keys_listener_manager();
media_keys_listener_manager_impl->SetObserverForTesting(this);
WebAppSystemMediaControlsManager* web_app_system_media_controls_manager =
media_keys_listener_manager_impl->web_app_system_media_controls_manager_
.get();
web_app_system_media_controls_manager->SetObserverForTesting(this);
// Tests may want to utilize this runloop to detect when browser has been
// bookkeeping added. We need to create this runloop early enough so that
// the runloop always wins the race between the waiter asking to "wait for
// browser added" and the browser actually being added.
browser_added_run_loop_.emplace();
// Do a similar thing for the web app added run loop.
web_app_added_run_loop_.emplace();
// And finally a similar thing for the watching media key run loop.
start_watching_media_key_run_loop_.emplace();
}
void TearDownOnMainThread() override {
system_media_controls::SystemMediaControls::
SetVisibilityChangedCallbackForTesting(nullptr);
ContentBrowserTest::TearDownOnMainThread();
}
net::EmbeddedTestServer* https_server() { return https_server_.get(); }
void StartPlaybackAndWait(Shell* shell, const std::string& id) {
shell->web_contents()->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(
base::ASCIIToUTF16(
JsReplace("document.getElementById($1).play();", id)),
base::NullCallback(), ISOLATED_WORLD_ID_GLOBAL);
WaitForStart(shell);
}
void WaitForStart(Shell* shell) {
MediaStartStopObserver observer(shell->web_contents(),
MediaStartStopObserver::Type::kStart);
observer.Wait();
}
void WaitForStop(Shell* shell) {
MediaStartStopObserver observer(shell->web_contents(),
MediaStartStopObserver::Type::kStop);
observer.Wait();
}
bool IsPlaying(Shell* shell, const std::string& id) {
return EvalJs(shell->web_contents(),
JsReplace("!document.getElementById($1).paused;", id))
.ExtractBool();
}
WebAppSystemMediaControlsManager* GetWebAppSystemMediaControlsManager() {
MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
BrowserMainLoop::GetInstance()->media_keys_listener_manager();
return media_keys_listener_manager_impl
->web_app_system_media_controls_manager_.get();
}
system_media_controls::SystemMediaControls* GetBrowserSystemMediaControls() {
MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
BrowserMainLoop::GetInstance()->media_keys_listener_manager();
return media_keys_listener_manager_impl->browser_system_media_controls_
.get();
}
system_media_controls::SystemMediaControls* GetSystemMediaControlsForWebApp(
base::UnguessableToken request_id) {
WebAppSystemMediaControls* web_app_system_media_controls =
GetWebAppSystemMediaControlsManager()->GetControlsForRequestId(
request_id);
EXPECT_NE(web_app_system_media_controls, nullptr);
system_media_controls::SystemMediaControls* system_media_controls =
web_app_system_media_controls->GetSystemMediaControls();
EXPECT_NE(system_media_controls, nullptr);
return system_media_controls;
}
// This method asks the WebAppSystemMediaControlsManager to just assume
// requests that come in come from a web app.
void SetAlwaysAssumeWebAppForTesting() {
GetWebAppSystemMediaControlsManager()->always_assume_web_app_for_testing_ =
true;
}
void SetAlwaysIgnoreMediaSessionForTesting(WebContents* web_contents) {
MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents);
media_session->always_ignore_for_active_session_for_testing_ = true;
}
// This mechanism allows us to wait for a web app to be added to the
// WebAppSystemMediaControls bookkeeping.
void OnWebAppAdded(base::UnguessableToken request_id) override {
last_web_app_request_id_ = request_id;
web_app_added_run_loop_->Quit();
}
base::UnguessableToken WaitForWebAppAdded() {
web_app_added_run_loop_->Run();
EXPECT_FALSE(last_web_app_request_id_.is_empty());
base::UnguessableToken cached_request_id = last_web_app_request_id_;
last_web_app_request_id_ = base::UnguessableToken::Null();
// Reset the runloop for the next use.
web_app_added_run_loop_.emplace();
return cached_request_id;
}
// This mechanism allows us to wait for MediaKeysListenerImpl to be ready
// to listen to keys.
void OnStartWatchingMediaKey(bool is_pwa) override {
start_watching_media_key_run_loop_->Quit();
last_watch_was_for_pwa_ = is_pwa;
}
// This function returns whether the last "watching key" event was for a PWA
// or not.
bool WaitForStartWatchingMediaKey() {
start_watching_media_key_run_loop_->Run();
EXPECT_TRUE(
last_watch_was_for_pwa_); // Check the value got set, optional resolves
// to true if the value got set.
bool cached_last_watch_was_for_pwa = last_watch_was_for_pwa_.value();
last_watch_was_for_pwa_ = std::nullopt;
// Reset the runloop for the next use.
start_watching_media_key_run_loop_.emplace();
return cached_last_watch_was_for_pwa;
}
// Waits for the visibility of the given WebApp's SystemMediaControls to match
// `desired_visibility`. Returns true if the visibility has successfully
// matched the expectation. Returns false if we time out before the state
// changes.
bool WaitForVisibility(const base::UnguessableToken& request_id,
bool desired_visibility) {
// If the controls are already in the desired visibility state, early
// return success.
if (GetSystemMediaControlsForWebApp(request_id)
->GetVisibilityForTesting() == desired_visibility) {
return true;
}
// Otherwise, wait for the visibility state to change.
base::RunLoop wait_for_desired_visibility;
auto visibility_changed_callback =
base::BindLambdaForTesting([&](bool is_visible) {
if (is_visible == desired_visibility) {
wait_for_desired_visibility.Quit();
}
});
system_media_controls::SystemMediaControls::
SetVisibilityChangedCallbackForTesting(&visibility_changed_callback);
wait_for_desired_visibility.Run();
// Return true if the state is now correct.
return GetSystemMediaControlsForWebApp(request_id)
->GetVisibilityForTesting() == desired_visibility;
}
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(
switches::kAutoplayPolicy,
switches::autoplay::kNoUserGestureRequiredPolicy);
feature_list_.InitAndEnableFeature(features::kWebAppSystemMediaControls);
}
private:
std::optional<base::RunLoop> web_app_added_run_loop_;
base::UnguessableToken last_web_app_request_id_;
std::optional<base::RunLoop> browser_added_run_loop_;
std::optional<base::RunLoop> start_watching_media_key_run_loop_;
std::optional<bool> last_watch_was_for_pwa_;
std::unique_ptr<net::EmbeddedTestServer> https_server_;
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest,
SimpleOneBrowserTest) {
GURL http_url(https_server()->GetURL("/media/session/media-session.html"));
EXPECT_TRUE(NavigateToURL(shell(), http_url));
// Run javascript to play the video, and wait for it to begin playing.
StartPlaybackAndWait(shell(), "long-video-loop");
// Check video is playing.
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
bool is_for_pwa = WaitForStartWatchingMediaKey();
EXPECT_FALSE(is_for_pwa);
// Hit pause via simulating SMTC pause.
MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
BrowserMainLoop::GetInstance()->media_keys_listener_manager();
// Check video is still playing.
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
media_keys_listener_manager_impl->OnPause(GetBrowserSystemMediaControls());
// Check video is paused.
WaitForStop(shell());
}
// TODO: crbug.com/361543620 - Fix the test on Win11 arm64 debug platform.
#if BUILDFLAG(IS_WIN) && !defined(NDEBUG) && defined(ARCH_CPU_ARM64)
#define MAYBE_ThreeBrowserTest DISABLED_ThreeBrowserTest
#else
#define MAYBE_ThreeBrowserTest ThreeBrowserTest
#endif
IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest,
MAYBE_ThreeBrowserTest) {
GURL http_url(https_server()->GetURL("/media/session/media-session.html"));
Shell* browser2 = CreateBrowser();
Shell* browser3 = CreateBrowser();
EXPECT_TRUE(NavigateToURL(shell(), http_url));
EXPECT_TRUE(NavigateToURL(browser2, http_url));
EXPECT_TRUE(NavigateToURL(browser3, http_url));
// Press play and wait for each one to start.
StartPlaybackAndWait(shell(), "long-video-loop");
StartPlaybackAndWait(browser2, "long-video-loop");
StartPlaybackAndWait(browser3, "long-video-loop");
EXPECT_TRUE(IsPlaying(browser3, "long-video-loop"));
EXPECT_TRUE(IsPlaying(browser2, "long-video-loop"));
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
// Now we have 3 things playing at the same time. Browser 3 should have
// control and be shown in SMTC.
// Wait until MediaKeysListenerManagerImpl starts listening for keys.
bool is_for_pwa = WaitForStartWatchingMediaKey();
EXPECT_FALSE(is_for_pwa);
// Hit pause via simulating SMTC pause.
MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
BrowserMainLoop::GetInstance()->media_keys_listener_manager();
media_keys_listener_manager_impl->OnPause(GetBrowserSystemMediaControls());
// Check audio is paused for browser3.
WaitForStop(browser3);
// The other stuff should be continuing to loop.
EXPECT_TRUE(IsPlaying(browser2, "long-video-loop"));
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
}
IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest,
BrowserAndWebAppTest) {
// Navigate two shells to the page.
GURL http_url(https_server()->GetURL("/media/session/media-session.html"));
EXPECT_TRUE(NavigateToURL(shell(), http_url));
Shell* web_app = CreateBrowser();
EXPECT_TRUE(NavigateToURL(web_app, http_url));
// Start two playbacks, but set the testing flags so that the second window
// will register as a web app to WebAppSystemMediaControlsManager.
{
StartPlaybackAndWait(shell(), "long-video-loop");
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
// We need to be careful here that this first play is completely done before
// we set the flag to pretend subsequent plays are from apps.
bool is_for_pwa = WaitForStartWatchingMediaKey();
EXPECT_FALSE(is_for_pwa);
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
}
SetAlwaysAssumeWebAppForTesting();
SetAlwaysIgnoreMediaSessionForTesting(web_app->web_contents());
// Start the playback in the web app, wait for state to be ready, then hit
// pause to the web app.
StartPlaybackAndWait(web_app, "long-video-loop");
base::UnguessableToken request_id = WaitForWebAppAdded();
EXPECT_TRUE(IsPlaying(web_app, "long-video-loop"));
EXPECT_FALSE(request_id.is_empty());
// Wait for MediaKeysListenerManagerImpl to also start watching.
bool is_for_pwa = WaitForStartWatchingMediaKey();
EXPECT_TRUE(is_for_pwa);
// Now retrieve the SMC and make a call to pause the video.
system_media_controls::SystemMediaControls* system_media_controls =
GetSystemMediaControlsForWebApp(request_id);
MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
BrowserMainLoop::GetInstance()->media_keys_listener_manager();
media_keys_listener_manager_impl->OnPause(system_media_controls);
// The "web app" should be paused.
WaitForStop(web_app);
// The browser is still playing.
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
// Now start the webapp again.
media_keys_listener_manager_impl->OnPlay(system_media_controls);
WaitForStart(web_app);
// The browser is still playing.
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
}
IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest, ThreeWebAppTest) {
// Navigate two shells to the page.
GURL http_url(https_server()->GetURL("/media/session/media-session.html"));
// We're mostly going to ignore this shell() based browser.
Shell* web_app1 = CreateBrowser();
Shell* web_app2 = CreateBrowser();
Shell* web_app3 = CreateBrowser();
EXPECT_TRUE(NavigateToURL(web_app1, http_url));
EXPECT_TRUE(NavigateToURL(web_app2, http_url));
EXPECT_TRUE(NavigateToURL(web_app3, http_url));
// Start all the playbacks.
SetAlwaysAssumeWebAppForTesting();
SetAlwaysIgnoreMediaSessionForTesting(web_app1->web_contents());
SetAlwaysIgnoreMediaSessionForTesting(web_app2->web_contents());
SetAlwaysIgnoreMediaSessionForTesting(web_app3->web_contents());
base::UnguessableToken web_app1_request_id;
base::UnguessableToken web_app2_request_id;
base::UnguessableToken web_app3_request_id;
{
StartPlaybackAndWait(web_app1, "long-video-loop");
web_app1_request_id = WaitForWebAppAdded();
// Also wait until MediaKeysListenerManagerImpl starts listening for keys.
bool is_for_pwa = WaitForStartWatchingMediaKey();
EXPECT_TRUE(is_for_pwa);
}
{
StartPlaybackAndWait(web_app2, "long-video-loop");
web_app2_request_id = WaitForWebAppAdded();
// Also wait until MediaKeysListenerManagerImpl starts listening for keys.
bool is_for_pwa = WaitForStartWatchingMediaKey();
EXPECT_TRUE(is_for_pwa);
}
{
StartPlaybackAndWait(web_app3, "long-video-loop");
web_app3_request_id = WaitForWebAppAdded();
// Also wait until MediaKeysListenerManagerImpl starts listening for keys.
bool is_for_pwa = WaitForStartWatchingMediaKey();
EXPECT_TRUE(is_for_pwa);
}
// All request ids should be valid.
EXPECT_NE(web_app1_request_id, base::UnguessableToken::Null());
EXPECT_NE(web_app2_request_id, base::UnguessableToken::Null());
EXPECT_NE(web_app3_request_id, base::UnguessableToken::Null());
system_media_controls::SystemMediaControls* web_app1_system_media_controls =
GetSystemMediaControlsForWebApp(web_app1_request_id);
system_media_controls::SystemMediaControls* web_app2_system_media_controls =
GetSystemMediaControlsForWebApp(web_app2_request_id);
system_media_controls::SystemMediaControls* web_app3_system_media_controls =
GetSystemMediaControlsForWebApp(web_app3_request_id);
MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
BrowserMainLoop::GetInstance()->media_keys_listener_manager();
media_keys_listener_manager_impl->OnPause(web_app2_system_media_controls);
WaitForStop(web_app2);
// The other stuff should be continuing to loop.
EXPECT_TRUE(IsPlaying(web_app1, "long-video-loop"));
EXPECT_TRUE(IsPlaying(web_app3, "long-video-loop"));
// Pause 3, only 1 remains.
media_keys_listener_manager_impl->OnPause(web_app3_system_media_controls);
WaitForStop(web_app3);
EXPECT_TRUE(IsPlaying(web_app1, "long-video-loop"));
// Pause 1, only 1 remains.
media_keys_listener_manager_impl->OnPause(web_app1_system_media_controls);
WaitForStop(web_app1);
}
IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest, TelemetryTest) {
base::HistogramTester histogram_tester;
Shell* web_app1 = CreateBrowser();
Shell* web_app2 = CreateBrowser();
// Navigate two shells to the page.
GURL http_url(https_server()->GetURL("/media/session/media-session.html"));
EXPECT_TRUE(NavigateToURL(web_app1, http_url));
EXPECT_TRUE(NavigateToURL(web_app2, http_url));
// Start playback.
SetAlwaysAssumeWebAppForTesting();
SetAlwaysIgnoreMediaSessionForTesting(web_app1->web_contents());
SetAlwaysIgnoreMediaSessionForTesting(web_app2->web_contents());
// Load a video from web_app1.
StartPlaybackAndWait(web_app1, "long-video-loop");
base::UnguessableToken web_app1_request_id = WaitForWebAppAdded();
EXPECT_TRUE(web_app1_request_id);
EXPECT_TRUE(WaitForStartWatchingMediaKey());
system_media_controls::SystemMediaControls* web_app1_system_media_controls =
GetSystemMediaControlsForWebApp(web_app1_request_id);
// Load a video from web_app2.
StartPlaybackAndWait(web_app2, "long-video-loop");
base::UnguessableToken web_app2_request_id = WaitForWebAppAdded();
EXPECT_TRUE(WaitForStartWatchingMediaKey());
system_media_controls::SystemMediaControls* web_app2_system_media_controls =
GetSystemMediaControlsForWebApp(web_app2_request_id);
MediaKeysListenerManagerImpl* media_keys_listener_manager =
BrowserMainLoop::GetInstance()->media_keys_listener_manager();
// Simulate a bunch of actions from SystemMediaTransportControls center.
{
media_keys_listener_manager->OnPause(web_app1_system_media_controls);
WaitForStop(web_app1);
media_keys_listener_manager->OnPlay(web_app1_system_media_controls);
WaitForStart(web_app1);
media_keys_listener_manager->OnPause(web_app2_system_media_controls);
WaitForStop(web_app2);
media_keys_listener_manager->OnPlay(web_app2_system_media_controls);
WaitForStart(web_app2);
FetchHistogramsFromChildProcesses();
// 4 starts hence 4 PwaPlayingMedia events.
histogram_tester.ExpectBucketCount(
"WebApp.Media.SystemMediaControls",
WebAppSystemMediaControlsEvent::kPwaPlayingMedia, 4);
histogram_tester.ExpectBucketCount(
"WebApp.Media.SystemMediaControls",
WebAppSystemMediaControlsEvent::kPwaSmcPlay, 2);
histogram_tester.ExpectBucketCount(
"WebApp.Media.SystemMediaControls",
WebAppSystemMediaControlsEvent::kPwaSmcPause, 2);
}
// Now just simulate some of the other ones. We can't do next/prev because
// those are disabled when there are no next or previous tracks. so just skip
// those.
{
media_keys_listener_manager->OnPlayPause(web_app1_system_media_controls);
media_keys_listener_manager->OnStop(web_app1_system_media_controls);
media_keys_listener_manager->OnSeek(web_app1_system_media_controls,
base::Seconds(2));
media_keys_listener_manager->OnSeekTo(web_app1_system_media_controls,
base::Seconds(2));
FetchHistogramsFromChildProcesses();
histogram_tester.ExpectBucketCount(
"WebApp.Media.SystemMediaControls",
WebAppSystemMediaControlsEvent::kPwaSmcPlayPause, 1);
histogram_tester.ExpectBucketCount(
"WebApp.Media.SystemMediaControls",
WebAppSystemMediaControlsEvent::kPwaSmcStop, 1);
histogram_tester.ExpectBucketCount(
"WebApp.Media.SystemMediaControls",
WebAppSystemMediaControlsEvent::kPwaSmcSeek, 1);
histogram_tester.ExpectBucketCount(
"WebApp.Media.SystemMediaControls",
WebAppSystemMediaControlsEvent::kPwaSmcSeekTo, 1);
}
}
IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest, TwoBrowserTest) {
// Navigate two shells to the page.
GURL http_url(https_server()->GetURL("/media/session/media-session.html"));
EXPECT_TRUE(NavigateToURL(shell(), http_url));
Shell* browser2 = CreateBrowser();
EXPECT_TRUE(NavigateToURL(browser2, http_url));
EXPECT_TRUE(NavigateToURL(shell(), http_url));
EXPECT_TRUE(NavigateToURL(browser2, http_url));
// Start two playbacks, both from the browser.
{
StartPlaybackAndWait(shell(), "long-video-loop");
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
// Wait for the playing audio to register in the media keys listener
// manager.
WaitForStartWatchingMediaKey();
StartPlaybackAndWait(browser2, "long-video-loop");
EXPECT_TRUE(IsPlaying(browser2, "long-video-loop"));
WaitForStartWatchingMediaKey();
}
// Now retrieve the SMC used for the browser and make a call to pause the
// video.
system_media_controls::SystemMediaControls* system_media_controls =
GetBrowserSystemMediaControls();
MediaKeysListenerManagerImpl* media_keys_listener_manager_impl =
BrowserMainLoop::GetInstance()->media_keys_listener_manager();
media_keys_listener_manager_impl->OnPause(system_media_controls);
// The browser2 should be paused.
WaitForStop(browser2);
// The shell is still playing.
EXPECT_TRUE(IsPlaying(shell(), "long-video-loop"));
// Close browser2, this will cause the controlled browser to fall back to
// shell.
browser2->Close();
// Wait a little for the fallback to occur.
WaitForStartWatchingMediaKey();
// Now hit pause again, it should pause shell().
media_keys_listener_manager_impl->OnPause(system_media_controls);
WaitForStop(shell());
// The browser is still playing.
EXPECT_FALSE(IsPlaying(shell(), "long-video-loop"));
}
IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest,
SMTCHiddenOnNavigationAway) {
// Set up a media session in 1 PWA.
GURL http_url(https_server()->GetURL("/media/session/media-session.html"));
Shell* web_app = CreateBrowser();
EXPECT_TRUE(NavigateToURL(web_app, http_url));
SetAlwaysAssumeWebAppForTesting();
SetAlwaysIgnoreMediaSessionForTesting(web_app->web_contents());
// Start the media session and wait for the controls to become visible.
StartPlaybackAndWait(web_app, "long-video-loop");
base::UnguessableToken request_id = WaitForWebAppAdded();
EXPECT_TRUE(WaitForVisibility(request_id, /*desired_visibility=*/true));
// Check the pwa is still playing, and navigate away to a different url.
EXPECT_TRUE(IsPlaying(web_app, "long-video-loop"));
GURL http_url2(https_server()->GetURL("/media/session/title1.html"));
EXPECT_TRUE(NavigateToURL(web_app, http_url2));
// The controls should hide now.
EXPECT_TRUE(WaitForVisibility(request_id, /*desired_visibility=*/false));
}
IN_PROC_BROWSER_TEST_F(WebAppSystemMediaControlsBrowserTest,
SMTCHiddenOnAudioEnd) {
// Set up a media session in 1 PWA.
GURL http_url(https_server()->GetURL("/media/session/media-session.html"));
Shell* web_app = CreateBrowser();
EXPECT_TRUE(NavigateToURL(web_app, http_url));
SetAlwaysAssumeWebAppForTesting();
SetAlwaysIgnoreMediaSessionForTesting(web_app->web_contents());
// Start the media session and wait for the controls to become visible.
StartPlaybackAndWait(web_app, "short-video");
base::UnguessableToken request_id = WaitForWebAppAdded();
EXPECT_TRUE(WaitForVisibility(request_id, /*desired_visibility=*/true));
// Wait for the audio track to end on its own.
WaitForStop(web_app);
EXPECT_FALSE(IsPlaying(web_app, "short-video"));
// The controls should hide now.
EXPECT_TRUE(WaitForVisibility(request_id, /*desired_visibility=*/false));
}
} // namespace content