diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-01-29 16:35:13 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-01 15:33:35 +0000 |
commit | c8c2d1901aec01e934adf561a9fdf0cc776cdef8 (patch) | |
tree | 9157c3d9815e5870799e070b113813bec53e0535 /chromium/content/gpu | |
parent | abefd5095b41dac94ca451d784ab6e27372e981a (diff) | |
download | qtwebengine-chromium-c8c2d1901aec01e934adf561a9fdf0cc776cdef8.tar.gz |
BASELINE: Update Chromium to 64.0.3282.139
Change-Id: I1cae68fe9c94ff7608b26b8382fc19862cdb293a
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/content/gpu')
-rw-r--r-- | chromium/content/gpu/BUILD.gn | 14 | ||||
-rw-r--r-- | chromium/content/gpu/DEPS | 4 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_child_thread.cc | 47 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_child_thread.h | 15 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_main.cc | 83 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_sandbox_hook_linux.cc | 351 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_sandbox_hook_linux.h | 17 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_service_factory.cc | 8 | ||||
-rw-r--r-- | chromium/content/gpu/in_process_gpu_thread.cc | 14 | ||||
-rw-r--r-- | chromium/content/gpu/in_process_gpu_thread.h | 9 |
10 files changed, 496 insertions, 66 deletions
diff --git a/chromium/content/gpu/BUILD.gn b/chromium/content/gpu/BUILD.gn index a5424bb7c11..b1277cbfae2 100644 --- a/chromium/content/gpu/BUILD.gn +++ b/chromium/content/gpu/BUILD.gn @@ -27,6 +27,7 @@ if (is_component_build) { } else { link_target_type = "static_library" } + target(link_target_type, "gpu_sources") { # This is an internal content API. Code outside of the content "component" # (like content/test and content/shell) should depend on ":gpu" above. @@ -38,6 +39,8 @@ target(link_target_type, "gpu_sources") { "gpu_main.cc", "gpu_process.cc", "gpu_process.h", + "gpu_sandbox_hook_linux.cc", + "gpu_sandbox_hook_linux.h", "gpu_service_factory.cc", "gpu_service_factory.h", "in_process_gpu_thread.cc", @@ -59,6 +62,7 @@ target(link_target_type, "gpu_sources") { "//content/public/common:common_sources", "//gpu:gpu", "//gpu/ipc/common:command_buffer_traits", + "//gpu/ipc/common:gpu_preferences_util", "//gpu/ipc/service", "//ipc", "//media/gpu", @@ -67,15 +71,16 @@ target(link_target_type, "gpu_sources") { # TODO(jrummell): As //media/gpu/ipc/service is a source_set in a # component build, determine if it should not be included here. # http://crbug.com/702833. + "//components/viz/service/main", "//media/gpu/ipc/service", "//media/mojo/clients:clients", "//services/service_manager/public/cpp", "//services/service_manager/public/interfaces", "//services/shape_detection:lib", "//services/shape_detection/public/interfaces", - "//services/ui/gpu", - "//services/ui/gpu/interfaces", + "//services/viz/privileged/interfaces", "//skia", + "//third_party/angle:angle_gpu_info_util", "//ui/gfx/ipc", "//ui/gl", "//ui/gl/init", @@ -114,4 +119,9 @@ target(link_target_type, "gpu_sources") { if (enable_vulkan) { deps += [ "//gpu/vulkan" ] } + + # Use DRI on desktop Linux builds. + if (is_desktop_linux && (!is_chromecast || is_cast_desktop_build)) { + configs += [ "//build/config/linux/dri" ] + } } diff --git a/chromium/content/gpu/DEPS b/chromium/content/gpu/DEPS index 11a913643f5..084a0645313 100644 --- a/chromium/content/gpu/DEPS +++ b/chromium/content/gpu/DEPS @@ -8,8 +8,8 @@ include_rules = [ "+services/service_manager", "+services/shape_detection", "+services/ui/common", - "+services/ui/gpu", - "+services/viz/privileged/interfaces/gl", + "+services/viz/privileged/interfaces", + "+services/viz/service", "+sandbox", "+skia", ] diff --git a/chromium/content/gpu/gpu_child_thread.cc b/chromium/content/gpu/gpu_child_thread.cc index 1048a37c9aa..6752f55e381 100644 --- a/chromium/content/gpu/gpu_child_thread.cc +++ b/chromium/content/gpu/gpu_child_thread.cc @@ -9,12 +9,14 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/command_line.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/sequenced_task_runner.h" #include "base/threading/thread_checker.h" #include "build/build_config.h" +#include "components/viz/common/switches.h" #include "content/child/child_process.h" #include "content/gpu/gpu_service_factory.h" #include "content/public/common/connection_filter.h" @@ -44,11 +46,6 @@ namespace content { namespace { -bool IsVizEnabled() { - // TODO(crbug.com/770833): Look at the --enable-viz flag instead. - return false; -} - ChildThreadImpl::Options GetOptions() { ChildThreadImpl::Options::Builder builder; @@ -106,7 +103,7 @@ class QueueingConnectionFilter : public ConnectionFilter { registry_->BindInterface(interface_name, std::move(*interface_pipe)); } else { std::unique_ptr<PendingRequest> request = - base::MakeUnique<PendingRequest>(); + std::make_unique<PendingRequest>(); request->interface_name = interface_name; request->interface_pipe = std::move(*interface_pipe); pending_requests_.push_back(std::move(request)); @@ -134,23 +131,26 @@ class QueueingConnectionFilter : public ConnectionFilter { DISALLOW_COPY_AND_ASSIGN(QueueingConnectionFilter); }; -ui::GpuMain::ExternalDependencies CreateGpuMainDependencies() { - ui::GpuMain::ExternalDependencies deps; - deps.create_display_compositor = IsVizEnabled(); +viz::VizMainImpl::ExternalDependencies CreateVizMainDependencies( + service_manager::Connector* connector) { + viz::VizMainImpl::ExternalDependencies deps; + deps.create_display_compositor = + base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableViz); if (GetContentClient()->gpu()) deps.sync_point_manager = GetContentClient()->gpu()->GetSyncPointManager(); auto* process = ChildProcess::current(); deps.shutdown_event = process->GetShutDownEvent(); deps.io_thread_task_runner = process->io_task_runner(); + deps.connector = connector; return deps; } } // namespace GpuChildThread::GpuChildThread(std::unique_ptr<gpu::GpuInit> gpu_init, - ui::GpuMain::LogMessages log_messages) + viz::VizMainImpl::LogMessages log_messages) : GpuChildThread(GetOptions(), std::move(gpu_init)) { - gpu_main_.SetLogMessagesForHost(std::move(log_messages)); + viz_main_.SetLogMessagesForHost(std::move(log_messages)); } GpuChildThread::GpuChildThread(const InProcessChildThreadParams& params, @@ -165,7 +165,9 @@ GpuChildThread::GpuChildThread(const InProcessChildThreadParams& params, GpuChildThread::GpuChildThread(const ChildThreadImpl::Options& options, std::unique_ptr<gpu::GpuInit> gpu_init) : ChildThreadImpl(options), - gpu_main_(this, CreateGpuMainDependencies(), std::move(gpu_init)), + viz_main_(this, + CreateVizMainDependencies(GetConnector()), + std::move(gpu_init)), weak_factory_(this) { if (in_process_gpu()) { DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -178,7 +180,7 @@ GpuChildThread::GpuChildThread(const ChildThreadImpl::Options& options, GpuChildThread::~GpuChildThread() {} void GpuChildThread::Init(const base::Time& process_start_time) { - gpu_main_.gpu_service()->set_start_time(process_start_time); + viz_main_.gpu_service()->set_start_time(process_start_time); // When running in in-process mode, this has been set in the browser at // ChromeBrowserMainPartsAndroid::PreMainMessageLoopRun(). @@ -189,11 +191,12 @@ void GpuChildThread::Init(const base::Time& process_start_time) { } #endif - AssociatedInterfaceRegistry* associated_registry = &associated_interfaces_; + blink::AssociatedInterfaceRegistry* associated_registry = + &associated_interfaces_; associated_registry->AddInterface(base::Bind( - &GpuChildThread::CreateGpuMainService, base::Unretained(this))); + &GpuChildThread::CreateVizMainService, base::Unretained(this))); - auto registry = base::MakeUnique<service_manager::BinderRegistry>(); + auto registry = std::make_unique<service_manager::BinderRegistry>(); registry->AddInterface(base::Bind(&GpuChildThread::BindServiceFactoryRequest, weak_factory_.GetWeakPtr()), base::ThreadTaskRunnerHandle::Get()); @@ -201,7 +204,7 @@ void GpuChildThread::Init(const base::Time& process_start_time) { GetContentClient()->gpu()->InitializeRegistry(registry.get()); std::unique_ptr<QueueingConnectionFilter> filter = - base::MakeUnique<QueueingConnectionFilter>(GetIOTaskRunner(), + std::make_unique<QueueingConnectionFilter>(GetIOTaskRunner(), std::move(registry)); release_pending_requests_closure_ = filter->GetReleaseCallback(); GetServiceManagerConnection()->AddConnectionFilter(std::move(filter)); @@ -209,13 +212,13 @@ void GpuChildThread::Init(const base::Time& process_start_time) { StartServiceManagerConnection(); } -void GpuChildThread::CreateGpuMainService( - ui::mojom::GpuMainAssociatedRequest request) { - gpu_main_.BindAssociated(std::move(request)); +void GpuChildThread::CreateVizMainService( + viz::mojom::VizMainAssociatedRequest request) { + viz_main_.BindAssociated(std::move(request)); } bool GpuChildThread::in_process_gpu() const { - return gpu_main_.gpu_service()->gpu_info().in_process_gpu; + return viz_main_.gpu_service()->gpu_info().in_process_gpu; } bool GpuChildThread::Send(IPC::Message* msg) { @@ -296,7 +299,7 @@ std::unique_ptr<media::AndroidOverlay> GpuChildThread::CreateAndroidOverlay( FROM_HERE, base::BindOnce(bind_connector_request, std::move(request))); } - return base::MakeUnique<media::MojoAndroidOverlay>( + return std::make_unique<media::MojoAndroidOverlay>( std::move(overlay_provider), std::move(config), routing_token, std::move(context_ref)); } diff --git a/chromium/content/gpu/gpu_child_thread.h b/chromium/content/gpu/gpu_child_thread.h index a1990df78a5..6bb47df8146 100644 --- a/chromium/content/gpu/gpu_child_thread.h +++ b/chromium/content/gpu/gpu_child_thread.h @@ -19,6 +19,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "components/viz/service/gl/gpu_service_impl.h" +#include "components/viz/service/main/viz_main_impl.h" #include "content/child/child_thread_impl.h" #include "content/common/associated_interface_registry_impl.h" #include "gpu/command_buffer/service/gpu_preferences.h" @@ -34,8 +35,7 @@ #include "mojo/public/cpp/bindings/binding_set.h" #include "services/service_manager/public/cpp/service_context_ref.h" #include "services/service_manager/public/interfaces/service_factory.mojom.h" -#include "services/ui/gpu/gpu_main.h" -#include "services/ui/gpu/interfaces/gpu_main.mojom.h" +#include "services/viz/privileged/interfaces/viz_main.mojom.h" #include "ui/gfx/native_widget_types.h" namespace content { @@ -45,10 +45,11 @@ class GpuServiceFactory; // these per process. It does process initialization and shutdown. It forwards // IPC messages to gpu::GpuChannelManager, which is responsible for issuing // rendering commands to the GPU. -class GpuChildThread : public ChildThreadImpl, public ui::GpuMain::Delegate { +class GpuChildThread : public ChildThreadImpl, + public viz::VizMainImpl::Delegate { public: GpuChildThread(std::unique_ptr<gpu::GpuInit> gpu_init, - ui::GpuMain::LogMessages deferred_messages); + viz::VizMainImpl::LogMessages deferred_messages); GpuChildThread(const InProcessChildThreadParams& params, std::unique_ptr<gpu::GpuInit> gpu_init); @@ -61,7 +62,7 @@ class GpuChildThread : public ChildThreadImpl, public ui::GpuMain::Delegate { GpuChildThread(const ChildThreadImpl::Options& options, std::unique_ptr<gpu::GpuInit> gpu_init); - void CreateGpuMainService(ui::mojom::GpuMainAssociatedRequest request); + void CreateVizMainService(viz::mojom::VizMainAssociatedRequest request); bool in_process_gpu() const; @@ -73,7 +74,7 @@ class GpuChildThread : public ChildThreadImpl, public ui::GpuMain::Delegate { const std::string& name, mojo::ScopedInterfaceEndpointHandle handle) override; - // ui::GpuMain::Delegate: + // viz::VizMainImpl::Delegate: void OnInitializationFailed() override; void OnGpuServiceConnection(viz::GpuServiceImpl* gpu_service) override; @@ -88,7 +89,7 @@ class GpuChildThread : public ChildThreadImpl, public ui::GpuMain::Delegate { media::AndroidOverlayConfig); #endif - ui::GpuMain gpu_main_; + viz::VizMainImpl viz_main_; // ServiceFactory for service_manager::Service hosting. std::unique_ptr<GpuServiceFactory> service_factory_; diff --git a/chromium/content/gpu/gpu_main.cc b/chromium/content/gpu/gpu_main.cc index 556cf00e8ac..c170ebdf874 100644 --- a/chromium/content/gpu/gpu_main.cc +++ b/chromium/content/gpu/gpu_main.cc @@ -22,6 +22,7 @@ #include "base/timer/hi_res_timer_manager.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "components/viz/service/main/viz_main_impl.h" #include "content/common/content_constants_internal.h" #include "content/common/content_switches_internal.h" #include "content/gpu/gpu_child_thread.h" @@ -36,11 +37,12 @@ #include "gpu/config/gpu_switches.h" #include "gpu/config/gpu_util.h" #include "gpu/ipc/common/gpu_memory_buffer_support.h" +#include "gpu/ipc/common/gpu_preferences_util.h" #include "gpu/ipc/service/gpu_config.h" #include "gpu/ipc/service/gpu_init.h" #include "gpu/ipc/service/gpu_watchdog_thread.h" #include "media/gpu/features.h" -#include "services/ui/gpu/gpu_main.h" +#include "third_party/angle/src/gpu_info_util/SystemInfo.h" #include "third_party/skia/include/core/SkGraphics.h" #include "ui/events/platform/platform_event_source.h" #include "ui/gfx/switches.h" @@ -76,8 +78,10 @@ #if defined(OS_LINUX) #include "content/common/font_config_ipc_linux.h" -#include "content/common/sandbox_linux/sandbox_linux.h" +#include "content/gpu/gpu_sandbox_hook_linux.h" +#include "content/public/common/common_sandbox_support_linux.h" #include "content/public/common/sandbox_init.h" +#include "services/service_manager/sandbox/linux/sandbox_linux.h" #include "third_party/skia/include/ports/SkFontConfigInterface.h" #endif @@ -99,19 +103,21 @@ namespace content { namespace { #if defined(OS_LINUX) -bool StartSandboxLinux(gpu::GpuWatchdogThread*, const gpu::GPUInfo*); +bool StartSandboxLinux(gpu::GpuWatchdogThread*, + const gpu::GPUInfo*, + const gpu::GpuPreferences&); #elif defined(OS_WIN) bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*); #endif -base::LazyInstance<ui::GpuMain::LogMessages>::DestructorAtExit +base::LazyInstance<viz::VizMainImpl::LogMessages>::DestructorAtExit deferred_messages = LAZY_INSTANCE_INITIALIZER; bool GpuProcessLogMessageHandler(int severity, const char* file, int line, size_t message_start, const std::string& str) { - ui::GpuMain::LogMessage log; + viz::VizMainImpl::LogMessage log; log.severity = severity; log.header = str.substr(0, message_start); log.message = str.substr(message_start); @@ -155,13 +161,14 @@ class ContentSandboxHelper : public gpu::GpuSandboxHelper { } bool EnsureSandboxInitialized(gpu::GpuWatchdogThread* watchdog_thread, - const gpu::GPUInfo* gpu_info) override { + const gpu::GPUInfo* gpu_info, + const gpu::GpuPreferences& gpu_prefs) override { #if defined(OS_LINUX) - return StartSandboxLinux(watchdog_thread, gpu_info); + return StartSandboxLinux(watchdog_thread, gpu_info, gpu_prefs); #elif defined(OS_WIN) return StartSandboxWindows(sandbox_info_); #elif defined(OS_MACOSX) - return service_manager::Sandbox::SandboxIsCurrentlyActive(); + return service_manager::SandboxMac::IsCurrentlyActive(); #else return false; #endif @@ -179,12 +186,21 @@ class ContentSandboxHelper : public gpu::GpuSandboxHelper { // Main function for starting the Gpu process. int GpuMain(const MainFunctionParams& parameters) { TRACE_EVENT0("gpu", "GpuMain"); - base::trace_event::TraceLog::GetInstance()->SetProcessName("GPU Process"); + base::trace_event::TraceLog::GetInstance()->set_process_name("GPU Process"); base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( kTraceEventGpuProcessSortIndex); const base::CommandLine& command_line = parameters.command_line; - if (command_line.HasSwitch(switches::kGpuStartupDialog)) + + gpu::GpuPreferences gpu_preferences; + if (command_line.HasSwitch(switches::kGpuPreferences)) { + std::string value = + command_line.GetSwitchValueASCII(switches::kGpuPreferences); + bool success = gpu::SwitchValueToGpuPreferences(value, &gpu_preferences); + CHECK(success); + } + + if (gpu_preferences.gpu_startup_dialog) WaitForDebugger("Gpu"); base::Time start_time = base::Time::Now(); @@ -239,9 +255,10 @@ int GpuMain(const MainFunctionParams& parameters) { #elif defined(OS_LINUX) #error "Unsupported Linux platform." #elif defined(OS_MACOSX) - // This is necessary for CoreAnimation layers hosted in the GPU process to - // be drawn. See http://crbug.com/312462. - std::unique_ptr<base::MessagePump> pump(new base::MessagePumpCFRunLoop()); + // Cross-process CoreAnimation requires a CFRunLoop to function at all, and + // requires a NSRunLoop to not starve under heavy load. See: + // https://crbug.com/312462#c51 and https://crbug.com/783298 + std::unique_ptr<base::MessagePump> pump(new base::MessagePumpNSRunLoop()); main_message_loop.reset(new base::MessageLoop(std::move(pump))); #else main_message_loop.reset( @@ -274,12 +291,12 @@ int GpuMain(const MainFunctionParams& parameters) { // set up between the browser and GPU process, and the GPU process crashes or // exits early, the browser process will never detect it. For this reason we // defer tearing down the GPU process until receiving the initialization - // message from the browser (through mojom::GpuMain::CreateGpuService()). + // message from the browser (through mojom::VizMain::CreateGpuService()). const bool init_success = gpu_init->InitializeAndStartSandbox( - const_cast<base::CommandLine*>(&command_line)); + const_cast<base::CommandLine*>(&command_line), gpu_preferences); const bool dead_on_arrival = !init_success; - logging::SetLogMessageHandler(NULL); + logging::SetLogMessageHandler(nullptr); GetContentClient()->SetGpuInfo(gpu_init->gpu_info()); base::ThreadPriority io_thread_priority = base::ThreadPriority::NORMAL; @@ -325,24 +342,38 @@ namespace { #if defined(OS_LINUX) bool StartSandboxLinux(gpu::GpuWatchdogThread* watchdog_thread, - const gpu::GPUInfo* gpu_info) { + const gpu::GPUInfo* gpu_info, + const gpu::GpuPreferences& gpu_prefs) { TRACE_EVENT0("gpu,startup", "Initialize sandbox"); - bool res = false; - if (watchdog_thread) { - // LinuxSandbox needs to be able to ensure that the thread + // SandboxLinux needs to be able to ensure that the thread // has really been stopped. - LinuxSandbox::StopThread(watchdog_thread); + service_manager::SandboxLinux::GetInstance()->StopThread(watchdog_thread); } - // LinuxSandbox::InitializeSandbox() must always be called + // SandboxLinux::InitializeSandbox() must always be called // with only one thread. - res = LinuxSandbox::InitializeSandbox(gpu_info); + service_manager::SandboxLinux::Options sandbox_options; + sandbox_options.use_amd_specific_policies = + gpu_info && angle::IsAMD(gpu_info->active_gpu().vendor_id); + sandbox_options.accelerated_video_decode_enabled = + !gpu_prefs.disable_accelerated_video_decode; + +#if defined(OS_CHROMEOS) + sandbox_options.vaapi_accelerated_video_encode_enabled = + !gpu_prefs.disable_vaapi_accelerated_video_encode; +#endif + + bool res = service_manager::SandboxLinux::GetInstance()->InitializeSandbox( + service_manager::SandboxTypeFromCommandLine( + *base::CommandLine::ForCurrentProcess()), + base::BindOnce(GpuProcessPreSandboxHook), sandbox_options); + if (watchdog_thread) { - base::Thread::Options options; - options.timer_slack = base::TIMER_SLACK_MAXIMUM; - watchdog_thread->StartWithOptions(options); + base::Thread::Options thread_options; + thread_options.timer_slack = base::TIMER_SLACK_MAXIMUM; + watchdog_thread->StartWithOptions(thread_options); } return res; diff --git a/chromium/content/gpu/gpu_sandbox_hook_linux.cc b/chromium/content/gpu/gpu_sandbox_hook_linux.cc new file mode 100644 index 00000000000..c0ea3627ea5 --- /dev/null +++ b/chromium/content/gpu/gpu_sandbox_hook_linux.cc @@ -0,0 +1,351 @@ +// 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/gpu/gpu_sandbox_hook_linux.h" + +#include <dlfcn.h> +#include <errno.h> + +#include <memory> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/files/file_enumerator.h" +#include "base/files/scoped_file.h" +#include "base/strings/stringprintf.h" +#include "build/build_config.h" +#include "build/buildflag.h" +#include "content/public/common/content_switches.h" +#include "media/gpu/features.h" +#include "sandbox/linux/bpf_dsl/policy.h" +#include "sandbox/linux/syscall_broker/broker_file_permission.h" +#include "sandbox/linux/syscall_broker/broker_process.h" +#include "services/service_manager/embedder/set_process_title.h" +#include "services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.h" +#include "services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.h" +#include "services/service_manager/sandbox/linux/bpf_gpu_policy_linux.h" +#include "services/service_manager/sandbox/linux/sandbox_linux.h" + +#if BUILDFLAG(USE_VAAPI) +#include <va/va_version.h> +#endif + +using sandbox::bpf_dsl::Policy; +using sandbox::syscall_broker::BrokerFilePermission; +using sandbox::syscall_broker::BrokerProcess; + +namespace content { +namespace { + +inline bool IsChromeOS() { +#if defined(OS_CHROMEOS) + return true; +#else + return false; +#endif +} + +inline bool IsArchitectureX86_64() { +#if defined(__x86_64__) + return true; +#else + return false; +#endif +} + +inline bool IsArchitectureI386() { +#if defined(__i386__) + return true; +#else + return false; +#endif +} + +inline bool IsArchitectureArm() { +#if defined(ARCH_CPU_ARM_FAMILY) + return true; +#else + return false; +#endif +} + +inline bool UseV4L2Codec() { +#if BUILDFLAG(USE_V4L2_CODEC) + return true; +#else + return false; +#endif +} + +inline bool UseLibV4L2() { +#if BUILDFLAG(USE_LIBV4L2) + return true; +#else + return false; +#endif +} + +inline bool IsLibVAVersion2() { +#if BUILDFLAG(USE_VAAPI) && VA_MAJOR_VERSION == 1 + return true; +#else + return false; +#endif +} + +constexpr int dlopen_flag = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE; + +void AddV4L2GpuWhitelist( + std::vector<BrokerFilePermission>* permissions, + const service_manager::SandboxSeccompBPF::Options& options) { + if (options.accelerated_video_decode_enabled) { + // Device nodes for V4L2 video decode accelerator drivers. + static const base::FilePath::CharType kDevicePath[] = + FILE_PATH_LITERAL("/dev/"); + static const base::FilePath::CharType kVideoDecPattern[] = "video-dec[0-9]"; + base::FileEnumerator enumerator(base::FilePath(kDevicePath), false, + base::FileEnumerator::FILES, + base::FilePath(kVideoDecPattern).value()); + for (base::FilePath name = enumerator.Next(); !name.empty(); + name = enumerator.Next()) + permissions->push_back(BrokerFilePermission::ReadWrite(name.value())); + } + + // Device node for V4L2 video encode accelerator drivers. + static const char kDevVideoEncPath[] = "/dev/video-enc"; + permissions->push_back(BrokerFilePermission::ReadWrite(kDevVideoEncPath)); + + // Device node for V4L2 JPEG decode accelerator drivers. + static const char kDevJpegDecPath[] = "/dev/jpeg-dec"; + permissions->push_back(BrokerFilePermission::ReadWrite(kDevJpegDecPath)); +} + +void AddArmMaliGpuWhitelist(std::vector<BrokerFilePermission>* permissions) { + // Device file needed by the ARM GPU userspace. + static const char kMali0Path[] = "/dev/mali0"; + + // Image processor used on ARM platforms. + static const char kDevImageProc0Path[] = "/dev/image-proc0"; + + permissions->push_back(BrokerFilePermission::ReadWrite(kMali0Path)); + permissions->push_back(BrokerFilePermission::ReadWrite(kDevImageProc0Path)); +} + +void AddAmdGpuWhitelist(std::vector<BrokerFilePermission>* permissions) { + static const char* const kReadOnlyList[] = {"/etc/ld.so.cache", + "/usr/lib64/libEGL.so.1", + "/usr/lib64/libGLESv2.so.2"}; + for (const char* item : kReadOnlyList) + permissions->push_back(BrokerFilePermission::ReadOnly(item)); + + static const char* const kReadWriteList[] = { + "/dev/dri", + "/dev/dri/card0", + "/dev/dri/controlD64", + "/dev/dri/renderD128", + "/sys/class/drm/card0/device/config", + "/sys/class/drm/controlD64/device/config", + "/sys/class/drm/renderD128/device/config", + "/usr/share/libdrm/amdgpu.ids"}; + for (const char* item : kReadWriteList) + permissions->push_back(BrokerFilePermission::ReadWrite(item)); + + static const char kCharDevices[] = "/sys/dev/char/"; + permissions->push_back(BrokerFilePermission::ReadOnlyRecursive(kCharDevices)); +} + +void AddArmGpuWhitelist(std::vector<BrokerFilePermission>* permissions) { + // On ARM we're enabling the sandbox before the X connection is made, + // so we need to allow access to |.Xauthority|. + static const char kXAuthorityPath[] = "/home/chronos/.Xauthority"; + static const char kLdSoCache[] = "/etc/ld.so.cache"; + + // Files needed by the ARM GPU userspace. + static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2"; + static const char kLibEglPath[] = "/usr/lib/libEGL.so.1"; + + permissions->push_back(BrokerFilePermission::ReadOnly(kXAuthorityPath)); + permissions->push_back(BrokerFilePermission::ReadOnly(kLdSoCache)); + permissions->push_back(BrokerFilePermission::ReadOnly(kLibGlesPath)); + permissions->push_back(BrokerFilePermission::ReadOnly(kLibEglPath)); + + AddArmMaliGpuWhitelist(permissions); +} + +void AddStandardGpuWhiteList(std::vector<BrokerFilePermission>* permissions) { + static const char kDriCardBasePath[] = "/dev/dri/card"; + static const char kNvidiaCtlPath[] = "/dev/nvidiactl"; + static const char kNvidiaDeviceBasePath[] = "/dev/nvidia"; + static const char kNvidiaParamsPath[] = "/proc/driver/nvidia/params"; + static const char kDevShm[] = "/dev/shm/"; + + // For shared memory. + permissions->push_back( + BrokerFilePermission::ReadWriteCreateTemporaryRecursive(kDevShm)); + + // For DRI cards. + for (int i = 0; i <= 9; ++i) { + permissions->push_back(BrokerFilePermission::ReadWrite( + base::StringPrintf("%s%d", kDriCardBasePath, i))); + } + + // For Nvidia GLX driver. + permissions->push_back(BrokerFilePermission::ReadWrite(kNvidiaCtlPath)); + for (int i = 0; i < 10; ++i) { + permissions->push_back(BrokerFilePermission::ReadWrite( + base::StringPrintf("%s%d", kNvidiaDeviceBasePath, i))); + } + permissions->push_back(BrokerFilePermission::ReadOnly(kNvidiaParamsPath)); +} + +std::vector<BrokerFilePermission> FilePermissionsForGpu( + const service_manager::SandboxSeccompBPF::Options& options) { + std::vector<BrokerFilePermission> permissions; + + // All GPU process policies need this file brokered out. + static const char kDriRcPath[] = "/etc/drirc"; + permissions.push_back(BrokerFilePermission::ReadOnly(kDriRcPath)); + + if (IsChromeOS()) { + if (UseV4L2Codec()) + AddV4L2GpuWhitelist(&permissions, options); + if (IsArchitectureArm()) { + AddArmGpuWhitelist(&permissions); + return permissions; + } + if (options.use_amd_specific_policies) { + AddAmdGpuWhitelist(&permissions); + return permissions; + } + } + AddStandardGpuWhiteList(&permissions); + return permissions; +} + +void LoadArmGpuLibraries() { + // Preload the Mali library. + dlopen("/usr/lib/libmali.so", dlopen_flag); + + // Preload the Tegra V4L2 (video decode acceleration) library. + dlopen("/usr/lib/libtegrav4l2.so", dlopen_flag); +} + +bool LoadAmdGpuLibraries() { + // Preload the amdgpu-dependent libraries. + if (nullptr == dlopen("libglapi.so", dlopen_flag)) { + LOG(ERROR) << "dlopen(libglapi.so) failed with error: " << dlerror(); + return false; + } + + const char* radeonsi_lib = "/usr/lib64/dri/radeonsi_dri.so"; +#if defined(DRI_DRIVER_DIR) + radeonsi_lib = DRI_DRIVER_DIR "/radeonsi_dri.so"; +#endif + if (nullptr == dlopen(radeonsi_lib, dlopen_flag)) { + LOG(ERROR) << "dlopen(radeonsi_dri.so) failed with error: " << dlerror(); + return false; + } + return true; +} + +void LoadV4L2Libraries() { + if (UseLibV4L2()) { + dlopen("/usr/lib/libv4l2.so", dlopen_flag); + + // This is a device-specific encoder plugin. + dlopen("/usr/lib/libv4l/plugins/libv4l-encplugin.so", dlopen_flag); + } +} + +void LoadStandardLibraries( + const service_manager::SandboxSeccompBPF::Options& options) { + if (IsArchitectureX86_64() || IsArchitectureI386()) { + // Accelerated video dlopen()'s some shared objects + // inside the sandbox, so preload them now. + if (options.vaapi_accelerated_video_encode_enabled || + options.accelerated_video_decode_enabled) { + if (IsLibVAVersion2()) { + if (IsArchitectureX86_64()) { + dlopen("/usr/lib64/va/drivers/i965_drv_video.so", dlopen_flag); + dlopen("/usr/lib64/va/drivers/hybrid_drv_video.so", dlopen_flag); + } else if (IsArchitectureI386()) { + dlopen("/usr/lib/va/drivers/i965_drv_video.so", dlopen_flag); + } + dlopen("libva.so.2", dlopen_flag); +#if defined(USE_OZONE) + dlopen("libva-drm.so.2", dlopen_flag); +#endif + } else { + // If we are linked against libva 1, we have two cases to handle: + // - the sysroot includes both libva 1 and 2, in which case the drivers + // are in /usr/lib{64}/va1/ + // - the sysroot only includes libva 1, in which case the drivers are + // are in /usr/lib{64}/va/ + // This is ugly, but temporary until all builds have switched to libva 2. + if (IsArchitectureX86_64()) { + if (!dlopen("/usr/lib64/va1/drivers/i965_drv_video.so", dlopen_flag)) + dlopen("/usr/lib64/va/drivers/i965_drv_video.so", dlopen_flag); + if (!dlopen("/usr/lib64/va1/drivers/hybrid_drv_video.so", dlopen_flag)) + dlopen("/usr/lib64/va/drivers/hybrid_drv_video.so", dlopen_flag); + } else if (IsArchitectureI386()) { + if (!dlopen("/usr/lib/va1/drivers/i965_drv_video.so", dlopen_flag)) + dlopen("/usr/lib/va/drivers/i965_drv_video.so", dlopen_flag); + } + dlopen("libva.so.1", dlopen_flag); +#if defined(USE_OZONE) + dlopen("libva-drm.so.1", dlopen_flag); +#elif defined(USE_X11) + dlopen("libva-x11.so.1", dlopen_flag); +#endif + } + } + } +} + +bool LoadLibrariesForGpu( + const service_manager::SandboxSeccompBPF::Options& options) { + if (IsChromeOS()) { + if (UseV4L2Codec()) + LoadV4L2Libraries(); + if (IsArchitectureArm()) { + LoadArmGpuLibraries(); + return true; + } + if (options.use_amd_specific_policies) + return LoadAmdGpuLibraries(); + } + LoadStandardLibraries(options); + return true; +} + +bool BrokerProcessPreSandboxHook( + service_manager::BPFBasePolicy* policy, + service_manager::SandboxLinux::Options options) { + // Oddly enough, we call back into gpu to invoke this service manager + // method, since it is part of the embedder component, and the service + // mananger's sandbox component is a lower layer that can't depend on it. + service_manager::SetProcessTitleFromCommandLine(nullptr); + return true; +} + +} // namespace + +bool GpuProcessPreSandboxHook(service_manager::BPFBasePolicy* policy, + service_manager::SandboxLinux::Options options) { + auto* instance = service_manager::SandboxLinux::GetInstance(); + instance->StartBrokerProcess(policy, FilePermissionsForGpu(options), + base::BindOnce(BrokerProcessPreSandboxHook), + options); + + if (!LoadLibrariesForGpu(options)) + return false; + + // TODO(tsepez): enable namspace sandbox here once crashes are understood. + + errno = 0; + return true; +} + +} // namespace content diff --git a/chromium/content/gpu/gpu_sandbox_hook_linux.h b/chromium/content/gpu/gpu_sandbox_hook_linux.h new file mode 100644 index 00000000000..581f61f7a5b --- /dev/null +++ b/chromium/content/gpu/gpu_sandbox_hook_linux.h @@ -0,0 +1,17 @@ +// 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. + +#ifndef CONTENT_GPU_GPU_SANDBOX_HOOK_LINUX_H_ +#define CONTENT_GPU_GPU_SANDBOX_HOOK_LINUX_H_ + +#include "services/service_manager/sandbox/linux/sandbox_linux.h" + +namespace content { + +bool GpuProcessPreSandboxHook(service_manager::BPFBasePolicy* policy, + service_manager::SandboxLinux::Options options); + +} // namespace content + +#endif // CONTENT_GPU_GPU_SANDBOX_HOOK_LINUX_H_ diff --git a/chromium/content/gpu/gpu_service_factory.cc b/chromium/content/gpu/gpu_service_factory.cc index c8d60024e39..9daced1ca4d 100644 --- a/chromium/content/gpu/gpu_service_factory.cc +++ b/chromium/content/gpu/gpu_service_factory.cc @@ -6,6 +6,7 @@ #include <memory> +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "services/shape_detection/public/interfaces/constants.mojom.h" #include "services/shape_detection/shape_detection_service.h" @@ -37,7 +38,12 @@ void GpuServiceFactory::RegisterServices(ServiceMap* services) { info.factory = base::Bind(&media::CreateGpuMediaService, gpu_preferences_, task_runner_, media_gpu_channel_manager_, android_overlay_factory_cb_); - info.use_own_thread = true; + // This service will host audio/video decoders, and if these decoding + // operations are blocked, user may hear audio glitch or see video freezing, + // hence "user blocking". + // TODO(crbug.com/786169): Check whether this needs to be single threaded. + info.task_runner = base::CreateSingleThreadTaskRunnerWithTraits( + {base::TaskPriority::USER_BLOCKING}); services->insert(std::make_pair("media", info)); #endif diff --git a/chromium/content/gpu/in_process_gpu_thread.cc b/chromium/content/gpu/in_process_gpu_thread.cc index 185ddee629a..39145978648 100644 --- a/chromium/content/gpu/in_process_gpu_thread.cc +++ b/chromium/content/gpu/in_process_gpu_thread.cc @@ -12,6 +12,7 @@ #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" #include "content/public/gpu/content_gpu_client.h" +#include "gpu/command_buffer/service/gpu_preferences.h" #include "gpu/config/gpu_info_collector.h" #include "gpu/config/gpu_util.h" #include "gpu/ipc/service/gpu_init.h" @@ -27,10 +28,13 @@ namespace content { -InProcessGpuThread::InProcessGpuThread(const InProcessChildThreadParams& params) +InProcessGpuThread::InProcessGpuThread( + const InProcessChildThreadParams& params, + const gpu::GpuPreferences& gpu_preferences) : base::Thread("Chrome_InProcGpuThread"), params_(params), - gpu_process_(NULL) {} + gpu_process_(nullptr), + gpu_preferences_(gpu_preferences) {} InProcessGpuThread::~InProcessGpuThread() { Stop(); @@ -54,6 +58,7 @@ void InProcessGpuThread::Init() { auto gpu_init = std::make_unique<gpu::GpuInit>(); auto* client = GetContentClient()->gpu(); gpu_init->InitializeInProcess(base::CommandLine::ForCurrentProcess(), + gpu_preferences_, client ? client->GetGPUInfo() : nullptr, client ? client->GetGpuFeatureInfo() : nullptr); @@ -77,8 +82,9 @@ void InProcessGpuThread::CleanUp() { } base::Thread* CreateInProcessGpuThread( - const InProcessChildThreadParams& params) { - return new InProcessGpuThread(params); + const InProcessChildThreadParams& params, + const gpu::GpuPreferences& gpu_preferences) { + return new InProcessGpuThread(params, gpu_preferences); } } // namespace content diff --git a/chromium/content/gpu/in_process_gpu_thread.h b/chromium/content/gpu/in_process_gpu_thread.h index 66af2058bdc..c8e96e88d47 100644 --- a/chromium/content/gpu/in_process_gpu_thread.h +++ b/chromium/content/gpu/in_process_gpu_thread.h @@ -11,6 +11,7 @@ #include "base/threading/thread.h" #include "content/common/content_export.h" #include "content/common/in_process_child_thread_params.h" +#include "gpu/command_buffer/service/gpu_preferences.h" namespace content { @@ -20,7 +21,8 @@ class GpuProcess; // with --in-process-gpu or --single-process. class InProcessGpuThread : public base::Thread { public: - explicit InProcessGpuThread(const InProcessChildThreadParams& params); + explicit InProcessGpuThread(const InProcessChildThreadParams& params, + const gpu::GpuPreferences& gpu_preferences); ~InProcessGpuThread() override; protected: @@ -33,11 +35,14 @@ class InProcessGpuThread : public base::Thread { // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. GpuProcess* gpu_process_; + gpu::GpuPreferences gpu_preferences_; + DISALLOW_COPY_AND_ASSIGN(InProcessGpuThread); }; CONTENT_EXPORT base::Thread* CreateInProcessGpuThread( - const InProcessChildThreadParams& params); + const InProcessChildThreadParams& params, + const gpu::GpuPreferences& gpu_preferences); } // namespace content |