// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/cast_core/runtime/browser/cast_runtime_content_browser_client.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ref.h"
#include "chromecast/browser/cast_content_browser_client.h"
#include "chromecast/browser/service/cast_service_simple.h"
#include "chromecast/browser/webui/constants.h"
#include "chromecast/cast_core/cast_core_switches.h"
#include "chromecast/cast_core/runtime/browser/runtime_service_impl.h"
#include "chromecast/common/cors_exempt_headers.h"
#include "chromecast/media/base/video_plane_controller.h"
#include "components/cast_receiver/browser/public/runtime_application.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/content_switches.h"
#include "media/base/cdm_factory.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
namespace chromecast {
namespace {
// CastServiceSimple impl for Cast Core that allows the runtime service to start
// up and tear down.
class CoreCastService : public shell::CastServiceSimple {
public:
CoreCastService(CastWebService* web_service,
RuntimeServiceImpl& runtime_service)
: CastServiceSimple(web_service), runtime_service_(runtime_service) {}
// CastServiceSimple overrides:
void StartInternal() override {
if (!runtime_service_->Start().ok()) {
base::Process::TerminateCurrentProcessImmediately(1);
}
}
void StopInternal() override { runtime_service_->Stop(); }
private:
raw_ref<RuntimeServiceImpl> runtime_service_;
};
} // namespace
CastRuntimeContentBrowserClient::CastRuntimeContentBrowserClient(
CastFeatureListCreator* feature_list_creator)
: shell::CastContentBrowserClient(feature_list_creator),
cast_browser_client_mixins_(
cast_receiver::ContentBrowserClientMixins::Create(base::BindRepeating(
&CastRuntimeContentBrowserClient::GetSystemNetworkContext,
base::Unretained(this)))) {
cast_browser_client_mixins_->AddStreamingResolutionObserver(&observer_);
cast_browser_client_mixins_->AddApplicationStateObserver(&observer_);
}
CastRuntimeContentBrowserClient::~CastRuntimeContentBrowserClient() {
cast_browser_client_mixins_->RemoveStreamingResolutionObserver(&observer_);
cast_browser_client_mixins_->RemoveApplicationStateObserver(&observer_);
}
std::unique_ptr<CastService> CastRuntimeContentBrowserClient::CreateCastService(
content::BrowserContext* browser_context,
CastSystemMemoryPressureEvaluatorAdjuster* memory_pressure_adjuster,
PrefService* pref_service,
media::VideoPlaneController* video_plane_controller,
CastWindowManager* window_manager,
CastWebService* web_service,
DisplaySettingsManager* display_settings_manager) {
observer_.SetVideoPlaneController(video_plane_controller);
InitializeCoreComponents(web_service);
// Unretained() is safe here because this instance will outlive CastService.
return std::make_unique<CoreCastService>(web_service, *runtime_service_);
}
std::unique_ptr<::media::CdmFactory>
CastRuntimeContentBrowserClient::CreateCdmFactory(
::media::mojom::FrameInterfaceFactory* frame_interfaces) {
return nullptr;
}
void CastRuntimeContentBrowserClient::AppendExtraCommandLineSwitches(
base::CommandLine* command_line,
int child_process_id) {
CastContentBrowserClient::AppendExtraCommandLineSwitches(command_line,
child_process_id);
base::CommandLine* browser_command_line =
base::CommandLine::ForCurrentProcess();
if (browser_command_line->HasSwitch(switches::kLogFile) &&
!command_line->HasSwitch(switches::kLogFile)) {
static const char* const kPath[] = {switches::kLogFile};
command_line->CopySwitchesFrom(*browser_command_line, kPath);
}
}
bool CastRuntimeContentBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
const url::Origin& origin) {
return origin.host() == kCastWebUIHomeHost;
}
bool CastRuntimeContentBrowserClient::IsBufferingEnabled() {
return observer_.IsBufferingEnabled();
}
void CastRuntimeContentBrowserClient::OnWebContentsCreated(
content::WebContents* web_contents) {
cast_browser_client_mixins_->OnWebContentsCreated(web_contents);
}
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
CastRuntimeContentBrowserClient::CreateURLLoaderThrottles(
const network::ResourceRequest& request,
content::BrowserContext* browser_context,
const base::RepeatingCallback<content::WebContents*()>& wc_getter,
content::NavigationUIData* navigation_ui_data,
int frame_tree_node_id,
std::optional<int64_t> navigation_id) {
return cast_browser_client_mixins_->CreateURLLoaderThrottles(
std::move(wc_getter), frame_tree_node_id,
base::BindRepeating(&IsCorsExemptHeader));
}
CastRuntimeContentBrowserClient::Observer::~Observer() = default;
void CastRuntimeContentBrowserClient::Observer::SetVideoPlaneController(
media::VideoPlaneController* video_plane_controller) {
video_plane_controller_ = video_plane_controller;
}
bool CastRuntimeContentBrowserClient::Observer::IsBufferingEnabled() const {
return is_buffering_enabled_.load();
}
void CastRuntimeContentBrowserClient::Observer::OnForegroundApplicationChanged(
cast_receiver::RuntimeApplication* app) {
bool enabled = true;
// Buffering must be disabled for streaming applications.
if (app && app->IsStreamingApplication()) {
enabled = false;
}
is_buffering_enabled_.store(enabled);
DLOG(INFO) << "Buffering is " << (enabled ? "enabled" : "disabled");
}
void CastRuntimeContentBrowserClient::Observer::OnStreamingResolutionChanged(
const gfx::Rect& size,
const ::media::VideoTransformation& transformation) {
if (video_plane_controller_) {
video_plane_controller_->SetGeometryFromMediaType(size, transformation);
}
}
void CastRuntimeContentBrowserClient::InitializeCoreComponents(
CastWebService* web_service) {
runtime_service_ = std::make_unique<RuntimeServiceImpl>(
*cast_browser_client_mixins_, *web_service);
}
} // namespace chromecast