Index: content/gpu/gpu_child_thread.cc |
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc |
index f2ad57e72cf35fc1b8d1729bf3e3297ad92fae2f..16bbd9867e2b8ad63b27cf1fb8500fc4fd02c175 100644 |
--- a/content/gpu/gpu_child_thread.cc |
+++ b/content/gpu/gpu_child_thread.cc |
@@ -9,10 +9,13 @@ |
#include "base/bind.h" |
#include "base/callback_helpers.h" |
+#include "base/memory/weak_ptr.h" |
+#include "base/threading/thread_checker.h" |
#include "build/build_config.h" |
#include "content/child/child_process.h" |
#include "content/common/field_trial_recorder.mojom.h" |
#include "content/gpu/gpu_service_factory.h" |
+#include "content/public/common/connection_filter.h" |
#include "content/public/common/content_client.h" |
#include "content/public/common/content_switches.h" |
#include "content/public/common/service_manager_connection.h" |
@@ -22,8 +25,8 @@ |
#include "gpu/ipc/service/gpu_watchdog_thread.h" |
#include "ipc/ipc_sync_message_filter.h" |
#include "media/gpu/ipc/service/media_gpu_channel_manager.h" |
+#include "services/service_manager/public/cpp/binder_registry.h" |
#include "services/service_manager/public/cpp/connector.h" |
-#include "services/service_manager/public/cpp/interface_registry.h" |
#include "services/ui/gpu/interfaces/gpu_service.mojom.h" |
#if defined(USE_OZONE) |
@@ -47,6 +50,7 @@ ChildThreadImpl::Options GetOptions() { |
builder.AddStartupFilter(message_filter); |
#endif |
+ builder.AutoStartServiceManagerConnection(false); |
builder.ConnectToBrowser(true); |
return builder.Build(); |
@@ -54,6 +58,81 @@ ChildThreadImpl::Options GetOptions() { |
} // namespace |
+// This ConnectionFilter queues all incoming bind interface requests until |
+// Release() is called. |
+class GpuChildThread::QueueingConnectionFilter : public ConnectionFilter { |
+ public: |
+ QueueingConnectionFilter( |
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner, |
+ std::unique_ptr<service_manager::BinderRegistry> registry) |
+ : io_task_runner_(io_task_runner), |
+ registry_(std::move(registry)), |
+ weak_factory_(this) { |
+ // This will be reattached by any of the IO thread functions on first call. |
+ io_thread_checker_.DetachFromThread(); |
+ } |
+ ~QueueingConnectionFilter() override { |
+ DCHECK(io_thread_checker_.CalledOnValidThread()); |
+ } |
+ |
+ base::Closure GetReleaseCallback() { |
+ return base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask), |
+ io_task_runner_, FROM_HERE, |
+ base::Bind(&QueueingConnectionFilter::Release, |
+ weak_factory_.GetWeakPtr())); |
+ } |
+ |
+ private: |
+ struct PendingRequest { |
+ service_manager::Identity source_identity; |
+ std::string interface_name; |
+ mojo::ScopedMessagePipeHandle interface_pipe; |
+ }; |
+ |
+ // ConnectionFilter: |
+ void OnBindInterface(const service_manager::ServiceInfo& source_info, |
+ const std::string& interface_name, |
+ mojo::ScopedMessagePipeHandle* interface_pipe, |
+ service_manager::Connector* connector) override { |
+ DCHECK(io_thread_checker_.CalledOnValidThread()); |
+ if (registry_->CanBindInterface(interface_name)) { |
+ base::AutoLock lock(lock_); |
+ if (released_) { |
+ registry_->BindInterface(source_info.identity, interface_name, |
+ std::move(*interface_pipe)); |
+ } else { |
+ std::unique_ptr<PendingRequest> request = |
+ base::MakeUnique<PendingRequest>(); |
+ request->source_identity = source_info.identity; |
+ request->interface_name = interface_name; |
+ request->interface_pipe = std::move(*interface_pipe); |
+ pending_requests_.push_back(std::move(request)); |
+ } |
+ } |
+ } |
+ |
+ void Release() { |
+ DCHECK(io_thread_checker_.CalledOnValidThread()); |
+ for (auto& request : pending_requests_) { |
+ registry_->BindInterface(request->source_identity, |
+ request->interface_name, |
+ std::move(request->interface_pipe)); |
+ } |
+ } |
+ |
+ base::ThreadChecker io_thread_checker_; |
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner_; |
+ // Guards |released_|. |
+ base::Lock lock_; |
+ bool released_ = false; |
+ std::vector<std::unique_ptr<PendingRequest>> pending_requests_; |
+ std::unique_ptr<service_manager::BinderRegistry> registry_; |
+ |
+ base::WeakPtrFactory<QueueingConnectionFilter> weak_factory_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(QueueingConnectionFilter); |
+}; |
+ |
GpuChildThread::GpuChildThread( |
std::unique_ptr<gpu::GpuWatchdogThread> watchdog_thread, |
bool dead_on_arrival, |
@@ -74,6 +153,7 @@ GpuChildThread::GpuChildThread(const InProcessChildThreadParams& params, |
const gpu::GpuFeatureInfo& gpu_feature_info) |
: GpuChildThread(ChildThreadImpl::Options::Builder() |
.InBrowserProcess(params) |
+ .AutoStartServiceManagerConnection(false) |
.ConnectToBrowser(true) |
.Build(), |
nullptr /* watchdog_thread */, |
@@ -119,15 +199,24 @@ void GpuChildThread::Init(const base::Time& process_start_time) { |
media::SetMediaDrmBridgeClient( |
GetContentClient()->GetMediaDrmBridgeClient()); |
#endif |
- // We don't want to process any incoming interface requests until |
- // OnInitialize() is invoked. |
- GetInterfaceRegistry()->PauseBinding(); |
+ AssociatedInterfaceRegistry* associated_registry = &associated_interfaces_; |
+ associated_registry->AddInterface(base::Bind( |
+ &GpuChildThread::CreateGpuMainService, base::Unretained(this))); |
+ auto registry = base::MakeUnique<service_manager::BinderRegistry>(); |
+ registry->AddInterface(base::Bind(&GpuChildThread::BindServiceFactoryRequest, |
+ base::Unretained(this)), |
+ base::ThreadTaskRunnerHandle::Get()); |
if (GetContentClient()->gpu()) // NULL in tests. |
- GetContentClient()->gpu()->Initialize(this); |
- AssociatedInterfaceRegistry* registry = &associated_interfaces_; |
- registry->AddInterface(base::Bind( |
- &GpuChildThread::CreateGpuMainService, base::Unretained(this))); |
+ GetContentClient()->gpu()->Initialize(this, registry.get()); |
+ |
+ std::unique_ptr<QueueingConnectionFilter> filter = |
+ base::MakeUnique<QueueingConnectionFilter>(GetIOTaskRunner(), |
+ std::move(registry)); |
+ release_closure_ = filter->GetReleaseCallback(); |
Ken Rockot(use gerrit already)
2017/04/20 17:41:44
nit: Maybe a better name than release_closure_ sin
|
+ GetServiceManagerConnection()->AddConnectionFilter(std::move(filter)); |
+ |
+ StartServiceManagerConnection(); |
} |
void GpuChildThread::OnFieldTrialGroupFinalized(const std::string& trial_name, |
@@ -196,16 +285,10 @@ void GpuChildThread::CreateGpuService( |
service_factory_.reset(new GpuServiceFactory( |
gpu_service_->media_gpu_channel_manager()->AsWeakPtr())); |
- GetInterfaceRegistry()->AddInterface(base::Bind( |
- &GpuChildThread::BindServiceFactoryRequest, base::Unretained(this))); |
- |
- if (GetContentClient()->gpu()) { // NULL in tests. |
- GetContentClient()->gpu()->ExposeInterfacesToBrowser(GetInterfaceRegistry(), |
- gpu_preferences); |
- GetContentClient()->gpu()->ConsumeInterfacesFromBrowser(GetConnector()); |
- } |
+ if (GetContentClient()->gpu()) // NULL in tests. |
+ GetContentClient()->gpu()->GpuServiceInitialized(gpu_preferences); |
- GetInterfaceRegistry()->ResumeBinding(); |
+ release_closure_.Run(); |
} |
void GpuChildThread::CreateFrameSinkManager( |