| Index: content/browser/media/session/media_session_visibility_browsertest.cc
|
| diff --git a/content/browser/media/session/media_session_visibility_browsertest.cc b/content/browser/media/session/media_session_visibility_browsertest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3fc4a27402d9672e667530a39cb7f05d02f67fb1
|
| --- /dev/null
|
| +++ b/content/browser/media/session/media_session_visibility_browsertest.cc
|
| @@ -0,0 +1,266 @@
|
| +// Copyright 2016 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 "base/command_line.h"
|
| +#include "content/browser/media/session/media_session.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/common/content_switches.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/test_navigation_observer.h"
|
| +#include "content/shell/browser/shell.h"
|
| +#include "media/base/media_switches.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace content {
|
| +namespace {
|
| +static const char kStartPlayerScript[] =
|
| + "document.getElementById('long-video').play()";
|
| +static const char kPausePlayerScript[] =
|
| + "document.getElementById('long-video').pause()";
|
| +}
|
| +
|
| +
|
| +// Base class of MediaSession visibility tests. The class is intended
|
| +// to be used to run tests under different configurations. Tests
|
| +// should inheret from this class, set up their own command line per
|
| +// their configuration, and use macro INCLUDE_TEST_FROM_BASE_CLASS to
|
| +// include required tests. See
|
| +// media_session_visibility_browsertest_instances.cc for examples.
|
| +class MediaSessionVisibilityBrowserTest
|
| + : public ContentBrowserTest {
|
| + public:
|
| + MediaSessionVisibilityBrowserTest() = default;
|
| + ~MediaSessionVisibilityBrowserTest() override = default;
|
| +
|
| + void SetUpOnMainThread() override {
|
| + ContentBrowserTest::SetUpOnMainThread();
|
| + web_contents_ = shell()->web_contents();
|
| + media_session_ = MediaSession::Get(web_contents_);
|
| +
|
| + media_session_state_loop_runners_[MediaSession::State::ACTIVE] =
|
| + new MessageLoopRunner();
|
| + media_session_state_loop_runners_[MediaSession::State::SUSPENDED] =
|
| + new MessageLoopRunner();
|
| + media_session_state_loop_runners_[MediaSession::State::INACTIVE] =
|
| + new MessageLoopRunner();
|
| + media_session_state_callback_subscription_ =
|
| + media_session_->RegisterMediaSessionStateChangedCallbackForTest(
|
| + base::Bind(&MediaSessionVisibilityBrowserTest::
|
| + OnMediaSessionStateChanged,
|
| + base::Unretained(this)));
|
| + }
|
| +
|
| + void TearDownOnMainThread() override {
|
| + // Unsubscribe the callback subscription before tearing down, so that the
|
| + // CallbackList in MediaSession will be empty when it is destroyed.
|
| + media_session_state_callback_subscription_.reset();
|
| + }
|
| +
|
| + void SetUpCommandLine(base::CommandLine* command_line) override {
|
| + command_line->AppendSwitch(
|
| + switches::kDisableGestureRequirementForMediaPlayback);
|
| +#if !defined(OS_ANDROID)
|
| + command_line->AppendSwitch(
|
| + switches::kEnableDefaultMediaSession);
|
| +#endif // !defined(OS_ANDROID)
|
| + }
|
| +
|
| + void LoadTestPage() {
|
| + TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
|
| + shell()->LoadURL(GetTestUrl("android/media", "media-session.html"));
|
| + navigation_observer.Wait();
|
| + }
|
| +
|
| + void RunScript(const std::string& script) {
|
| + ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(), script));
|
| + }
|
| +
|
| + void ClearMediaSessionStateLoopRunners() {
|
| + for (auto& state_loop_runner : media_session_state_loop_runners_)
|
| + state_loop_runner.second = new MessageLoopRunner();
|
| + }
|
| +
|
| + void OnMediaSessionStateChanged(MediaSession::State state) {
|
| + ASSERT_TRUE(media_session_state_loop_runners_.count(state));
|
| + media_session_state_loop_runners_[state]->Quit();
|
| + }
|
| +
|
| + // TODO(zqzhang): This method is shared with
|
| + // MediaRouterIntegrationTests. Move it into a general place.
|
| + void Wait(base::TimeDelta timeout) {
|
| + base::RunLoop run_loop;
|
| + base::MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE, run_loop.QuitClosure(), timeout);
|
| + run_loop.Run();
|
| + }
|
| +
|
| + void WaitForMediaSessionState(MediaSession::State state) {
|
| + ASSERT_TRUE(media_session_state_loop_runners_.count(state));
|
| + media_session_state_loop_runners_[state]->Run();
|
| + }
|
| +
|
| + protected:
|
| + void TestSessionInactiveWhenHiddenAfterContentPause() {
|
| + LoadTestPage();
|
| +
|
| + ClearMediaSessionStateLoopRunners();
|
| + RunScript(kStartPlayerScript);
|
| + WaitForMediaSessionState(MediaSession::State::ACTIVE);
|
| +
|
| + ClearMediaSessionStateLoopRunners();
|
| + RunScript(kPausePlayerScript);
|
| + WaitForMediaSessionState(MediaSession::State::SUSPENDED);
|
| +
|
| + ClearMediaSessionStateLoopRunners();
|
| + web_contents_->WasHidden();
|
| + WaitForMediaSessionState(MediaSession::State::INACTIVE);
|
| + }
|
| +
|
| + void TestSessionInactiveWhenHiddenWhilePlaying() {
|
| + LoadTestPage();
|
| +
|
| + ClearMediaSessionStateLoopRunners();
|
| + RunScript(kStartPlayerScript);
|
| + WaitForMediaSessionState(MediaSession::State::ACTIVE);
|
| +
|
| + ClearMediaSessionStateLoopRunners();
|
| + web_contents_->WasHidden();
|
| + WaitForMediaSessionState(MediaSession::State::INACTIVE);
|
| + }
|
| +
|
| + void TestSessionSuspendedWhenHiddenAfterContentPause() {
|
| + LoadTestPage();
|
| +
|
| + ClearMediaSessionStateLoopRunners();
|
| + RunScript(kStartPlayerScript);
|
| + WaitForMediaSessionState(MediaSession::State::ACTIVE);
|
| +
|
| + ClearMediaSessionStateLoopRunners();
|
| + RunScript(kPausePlayerScript);
|
| + WaitForMediaSessionState(MediaSession::State::SUSPENDED);
|
| +
|
| + // Wait for 1 second and check the MediaSession state.
|
| + // No better solution till now.
|
| + web_contents_->WasHidden();
|
| + Wait(base::TimeDelta::FromSeconds(1));
|
| + ASSERT_EQ(media_session_->audio_focus_state_,
|
| + MediaSession::State::SUSPENDED);
|
| + }
|
| +
|
| + void TestSessionActiveWhenHiddenWhilePlaying() {
|
| + LoadTestPage();
|
| +
|
| + ClearMediaSessionStateLoopRunners();
|
| + RunScript(kStartPlayerScript);
|
| + WaitForMediaSessionState(MediaSession::State::ACTIVE);
|
| +
|
| + // Wait for 1 second and check the MediaSession state.
|
| + // No better solution till now.
|
| + web_contents_->WasHidden();
|
| + Wait(base::TimeDelta::FromSeconds(1));
|
| + ASSERT_EQ(media_session_->audio_focus_state_,
|
| + MediaSession::State::ACTIVE);
|
| + }
|
| +
|
| + WebContents* web_contents_;
|
| + MediaSession* media_session_;
|
| + // MessageLoopRunners for waiting MediaSession state to change. Note that the
|
| + // MessageLoopRunners can accept Quit() before calling Run(), thus the state
|
| + // change can still be captured before waiting. For example, the MediaSession
|
| + // might go active immediately after calling HTMLMediaElement.play(). A test
|
| + // can listen to the state change before calling play(), and then wait for the
|
| + // state change after play().
|
| + std::map<MediaSession::State, scoped_refptr<MessageLoopRunner> >
|
| + media_session_state_loop_runners_;
|
| + scoped_ptr<base::CallbackList<void(MediaSession::State)>::Subscription>
|
| + media_session_state_callback_subscription_;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(MediaSessionVisibilityBrowserTest);
|
| +};
|
| +
|
| +// Helper macro to include tests from the base class.
|
| +#define INCLUDE_TEST_FROM_BASE_CLASS(test_fixture, test_name) \
|
| + IN_PROC_BROWSER_TEST_F(test_fixture, test_name) { \
|
| + test_name(); \
|
| + }
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// Configuration instances.
|
| +
|
| +// UnifiedPipeline + SuspendOnHide
|
| +class MediaSessionVisibilityBrowserTest_UnifiedPipeline_SuspendOnHide :
|
| + public MediaSessionVisibilityBrowserTest {
|
| + void SetUpCommandLine(base::CommandLine* command_line) override {
|
| + MediaSessionVisibilityBrowserTest::SetUpCommandLine(command_line);
|
| +#if !defined(OS_ANDROID)
|
| + command_line->AppendSwitch(switches::kEnableMediaSuspend);
|
| +#endif // defined(OS_ANDROID)
|
| + }
|
| +};
|
| +
|
| +INCLUDE_TEST_FROM_BASE_CLASS(
|
| + MediaSessionVisibilityBrowserTest_UnifiedPipeline_SuspendOnHide,
|
| + TestSessionInactiveWhenHiddenAfterContentPause)
|
| +INCLUDE_TEST_FROM_BASE_CLASS(
|
| + MediaSessionVisibilityBrowserTest_UnifiedPipeline_SuspendOnHide,
|
| + TestSessionInactiveWhenHiddenWhilePlaying)
|
| +
|
| +// UnifiedPipeline + NosuspendOnHide
|
| +class MediaSessionVisibilityBrowserTest_UnifiedPipeline_NosuspendOnHide :
|
| + public MediaSessionVisibilityBrowserTest {
|
| + void SetUpCommandLine(base::CommandLine* command_line) override {
|
| + MediaSessionVisibilityBrowserTest::SetUpCommandLine(command_line);
|
| +#if defined(OS_ANDROID)
|
| + command_line->AppendSwitch(switches::kDisableMediaSuspend);
|
| +#endif // defined(OS_ANDROID)
|
| + }
|
| +};
|
| +
|
| +INCLUDE_TEST_FROM_BASE_CLASS(
|
| + MediaSessionVisibilityBrowserTest_UnifiedPipeline_NosuspendOnHide,
|
| + TestSessionSuspendedWhenHiddenAfterContentPause)
|
| +INCLUDE_TEST_FROM_BASE_CLASS(
|
| + MediaSessionVisibilityBrowserTest_UnifiedPipeline_NosuspendOnHide,
|
| + TestSessionActiveWhenHiddenWhilePlaying)
|
| +
|
| +#if defined(OS_ANDROID)
|
| +// AndroidPipeline + SuspendOnHide
|
| +class MediaSessionVisibilityBrowserTest_AndroidPipeline_SuspendOnHide :
|
| + public MediaSessionVisibilityBrowserTest {
|
| + void SetUpCommandLine(base::CommandLine* command_line) override {
|
| + MediaSessionVisibilityBrowserTest::SetUpCommandLine(command_line);
|
| + command_line->AppendSwitch(switches::kDisableUnifiedMediaPipeline);
|
| + }
|
| +};
|
| +
|
| +INCLUDE_TEST_FROM_BASE_CLASS(
|
| + MediaSessionVisibilityBrowserTest_AndroidPipeline_SuspendOnHide,
|
| + TestSessionInactiveWhenHiddenAfterContentPause)
|
| +INCLUDE_TEST_FROM_BASE_CLASS(
|
| + MediaSessionVisibilityBrowserTest_AndroidPipeline_SuspendOnHide,
|
| + TestSessionInactiveWhenHiddenWhilePlaying)
|
| +
|
| +// AndroidPipeline + NosuspendOnHide
|
| +class MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide :
|
| + public MediaSessionVisibilityBrowserTest {
|
| + void SetUpCommandLine(base::CommandLine* command_line) override {
|
| + MediaSessionVisibilityBrowserTest::SetUpCommandLine(command_line);
|
| + command_line->AppendSwitch(switches::kDisableUnifiedMediaPipeline);
|
| + command_line->AppendSwitch(switches::kDisableMediaSuspend);
|
| + }
|
| +};
|
| +
|
| +INCLUDE_TEST_FROM_BASE_CLASS(
|
| + MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide,
|
| + TestSessionSuspendedWhenHiddenAfterContentPause)
|
| +INCLUDE_TEST_FROM_BASE_CLASS(
|
| + MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide,
|
| + TestSessionActiveWhenHiddenWhilePlaying)
|
| +
|
| +#endif // defined(OS_ANDROID)
|
| +
|
| +} // namespace content
|
|
|