blob: 0339ba0cc8b8edf88fa5e1fa7e2977f4ff3a1417 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/browser/media_session.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.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/shell/browser/shell.h"
#include "media/base/media_switches.h"
namespace content {
namespace {
// Integration tests for content::MediaSession that do not take into
// consideration the implementation details contrary to
// MediaSessionImplBrowserTest.
class MediaSessionBrowserTest : public ContentBrowserTest {
public:
MediaSessionBrowserTest() = default;
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kIgnoreAutoplayRestrictionsForTests);
}
void EnableInternalMediaSesion() {
#if !defined(OS_ANDROID)
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableInternalMediaSession);
#endif // !defined(OS_ANDROID)
}
void StartPlaybackAndWait(Shell* shell, const std::string& id) {
shell->web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
base::ASCIIToUTF16("document.querySelector('#" + id + "').play();"));
WaitForStart(shell);
}
void StopPlaybackAndWait(Shell* shell, const std::string& id) {
shell->web_contents()->GetMainFrame()->ExecuteJavaScriptForTests(
base::ASCIIToUTF16("document.querySelector('#" + id + "').pause();"));
WaitForStop(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) {
bool result;
EXPECT_TRUE(
ExecuteScriptAndExtractBool(shell->web_contents(),
"window.domAutomationController.send("
"!document.querySelector('#" +
id + "').paused);",
&result));
return result;
}
private:
class MediaStartStopObserver : public WebContentsObserver {
public:
enum class Type { kStart, kStop };
MediaStartStopObserver(WebContents* web_contents, Type type)
: WebContentsObserver(web_contents), type_(type) {}
void MediaStartedPlaying(const MediaPlayerInfo& info,
const MediaPlayerId& id) override {
if (type_ != Type::kStart)
return;
run_loop_.Quit();
}
void MediaStoppedPlaying(const MediaPlayerInfo& info,
const MediaPlayerId& id) override {
if (type_ != Type::kStop)
return;
run_loop_.Quit();
}
void Wait() { run_loop_.Run(); }
private:
base::RunLoop run_loop_;
Type type_;
DISALLOW_COPY_AND_ASSIGN(MediaStartStopObserver);
};
DISALLOW_COPY_AND_ASSIGN(MediaSessionBrowserTest);
};
} // anonymous namespace
#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
// The feature can't be disabled on Android and Chrome OS.
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MediaSessionNoOpWhenDisabled) {
NavigateToURL(shell(), GetTestUrl("media/session", "media-session.html"));
MediaSession* media_session = MediaSession::Get(shell()->web_contents());
ASSERT_NE(nullptr, media_session);
StartPlaybackAndWait(shell(), "long-video");
StartPlaybackAndWait(shell(), "long-audio");
media_session->Suspend(MediaSession::SuspendType::SYSTEM);
StopPlaybackAndWait(shell(), "long-audio");
// At that point, only "long-audio" is paused.
EXPECT_FALSE(IsPlaying(shell(), "long-audio"));
EXPECT_TRUE(IsPlaying(shell(), "long-video"));
}
#endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, SimplePlayPause) {
EnableInternalMediaSesion();
NavigateToURL(shell(), GetTestUrl("media/session", "media-session.html"));
MediaSession* media_session = MediaSession::Get(shell()->web_contents());
ASSERT_NE(nullptr, media_session);
StartPlaybackAndWait(shell(), "long-video");
media_session->Suspend(MediaSession::SuspendType::SYSTEM);
WaitForStop(shell());
EXPECT_FALSE(IsPlaying(shell(), "long-video"));
media_session->Resume(MediaSession::SuspendType::SYSTEM);
WaitForStart(shell());
EXPECT_TRUE(IsPlaying(shell(), "long-video"));
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MultiplePlayersPlayPause) {
EnableInternalMediaSesion();
NavigateToURL(shell(), GetTestUrl("media/session", "media-session.html"));
MediaSession* media_session = MediaSession::Get(shell()->web_contents());
ASSERT_NE(nullptr, media_session);
StartPlaybackAndWait(shell(), "long-video");
StartPlaybackAndWait(shell(), "long-audio");
media_session->Suspend(MediaSession::SuspendType::SYSTEM);
WaitForStop(shell());
EXPECT_FALSE(IsPlaying(shell(), "long-video"));
EXPECT_FALSE(IsPlaying(shell(), "long-audio"));
media_session->Resume(MediaSession::SuspendType::SYSTEM);
WaitForStart(shell());
EXPECT_TRUE(IsPlaying(shell(), "long-video"));
EXPECT_TRUE(IsPlaying(shell(), "long-audio"));
}
#if !defined(OS_ANDROID)
// On Android, System Audio Focus would break this test.
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MultipleTabsPlayPause) {
EnableInternalMediaSesion();
Shell* other_shell = CreateBrowser();
NavigateToURL(shell(), GetTestUrl("media/session", "media-session.html"));
NavigateToURL(other_shell, GetTestUrl("media/session", "media-session.html"));
MediaSession* media_session = MediaSession::Get(shell()->web_contents());
MediaSession* other_media_session =
MediaSession::Get(other_shell->web_contents());
ASSERT_NE(nullptr, media_session);
ASSERT_NE(nullptr, other_media_session);
StartPlaybackAndWait(shell(), "long-video");
StartPlaybackAndWait(other_shell, "long-video");
media_session->Suspend(MediaSession::SuspendType::SYSTEM);
WaitForStop(shell());
EXPECT_FALSE(IsPlaying(shell(), "long-video"));
EXPECT_TRUE(IsPlaying(other_shell, "long-video"));
other_media_session->Suspend(MediaSession::SuspendType::SYSTEM);
WaitForStop(other_shell);
EXPECT_FALSE(IsPlaying(shell(), "long-video"));
EXPECT_FALSE(IsPlaying(other_shell, "long-video"));
media_session->Resume(MediaSession::SuspendType::SYSTEM);
WaitForStart(shell());
EXPECT_TRUE(IsPlaying(shell(), "long-video"));
EXPECT_FALSE(IsPlaying(other_shell, "long-video"));
other_media_session->Resume(MediaSession::SuspendType::SYSTEM);
WaitForStart(other_shell);
EXPECT_TRUE(IsPlaying(shell(), "long-video"));
EXPECT_TRUE(IsPlaying(other_shell, "long-video"));
}
#endif // defined(OS_ANDROID)
} // namespace content