Commit 81fcb61e authored by Kevin Marshall's avatar Kevin Marshall Committed by Commit Bot

[cast_runner] Enable headless mode using device configuration data.

Enables HEADLESS operation on screen-less devices, using a switch
published via the system's config store.

Reading/parsing logic is promoted to a common library,
"config_reader.h", and ContextProvider is modified to use it.

Bug: 1025045
Change-Id: Iad72297cf0e2a2d30e2650563c23d58204ad7eb5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1989998
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Reviewed-by: default avatarSergey Ulanov <sergeyu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#729920}
parent 22850ca6
...@@ -11,11 +11,13 @@ import("//testing/test.gni") ...@@ -11,11 +11,13 @@ import("//testing/test.gni")
# Integration helpers for commonly used fuchsia.* APIs. # Integration helpers for commonly used fuchsia.* APIs.
source_set("base") { source_set("base") {
sources = [ sources = [
"config_reader.cc",
"init_logging.cc", "init_logging.cc",
"mem_buffer_util.cc", "mem_buffer_util.cc",
"string_util.cc", "string_util.cc",
] ]
public = [ public = [
"config_reader.h",
"init_logging.h", "init_logging.h",
"mem_buffer_util.h", "mem_buffer_util.h",
"string_util.h", "string_util.h",
......
// Copyright 2020 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 "fuchsia/base/config_reader.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
namespace cr_fuchsia {
base::Optional<base::Value> LoadPackageConfig() {
constexpr char kConfigPath[] = "/config/data/config.json";
base::FilePath path(kConfigPath);
if (!base::PathExists(path)) {
LOG(WARNING) << "Config file doesn't exist: " << path.value();
return base::nullopt;
}
std::string file_content;
bool loaded = base::ReadFileToString(path, &file_content);
if (!loaded) {
LOG(WARNING) << "Couldn't read config file: " << path.value();
return base::nullopt;
}
base::JSONReader reader;
base::Optional<base::Value> parsed = reader.Read(file_content);
CHECK(parsed) << "Failed to parse " << path.value() << ": "
<< reader.GetErrorMessage();
CHECK(parsed->is_dict()) << "Config is not a JSON dictinary: "
<< path.value();
return std::move(parsed.value());
}
} // namespace cr_fuchsia
// Copyright 2020 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 FUCHSIA_BASE_CONFIG_READER_H_
#define FUCHSIA_BASE_CONFIG_READER_H_
#include "base/files/file_path.h"
#include "base/values.h"
namespace cr_fuchsia {
// Loads and parses configuration data from the environment.
// Returns a null value if the file(s) do not exist.
// CHECK-fails if the file(s) are present but not parseable.
base::Optional<base::Value> LoadPackageConfig();
} // namespace cr_fuchsia
#endif // FUCHSIA_BASE_CONFIG_READER_H_
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "components/viz/common/features.h" #include "components/viz/common/features.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "fuchsia/base/config_reader.h"
#include "fuchsia/engine/common/web_engine_content_client.h" #include "fuchsia/engine/common/web_engine_content_client.h"
#include "fuchsia/engine/switches.h" #include "fuchsia/engine/switches.h"
#include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/command_buffer/service/gpu_switches.h"
...@@ -114,32 +115,15 @@ bool SetContentDirectoriesInCommandLine( ...@@ -114,32 +115,15 @@ bool SetContentDirectoriesInCommandLine(
return true; return true;
} }
constexpr char kConfigFileName[] = "/config/data/config.json"; base::Value LoadConfig() {
base::Optional<base::Value> config = cr_fuchsia::LoadPackageConfig();
base::Value LoadConfigFrom(const base::FilePath& file_path) { if (!config) {
if (!base::PathExists(file_path)) { DLOG(WARNING) << "Configuration data not found. Using default "
DLOG(WARNING) << file_path.value() "WebEngine configuration.";
<< " doesn't exist. Using default WebEngine configuration.";
return base::Value(base::Value::Type::DICTIONARY); return base::Value(base::Value::Type::DICTIONARY);
} }
std::string file_content; return std::move(*config);
bool loaded = base::ReadFileToString(file_path, &file_content);
CHECK(loaded) << "Failed to read " << file_path.value();
base::JSONReader reader;
base::Optional<base::Value> parsed = reader.Read(file_content);
CHECK(parsed) << "Failed to parse " << file_path.value() << ": "
<< reader.GetErrorMessage();
CHECK(parsed->is_dict()) << "Config is not a JSON dictinary: "
<< file_path.value();
return std::move(parsed.value());
}
const base::Value& GetWebEngineConfig() {
static base::Value config = LoadConfigFrom(base::FilePath(kConfigFileName));
return config;
} }
// Returns false if the config is present but has invalid contents. // Returns false if the config is present but has invalid contents.
...@@ -303,6 +287,15 @@ void ContextProviderImpl::Create( ...@@ -303,6 +287,15 @@ void ContextProviderImpl::Create(
if (params.has_features()) if (params.has_features())
features = params.features(); features = params.features();
const bool is_headless =
(features & fuchsia::web::ContextFeatureFlags::HEADLESS) ==
fuchsia::web::ContextFeatureFlags::HEADLESS;
if (is_headless) {
launch_command.AppendSwitchNative(switches::kOzonePlatform,
switches::kHeadless);
launch_command.AppendSwitch(switches::kHeadless);
}
bool enable_vulkan = (features & fuchsia::web::ContextFeatureFlags::VULKAN) == bool enable_vulkan = (features & fuchsia::web::ContextFeatureFlags::VULKAN) ==
fuchsia::web::ContextFeatureFlags::VULKAN; fuchsia::web::ContextFeatureFlags::VULKAN;
bool enable_widevine = bool enable_widevine =
...@@ -320,21 +313,12 @@ void ContextProviderImpl::Create( ...@@ -320,21 +313,12 @@ void ContextProviderImpl::Create(
} }
bool enable_drm = enable_widevine || enable_playready; bool enable_drm = enable_widevine || enable_playready;
if (enable_drm && !enable_vulkan) { if (enable_drm && !enable_vulkan && !is_headless) {
DLOG(ERROR) << "WIDEVINE_CDM and PLAYREADY_CDM features require VULKAN."; DLOG(ERROR) << "WIDEVINE_CDM and PLAYREADY_CDM features require VULKAN.";
context_request.Close(ZX_ERR_INVALID_ARGS); context_request.Close(ZX_ERR_INVALID_ARGS);
return; return;
} }
const bool is_headless =
(features & fuchsia::web::ContextFeatureFlags::HEADLESS) ==
fuchsia::web::ContextFeatureFlags::HEADLESS;
if (is_headless) {
launch_command.AppendSwitchNative(switches::kOzonePlatform,
switches::kHeadless);
launch_command.AppendSwitch(switches::kHeadless);
}
if (enable_vulkan) { if (enable_vulkan) {
if (is_headless) { if (is_headless) {
LOG(ERROR) << "VULKAN and HEADLESS features cannot be used together."; LOG(ERROR) << "VULKAN and HEADLESS features cannot be used together.";
...@@ -365,8 +349,9 @@ void ContextProviderImpl::Create( ...@@ -365,8 +349,9 @@ void ContextProviderImpl::Create(
launch_command.AppendSwitch(switches::kDisableSoftwareRasterizer); launch_command.AppendSwitch(switches::kDisableSoftwareRasterizer);
} }
const base::Value& web_engine_config = base::Value web_engine_config =
config_for_test_.is_none() ? GetWebEngineConfig() : config_for_test_; config_for_test_.is_none() ? LoadConfig() : std::move(config_for_test_);
bool allow_protected_graphics = bool allow_protected_graphics =
web_engine_config.FindBoolPath("allow-protected-graphics") web_engine_config.FindBoolPath("allow-protected-graphics")
.value_or(false); .value_or(false);
......
{ {
"sandbox": { "sandbox": {
"features": [
"config-data"
],
"services": [ "services": [
"chromium.cast.ApplicationConfigManager", "chromium.cast.ApplicationConfigManager",
"fuchsia.accessibility.semantics.SemanticsManager", "fuchsia.accessibility.semantics.SemanticsManager",
......
...@@ -8,13 +8,32 @@ ...@@ -8,13 +8,32 @@
#include "base/fuchsia/default_context.h" #include "base/fuchsia/default_context.h"
#include "base/fuchsia/file_utils.h" #include "base/fuchsia/file_utils.h"
#include "base/message_loop/message_pump_type.h" #include "base/message_loop/message_pump_type.h"
#include "base/optional.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/task/single_thread_task_executor.h" #include "base/task/single_thread_task_executor.h"
#include "base/values.h"
#include "build/buildflag.h" #include "build/buildflag.h"
#include "fuchsia/base/config_reader.h"
#include "fuchsia/base/init_logging.h" #include "fuchsia/base/init_logging.h"
#include "fuchsia/runners/buildflags.h" #include "fuchsia/runners/buildflags.h"
#include "fuchsia/runners/cast/cast_runner.h" #include "fuchsia/runners/cast/cast_runner.h"
namespace {
bool IsHeadless() {
constexpr char kHeadlessConfigKey[] = "headless";
base::Optional<base::Value> config = cr_fuchsia::LoadPackageConfig();
if (config) {
base::Optional<bool> headless = config->FindBoolPath(kHeadlessConfigKey);
return headless && *headless;
}
return false;
}
} // namespace
int main(int argc, char** argv) { int main(int argc, char** argv) {
base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO); base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO);
base::RunLoop run_loop; base::RunLoop run_loop;
...@@ -27,10 +46,16 @@ int main(int argc, char** argv) { ...@@ -27,10 +46,16 @@ int main(int argc, char** argv) {
fuchsia::web::ContextFeatureFlags features = fuchsia::web::ContextFeatureFlags features =
fuchsia::web::ContextFeatureFlags::NETWORK | fuchsia::web::ContextFeatureFlags::NETWORK |
fuchsia::web::ContextFeatureFlags::AUDIO | fuchsia::web::ContextFeatureFlags::AUDIO |
fuchsia::web::ContextFeatureFlags::VULKAN | fuchsia::web::ContextFeatureFlags::WIDEVINE_CDM;
fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER |
fuchsia::web::ContextFeatureFlags::WIDEVINE_CDM | if (IsHeadless()) {
fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER_ONLY; LOG(WARNING) << "Running in headless mode.";
features |= fuchsia::web::ContextFeatureFlags::HEADLESS;
} else {
features |= fuchsia::web::ContextFeatureFlags::VULKAN |
fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER |
fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER_ONLY;
}
fuchsia::web::CreateContextParams create_context_params; fuchsia::web::CreateContextParams create_context_params;
create_context_params.set_features(features); create_context_params.set_features(features);
...@@ -39,8 +64,6 @@ int main(int argc, char** argv) { ...@@ -39,8 +64,6 @@ int main(int argc, char** argv) {
base::FilePath(base::fuchsia::kServiceDirectoryPath))); base::FilePath(base::fuchsia::kServiceDirectoryPath)));
CHECK(create_context_params.service_directory()); CHECK(create_context_params.service_directory());
// TODO(crbug.com/1025045): Set HEADLESS flag based on system config data.
const char kCastPlayreadyKeySystem[] = "com.chromecast.playready"; const char kCastPlayreadyKeySystem[] = "com.chromecast.playready";
create_context_params.set_playready_key_system(kCastPlayreadyKeySystem); create_context_params.set_playready_key_system(kCastPlayreadyKeySystem);
......
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