Commit a65ad1b5 authored by Andres Medina's avatar Andres Medina Committed by Commit Bot

[chromecast] MediaBlock: Added cast renderer initialization block.

Allowed a new type of media block that blocks cast_renderer
initialization instead of webmediaplayer loading.

Test: Manual test blocking is happening at the renderer by inspecting
device logs
Bug: b/134961542

Change-Id: I97b0e59a6752c43d14b8e96327079aa8669b1c00
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1673829Reviewed-by: default avatarSean Topping <seantopping@chromium.org>
Reviewed-by: default avatarYuchen Liu <yucliu@chromium.org>
Auto-Submit: Andres Medina <medinaandres@chromium.org>
Commit-Queue: Andres Medina <medinaandres@chromium.org>
Cr-Commit-Position: refs/heads/master@{#672687}
parent 6b3b3baa
......@@ -82,6 +82,8 @@ cast_source_set("browser") {
"cast_permission_manager.h",
"cast_quota_permission_context.cc",
"cast_quota_permission_context.h",
"cast_renderer_block_data.cc",
"cast_renderer_block_data.h",
"cast_resource_dispatcher_host_delegate.cc",
"cast_resource_dispatcher_host_delegate.h",
"cast_session_id_map.cc",
......@@ -502,6 +504,7 @@ cast_source_set("unittests") {
testonly = true
sources = [
"application_media_info_manager_unittest.cc",
"bluetooth/cast_bluetooth_chooser_unittest.cc",
"cast_media_blocker_unittest.cc",
"cast_network_delegate_unittest.cc",
......
......@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "chromecast/browser/application_media_info_manager.h"
#include "chromecast/browser/cast_renderer_block_data.h"
#include "content/public/browser/web_contents.h"
#include <utility>
......@@ -28,12 +30,39 @@ ApplicationMediaInfoManager::ApplicationMediaInfoManager(
bool mixer_audio_enabled)
: FrameServiceBase(render_frame_host, std::move(request)),
application_session_id_(std::move(application_session_id)),
mixer_audio_enabled_(mixer_audio_enabled) {}
mixer_audio_enabled_(mixer_audio_enabled),
renderer_blocked_(false) {
shell::CastRendererBlockData::SetApplicationMediaInfoManagerForWebContents(
content::WebContents::FromRenderFrameHost(render_frame_host), this);
}
ApplicationMediaInfoManager::~ApplicationMediaInfoManager() = default;
void ApplicationMediaInfoManager::SetRendererBlock(bool renderer_blocked) {
LOG(INFO) << "Setting blocked to: " << renderer_blocked << " from "
<< renderer_blocked_
<< "(Pending call set: " << (!pending_call_.is_null()) << ")";
if (renderer_blocked_ && !renderer_blocked && pending_call_) {
// Move callbacks in case CanStartRenderer() is called.
std::move(pending_call_)
.Run(::media::mojom::CastApplicationMediaInfo::New(
application_session_id_, mixer_audio_enabled_));
pending_call_.Reset();
}
renderer_blocked_ = renderer_blocked;
}
void ApplicationMediaInfoManager::GetCastApplicationMediaInfo(
GetCastApplicationMediaInfoCallback callback) {
LOG(INFO) << "GetCastApplicationMediaInfo called with blocked: "
<< renderer_blocked_;
if (renderer_blocked_) {
DCHECK(!pending_call_);
pending_call_ = std::move(callback);
return;
}
std::move(callback).Run(::media::mojom::CastApplicationMediaInfo::New(
application_session_id_, mixer_audio_enabled_));
}
......
......@@ -6,8 +6,10 @@
#define CHROMECAST_BROWSER_APPLICATION_MEDIA_INFO_MANAGER_H_
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/frame_service_base.h"
#include "media/mojo/interfaces/cast_application_media_info_manager.mojom.h"
......@@ -18,9 +20,12 @@ class RenderFrameHost;
namespace chromecast {
namespace media {
class ApplicationMediaInfoManagerTest;
class ApplicationMediaInfoManager
: public ::content::FrameServiceBase<
::media::mojom::CastApplicationMediaInfoManager> {
::media::mojom::CastApplicationMediaInfoManager>,
public base::SupportsWeakPtr<ApplicationMediaInfoManager> {
public:
ApplicationMediaInfoManager(
content::RenderFrameHost* render_frame_host,
......@@ -29,13 +34,19 @@ class ApplicationMediaInfoManager
bool mixer_audio_enabled);
~ApplicationMediaInfoManager() override;
void SetRendererBlock(bool renderer_blocked);
private:
friend ApplicationMediaInfoManagerTest;
// ::media::mojom::CastApplicationMediaInfoManager implementation:
void GetCastApplicationMediaInfo(
GetCastApplicationMediaInfoCallback callback) final;
GetCastApplicationMediaInfoCallback pending_call_;
const std::string application_session_id_;
bool mixer_audio_enabled_;
// Flag to determine if renderer can start.
bool renderer_blocked_;
DISALLOW_COPY_AND_ASSIGN(ApplicationMediaInfoManager);
};
......
// 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 "chromecast/browser/application_media_info_manager.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "content/public/test/test_content_client_initializer.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromecast {
namespace media {
using ::testing::_;
using ::testing::Invoke;
namespace {
const char kSessionId[] = "test-session-id";
constexpr bool kMixedAudioEnabled = true;
} // namespace
class ApplicationMediaInfoManagerTest
: public content::RenderViewHostTestHarness {
public:
ApplicationMediaInfoManagerTest() : started_(false) {}
~ApplicationMediaInfoManagerTest() override {}
void SetUp() override {
initializer_ = std::make_unique<content::TestContentClientInitializer>();
content::RenderViewHostTestHarness::SetUp();
application_media_info_manager_ =
std::make_unique<ApplicationMediaInfoManager>(
main_rfh(), mojo::MakeRequest(&application_media_info_manager_ptr_),
kSessionId, kMixedAudioEnabled);
}
void OnCastApplicationMediaInfo(
::media::mojom::CastApplicationMediaInfoPtr ptr) {
EXPECT_EQ(ptr->application_session_id, kSessionId);
EXPECT_EQ(ptr->mixer_audio_enabled, kMixedAudioEnabled);
started_ = true;
}
::media::mojom::CastApplicationMediaInfoManagerPtr
application_media_info_manager_ptr_;
std::unique_ptr<content::TestContentClientInitializer> initializer_;
std::unique_ptr<ApplicationMediaInfoManager> application_media_info_manager_;
bool started_;
};
TEST_F(ApplicationMediaInfoManagerTest, NoBlock_GetMediaInfo) {
application_media_info_manager_ptr_->GetCastApplicationMediaInfo(
base::BindOnce(
&ApplicationMediaInfoManagerTest::OnCastApplicationMediaInfo,
base::Unretained(this)));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(started_);
}
TEST_F(ApplicationMediaInfoManagerTest, Block_GetMediaInfo_Unblock) {
application_media_info_manager_->SetRendererBlock(true);
base::RunLoop().RunUntilIdle();
application_media_info_manager_ptr_->GetCastApplicationMediaInfo(
base::BindOnce(
&ApplicationMediaInfoManagerTest::OnCastApplicationMediaInfo,
base::Unretained(this)));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(started_);
application_media_info_manager_->SetRendererBlock(false);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(started_);
}
TEST_F(ApplicationMediaInfoManagerTest, Block_Unblock_GetMediaInfo) {
application_media_info_manager_->SetRendererBlock(true);
base::RunLoop().RunUntilIdle();
application_media_info_manager_->SetRendererBlock(false);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(started_);
application_media_info_manager_ptr_->GetCastApplicationMediaInfo(
base::BindOnce(
&ApplicationMediaInfoManagerTest::OnCastApplicationMediaInfo,
base::Unretained(this)));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(started_);
}
} // namespace media
} // namespace chromecast
......@@ -7,6 +7,7 @@
#include <utility>
#include "base/threading/thread_checker.h"
#include "chromecast/browser/cast_renderer_block_data.h"
#include "chromecast/common/mojom/media_playback_options.mojom.h"
#include "content/public/browser/media_session.h"
#include "content/public/browser/web_contents.h"
......@@ -20,7 +21,8 @@ CastMediaBlocker::CastMediaBlocker(content::WebContents* web_contents)
}
CastMediaBlocker::CastMediaBlocker(content::MediaSession* media_session)
: blocked_(false),
: media_loading_blocked_(false),
media_starting_blocked_(false),
paused_by_user_(true),
suspended_(true),
controllable_(false),
......@@ -34,18 +36,36 @@ CastMediaBlocker::CastMediaBlocker(content::MediaSession* media_session)
CastMediaBlocker::~CastMediaBlocker() {}
void CastMediaBlocker::BlockMediaLoading(bool blocked) {
if (blocked_ == blocked)
if (media_loading_blocked_ == blocked)
return;
blocked_ = blocked;
UpdateMediaBlockedState();
media_loading_blocked_ = blocked;
UpdateMediaLoadingBlockedState();
LOG(INFO) << __FUNCTION__ << " blocked=" << blocked_
UpdatePlayingState();
}
void CastMediaBlocker::BlockMediaStarting(bool blocked) {
if (media_starting_blocked_ == blocked)
return;
media_starting_blocked_ = blocked;
shell::CastRendererBlockData::SetRendererBlockForWebContents(
web_contents(), media_starting_blocked_);
UpdatePlayingState();
}
void CastMediaBlocker::UpdatePlayingState() {
LOG(INFO) << __FUNCTION__
<< " media_loading_blocked=" << media_loading_blocked_
<< " media_starting_blocked=" << media_starting_blocked_
<< " suspended=" << suspended_ << " controllable=" << controllable_
<< " paused_by_user=" << paused_by_user_;
// If blocking media, suspend if possible.
if (blocked_) {
if (PlayingBlocked()) {
if (!suspended_ && controllable_) {
Suspend();
}
......@@ -67,12 +87,18 @@ void CastMediaBlocker::EnableBackgroundVideoPlayback(bool enabled) {
UpdateBackgroundVideoPlaybackState();
}
bool CastMediaBlocker::PlayingBlocked() const {
return (media_loading_blocked_ || media_starting_blocked_);
}
void CastMediaBlocker::MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr session_info) {
bool is_suspended = session_info->playback_state ==
media_session::mojom::MediaPlaybackState::kPaused;
LOG(INFO) << __FUNCTION__ << " blocked=" << blocked_
LOG(INFO) << __FUNCTION__
<< " media_loading_blocked=" << media_loading_blocked_
<< " media_starting_blocked=" << media_starting_blocked_
<< " is_suspended=" << is_suspended
<< " is_controllable=" << session_info->is_controllable
<< " paused_by_user=" << paused_by_user_;
......@@ -83,13 +109,14 @@ void CastMediaBlocker::MediaSessionInfoChanged(
// If not blocked, and we regain control and the media wasn't paused when
// blocked, resume media if suspended.
if (!blocked_ && !paused_by_user_ && is_suspended && controllable_) {
if (!PlayingBlocked() && !paused_by_user_ && is_suspended &&
controllable_) {
paused_by_user_ = true;
Resume();
}
// Suspend if blocked and the session becomes controllable.
if (blocked_ && !is_suspended && controllable_) {
if (PlayingBlocked() && !is_suspended && controllable_) {
// Only suspend if suspended_ doesn't change. Otherwise, this will be
// handled in the suspended changed block.
if (suspended_ == is_suspended)
......@@ -101,7 +128,7 @@ void CastMediaBlocker::MediaSessionInfoChanged(
if (suspended_ != is_suspended) {
suspended_ = is_suspended;
// If blocking, suspend media whenever possible.
if (blocked_ && !suspended_) {
if (PlayingBlocked() && !suspended_) {
// If media was resumed when blocked, the user tried to play music.
paused_by_user_ = false;
if (controllable_)
......@@ -109,7 +136,7 @@ void CastMediaBlocker::MediaSessionInfoChanged(
}
// If not blocking, cache the user's play intent.
if (!blocked_)
if (!PlayingBlocked())
paused_by_user_ = suspended_;
}
}
......@@ -132,22 +159,22 @@ void CastMediaBlocker::Resume() {
void CastMediaBlocker::RenderFrameCreated(
content::RenderFrameHost* render_frame_host) {
UpdateRenderFrameMediaBlockedState(render_frame_host);
UpdateRenderFrameMediaLoadingBlockedState(render_frame_host);
UpdateRenderFrameBackgroundVideoPlaybackState(render_frame_host);
}
void CastMediaBlocker::RenderViewReady() {
UpdateMediaBlockedState();
UpdateMediaLoadingBlockedState();
}
void CastMediaBlocker::UpdateMediaBlockedState() {
void CastMediaBlocker::UpdateMediaLoadingBlockedState() {
if (!web_contents())
return;
const std::vector<content::RenderFrameHost*> frames =
web_contents()->GetAllFrames();
for (content::RenderFrameHost* frame : frames) {
UpdateRenderFrameMediaBlockedState(frame);
UpdateRenderFrameMediaLoadingBlockedState(frame);
}
}
......@@ -161,14 +188,14 @@ void CastMediaBlocker::UpdateBackgroundVideoPlaybackState() {
}
}
void CastMediaBlocker::UpdateRenderFrameMediaBlockedState(
void CastMediaBlocker::UpdateRenderFrameMediaLoadingBlockedState(
content::RenderFrameHost* render_frame_host) {
DCHECK(render_frame_host);
chromecast::shell::mojom::MediaPlaybackOptionsAssociatedPtr
media_playback_options;
render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
&media_playback_options);
media_playback_options->SetMediaLoadingBlocked(media_loading_blocked());
media_playback_options->SetMediaLoadingBlocked(media_loading_blocked_);
}
void CastMediaBlocker::UpdateRenderFrameBackgroundVideoPlaybackState(
......@@ -180,4 +207,9 @@ void CastMediaBlocker::UpdateRenderFrameBackgroundVideoPlaybackState(
background_video_playback_enabled_);
}
void CastMediaBlocker::SetMediaSessionForTesting(
content::MediaSession* media_session) {
media_session_ = media_session;
}
} // namespace chromecast
......@@ -18,6 +18,10 @@ class MediaSession;
namespace chromecast {
namespace shell {
class CastMediaBlockerTest;
} // namespace shell
// This class implements a blocking mode for web applications and is used in
// Chromecast internal code. Media is unblocked by default.
class CastMediaBlocker : public content::WebContentsObserver,
......@@ -31,9 +35,17 @@ class CastMediaBlocker : public content::WebContentsObserver,
~CastMediaBlocker() override;
// Sets if the web contents is allowed to play media or not. If media is
// unblocked, previously suspended elements should begin playing again.
// Sets if the web contents is allowed to load and play media or not.
// If media is unblocked, previously suspended elements should begin playing
// again. Media is unblocked when both MediaLoading and MediaStarting blocks
// are off.
void BlockMediaLoading(bool blocked);
// Sets if the web contents is allowed to play media or not. If media is
// unblocked, previously suspended elements should begin playing again. Media
// is unblocked when both MediaLoading and MediaStarting blocks are off.
// This is a more relaxed block than BlockMediaLoading since the block doesn't
// block media from loading but it does block media from starting.
void BlockMediaStarting(bool blocked);
void EnableBackgroundVideoPlayback(bool enabled);
// media_session::mojom::MediaSessionObserver implementation:
......@@ -50,8 +62,7 @@ class CastMediaBlocker : public content::WebContentsObserver,
override {}
private:
bool media_loading_blocked() const { return blocked_; }
friend shell::CastMediaBlockerTest;
// content::WebContentsObserver implementation:
void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
void RenderViewReady() override;
......@@ -62,17 +73,30 @@ class CastMediaBlocker : public content::WebContentsObserver,
// Blocks or unblocks the render process from loading new media
// according to |blocked_|.
void UpdateMediaBlockedState();
void UpdateRenderFrameMediaBlockedState(
void UpdateMediaLoadingBlockedState();
void UpdateRenderFrameMediaLoadingBlockedState(
content::RenderFrameHost* render_frame_host);
void UpdatePlayingState();
void UpdateBackgroundVideoPlaybackState();
void UpdateRenderFrameBackgroundVideoPlaybackState(
content::RenderFrameHost* frame);
// Whether or not media should be blocked. This value cache's the last call to
// BlockMediaLoading. Is false by default.
bool blocked_;
bool PlayingBlocked() const;
// MediaSession when initialized from WebContesnts is always a
// MediaSessionImpl type. This method allows to replace the MediaSession with
// mockable MediaSessions for testing.
void SetMediaSessionForTesting(content::MediaSession* media_session);
// Whether or not media loading should be blocked. This value cache's the last
// call to BlockMediaLoading. Is false by default.
bool media_loading_blocked_;
// Whether or not media starting should be blocked. This value cache's the
// last call to BlockMediaStarting. Is false by default.
bool media_starting_blocked_;
// Whether or not the user paused media on the page.
bool paused_by_user_;
......@@ -87,7 +111,7 @@ class CastMediaBlocker : public content::WebContentsObserver,
// be disabled.
bool background_video_playback_enabled_;
content::MediaSession* const media_session_;
content::MediaSession* media_session_;
mojo::Binding<media_session::mojom::MediaSessionObserver> observer_binding_{
this};
......
......@@ -9,6 +9,7 @@
#include "base/time/time.h"
#include "content/public/browser/media_session.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_content_client_initializer.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gmock/include/gmock/gmock.h"
......@@ -66,8 +67,10 @@ class CastMediaBlockerTest : public content::RenderViewHostTestHarness {
gl::GLSurfaceTestSupport::InitializeOneOff();
initializer_ = std::make_unique<content::TestContentClientInitializer>();
content::RenderViewHostTestHarness::SetUp();
web_contents_ = CreateTestWebContents();
media_session_ = std::make_unique<MockMediaSession>();
media_blocker_ = std::make_unique<CastMediaBlocker>(media_session_.get());
media_blocker_ = std::make_unique<CastMediaBlocker>(web_contents_.get());
media_blocker_->SetMediaSessionForTesting(media_session_.get());
}
void MediaSessionChanged(bool controllable, bool suspended) {
......@@ -81,10 +84,17 @@ class CastMediaBlockerTest : public content::RenderViewHostTestHarness {
media_blocker_->MediaSessionInfoChanged(std::move(session_info));
}
void TearDown() override {
media_blocker_.reset();
web_contents_.reset();
content::RenderViewHostTestHarness::TearDown();
}
protected:
std::unique_ptr<content::TestContentClientInitializer> initializer_;
std::unique_ptr<MockMediaSession> media_session_;
std::unique_ptr<CastMediaBlocker> media_blocker_;
std::unique_ptr<content::WebContents> web_contents_;
private:
DISALLOW_COPY_AND_ASSIGN(CastMediaBlockerTest);
......@@ -289,5 +299,130 @@ TEST_F(CastMediaBlockerTest, Unblocked_Already_Playing) {
media_blocker_->BlockMediaLoading(false);
}
TEST_F(CastMediaBlockerTest, BlockStarting_UnblockStarting_Suspended) {
// Testing block/unblock operations do nothing if media never plays.
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaStarting(true);
media_blocker_->BlockMediaStarting(false);
MediaSessionChanged(true, true);
media_blocker_->BlockMediaStarting(true);
media_blocker_->BlockMediaStarting(false);
media_blocker_->BlockMediaStarting(true);
MediaSessionChanged(false, true);
media_blocker_->BlockMediaStarting(false);
}
TEST_F(CastMediaBlockerTest, BlockStarting_Before_Controllable) {
// Tests CastMediaBlocker only suspends when controllable.
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaStarting(true);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
// Session becomes controllable
EXPECT_CALL(*media_session_, Suspend(_)).Times(1);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
MediaSessionChanged(true, false);
}
TEST_F(CastMediaBlockerTest, BlockStarting_After_Controllable) {
// Tests CastMediaBlocker suspends immediately on block if controllable.
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
MediaSessionChanged(true, false);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
// Block when media is playing
EXPECT_CALL(*media_session_, Suspend(_)).Times(1);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaStarting(true);
MediaSessionChanged(true, true);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
// Unblock
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(1);
media_blocker_->BlockMediaStarting(false);
}
TEST_F(CastMediaBlockerTest, BlockStarting_Unblock_Suspended) {
// Testing block/unblock operations do nothing if media never plays.
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaStarting(true);
media_blocker_->BlockMediaStarting(false);
MediaSessionChanged(true, true);
media_blocker_->BlockMediaStarting(true);
media_blocker_->BlockMediaStarting(false);
media_blocker_->BlockMediaStarting(true);
MediaSessionChanged(false, true);
media_blocker_->BlockMediaStarting(false);
}
TEST_F(CastMediaBlockerTest, BlockLoading_BlockStarting_After_Controllable) {
// Tests CastMediaBlocker suspends immediately on block if controllable.
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
MediaSessionChanged(true, false);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
// Block when media is playing
EXPECT_CALL(*media_session_, Suspend(_)).Times(1);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaLoading(true);
MediaSessionChanged(true, true);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaStarting(true);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
// Unblock
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaLoading(false);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(1);
media_blocker_->BlockMediaStarting(false);
}
TEST_F(CastMediaBlockerTest, BlockStarting_BlockLoading_After_Controllable) {
// Tests CastMediaBlocker suspends immediately on block if controllable.
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
MediaSessionChanged(true, false);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
// Block when media is playing
EXPECT_CALL(*media_session_, Suspend(_)).Times(1);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaStarting(true);
MediaSessionChanged(true, true);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaLoading(true);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
// Unblock
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(0);
media_blocker_->BlockMediaStarting(false);
testing::Mock::VerifyAndClearExpectations(media_session_.get());
EXPECT_CALL(*media_session_, Suspend(_)).Times(0);
EXPECT_CALL(*media_session_, Resume(_)).Times(1);
media_blocker_->BlockMediaLoading(false);
}
} // namespace shell
} // namespace chromecast
// Copyright 2019 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 "chromecast/browser/cast_renderer_block_data.h"
#include "chromecast/browser/application_media_info_manager.h"
#include "chromecast/browser/cast_session_id_map.h"
#include "content/public/browser/web_contents.h"
namespace chromecast {
namespace shell {
namespace {
const char kUserDataKey[] = "chromecast.shell.RenderBlockUserData.key";
CastRendererBlockData* GetOrCreateCastRendererBlockData(
content::WebContents* web_contents) {
CastRendererBlockData* data = static_cast<CastRendererBlockData*>(
web_contents->GetUserData(kUserDataKey));
if (!data) {
auto cast_renderer_block_data = std::make_unique<CastRendererBlockData>();
data = cast_renderer_block_data.get();
web_contents->SetUserData(kUserDataKey,
std::move(cast_renderer_block_data));
}
return data;
}
} // namespace
// static
void CastRendererBlockData::SetRendererBlockForWebContents(
content::WebContents* web_contents,
bool blocked) {
DCHECK(web_contents);
CastRendererBlockData* data = GetOrCreateCastRendererBlockData(web_contents);
data->SetBlocked(blocked);
}
// static
void CastRendererBlockData::SetApplicationMediaInfoManagerForWebContents(
content::WebContents* web_contents,
media::ApplicationMediaInfoManager* application_media_info_manager) {
DCHECK(web_contents);
CastRendererBlockData* data = GetOrCreateCastRendererBlockData(web_contents);
data->SetApplicationMediaInfoManager(application_media_info_manager);
}
CastRendererBlockData::CastRendererBlockData() : blocked_(false) {}
CastRendererBlockData::~CastRendererBlockData() = default;
void CastRendererBlockData::SetBlocked(bool blocked) {
LOG(INFO) << "Setting blocked to: " << blocked << " from " << blocked_;
blocked_ = blocked;
if (application_media_info_manager_) {
application_media_info_manager_->SetRendererBlock(blocked);
}
}
void CastRendererBlockData::SetApplicationMediaInfoManager(
media::ApplicationMediaInfoManager* application_media_info_manager) {
DCHECK(application_media_info_manager);
application_media_info_manager_ =
base::AsWeakPtr(application_media_info_manager);
application_media_info_manager_->SetRendererBlock(blocked_);
}
} // namespace shell
} // namespace chromecast
// Copyright 2019 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.
#ifndef CHROMECAST_BROWSER_CAST_RENDERER_BLOCK_DATA_H_
#define CHROMECAST_BROWSER_CAST_RENDERER_BLOCK_DATA_H_
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
namespace content {
class WebContents;
}
namespace chromecast {
namespace media {
class ApplicationMediaInfoManager;
}
namespace shell {
class CastRendererBlockData : public base::SupportsUserData::Data {
public:
static void SetRendererBlockForWebContents(content::WebContents* web_contents,
bool blocked);
static void SetApplicationMediaInfoManagerForWebContents(
content::WebContents* web_contents,
media::ApplicationMediaInfoManager* application_media_info_manager);
CastRendererBlockData();
~CastRendererBlockData() override;
bool blocked() const { return blocked_; }
void SetBlocked(bool blocked);
void SetApplicationMediaInfoManager(
media::ApplicationMediaInfoManager* application_media_info_manager);
private:
bool blocked_;
base::WeakPtr<media::ApplicationMediaInfoManager>
application_media_info_manager_;
};
} // namespace shell
} // namespace chromecast
#endif // CHROMECAST_BROWSER_CAST_RENDERER_BLOCK_DATA_H_
......@@ -266,6 +266,10 @@ class CastWebContents {
// Block/unblock media from loading in all RenderFrames for the WebContents.
virtual void BlockMediaLoading(bool blocked) = 0;
// Block/unblock media from starting in all RenderFrames for the WebContents.
// As opposed to |BlockMediaLoading|, |BlockMediaStarting| allows media to
// load while in blocking state.
virtual void BlockMediaStarting(bool blocked) = 0;
virtual void EnableBackgroundVideoPlayback(bool enabled) = 0;
// ===========================================================================
......
......@@ -189,6 +189,11 @@ void CastWebContentsImpl::BlockMediaLoading(bool blocked) {
media_blocker_->BlockMediaLoading(blocked);
}
void CastWebContentsImpl::BlockMediaStarting(bool blocked) {
if (media_blocker_)
media_blocker_->BlockMediaStarting(blocked);
}
void CastWebContentsImpl::EnableBackgroundVideoPlayback(bool enabled) {
if (media_blocker_)
media_blocker_->EnableBackgroundVideoPlayback(enabled);
......
......@@ -55,6 +55,7 @@ class CastWebContentsImpl : public CastWebContents,
service_manager::InterfaceProvider* interface_provider) override;
service_manager::BinderRegistry* binder_registry() override;
void BlockMediaLoading(bool blocked) override;
void BlockMediaStarting(bool blocked) override;
void EnableBackgroundVideoPlayback(bool enabled) override;
// Observer interface:
......
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