Commit 1030629e authored by Ken Rockot's avatar Ken Rockot Committed by Commit Bot

Migrate video_capture away from ServiceContext

This changes the video_capture service to use ServiceBinding for its
Service interface binding, eliminating reliance on ServiceContext as
well as EmebddedServiceInfo etc for content integration.

Bug: 891780
Change-Id: Ic1b89aa5487e230b4fafef2fdddf4b0e8e307b3c
Reviewed-on: https://chromium-review.googlesource.com/c/1311797Reviewed-by: default avatarEmircan Uysaler <emircan@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Ken Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#604934}
parent 9f243b44
...@@ -84,6 +84,7 @@ ExtensionService* TestExtensionSystem::CreateExtensionService( ...@@ -84,6 +84,7 @@ ExtensionService* TestExtensionSystem::CreateExtensionService(
if (!connector_factory_) { if (!connector_factory_) {
connector_factory_ = connector_factory_ =
std::make_unique<service_manager::TestConnectorFactory>(); std::make_unique<service_manager::TestConnectorFactory>();
connector_factory_->set_ignore_quit_requests(true);
data_decoder_ = std::make_unique<data_decoder::DataDecoderService>( data_decoder_ = std::make_unique<data_decoder::DataDecoderService>(
connector_factory_->RegisterInstance( connector_factory_->RegisterInstance(
data_decoder::mojom::kServiceName)); data_decoder::mojom::kServiceName));
......
...@@ -105,7 +105,9 @@ class ZipFileInstallerTest : public testing::Test { ...@@ -105,7 +105,9 @@ class ZipFileInstallerTest : public testing::Test {
unzip_service_context_(unzip::UnzipService::CreateService(), unzip_service_context_(unzip::UnzipService::CreateService(),
test_connector_factory_.RegisterInstance( test_connector_factory_.RegisterInstance(
unzip::mojom::kServiceName)), unzip::mojom::kServiceName)),
connector_(test_connector_factory_.CreateConnector()) {} connector_(test_connector_factory_.CreateConnector()) {
test_connector_factory_.set_ignore_quit_requests(true);
}
void SetUp() override { void SetUp() override {
extensions::LoadErrorReporter::Init(/*enable_noisy_errors=*/false); extensions::LoadErrorReporter::Init(/*enable_noisy_errors=*/false);
......
...@@ -371,6 +371,42 @@ bool AudioServiceOutOfProcess() { ...@@ -371,6 +371,42 @@ bool AudioServiceOutOfProcess() {
!GetContentClient()->browser()->OverridesAudioManager(); !GetContentClient()->browser()->OverridesAudioManager();
} }
using InProcessServiceFactory =
base::RepeatingCallback<std::unique_ptr<service_manager::Service>(
service_manager::mojom::ServiceRequest request)>;
void LaunchInProcessServiceOnSequence(
const InProcessServiceFactory& factory,
service_manager::mojom::ServiceRequest request) {
auto* raw_service_impl = factory.Run(std::move(request)).release();
raw_service_impl->set_termination_closure(base::BindOnce(
[](service_manager::Service* impl) { delete impl; }, raw_service_impl));
}
void LaunchInProcessService(
scoped_refptr<base::SequencedTaskRunner> task_runner,
const InProcessServiceFactory& factory,
service_manager::mojom::ServiceRequest request) {
task_runner->PostTask(
FROM_HERE, base::BindOnce(&LaunchInProcessServiceOnSequence, factory,
std::move(request)));
}
void RegisterInProcessService(
ServiceManagerConnection* connection,
const std::string& service_name,
scoped_refptr<base::SequencedTaskRunner> task_runner,
const InProcessServiceFactory& factory) {
connection->AddServiceRequestHandler(
service_name,
base::BindRepeating(&LaunchInProcessService, task_runner, factory));
}
std::unique_ptr<service_manager::Service> CreateVideoCaptureService(
service_manager::mojom::ServiceRequest request) {
return std::make_unique<video_capture::ServiceImpl>(std::move(request));
}
} // namespace } // namespace
// State which lives on the IO thread and drives the ServiceManager. // State which lives on the IO thread and drives the ServiceManager.
...@@ -614,10 +650,8 @@ ServiceManagerContext::ServiceManagerContext( ...@@ -614,10 +650,8 @@ ServiceManagerContext::ServiceManagerContext(
} }
if (features::IsVideoCaptureServiceEnabledForBrowserProcess()) { if (features::IsVideoCaptureServiceEnabledForBrowserProcess()) {
service_manager::EmbeddedServiceInfo video_capture_info; RegisterInProcessService(
video_capture_info.factory = packaged_services_connection_.get(), video_capture::mojom::kServiceName,
base::BindRepeating(&video_capture::ServiceImpl::Create);
video_capture_info.task_runner =
#if defined(OS_WIN) #if defined(OS_WIN)
base::CreateCOMSTATaskRunnerWithTraits( base::CreateCOMSTATaskRunnerWithTraits(
#else #else
...@@ -625,9 +659,8 @@ ServiceManagerContext::ServiceManagerContext( ...@@ -625,9 +659,8 @@ ServiceManagerContext::ServiceManagerContext(
#endif #endif
base::TaskTraits({base::MayBlock(), base::WithBaseSyncPrimitives(), base::TaskTraits({base::MayBlock(), base::WithBaseSyncPrimitives(),
base::TaskPriority::BEST_EFFORT}), base::TaskPriority::BEST_EFFORT}),
base::SingleThreadTaskRunnerThreadMode::DEDICATED); base::SingleThreadTaskRunnerThreadMode::DEDICATED),
packaged_services_connection_->AddEmbeddedService( base::BindRepeating(&CreateVideoCaptureService));
video_capture::mojom::kServiceName, video_capture_info);
} }
{ {
......
...@@ -133,12 +133,6 @@ void UtilityServiceFactory::CreateService( ...@@ -133,12 +133,6 @@ void UtilityServiceFactory::CreateService(
void UtilityServiceFactory::RegisterServices(ServiceMap* services) { void UtilityServiceFactory::RegisterServices(ServiceMap* services) {
GetContentClient()->utility()->RegisterServices(services); GetContentClient()->utility()->RegisterServices(services);
service_manager::EmbeddedServiceInfo video_capture_info;
video_capture_info.factory =
base::BindRepeating(&video_capture::ServiceImpl::Create);
services->insert(
std::make_pair(video_capture::mojom::kServiceName, video_capture_info));
GetContentClient()->utility()->RegisterAudioBinders(audio_registry_.get()); GetContentClient()->utility()->RegisterAudioBinders(audio_registry_.get());
service_manager::EmbeddedServiceInfo audio_info; service_manager::EmbeddedServiceInfo audio_info;
audio_info.factory = base::BindRepeating( audio_info.factory = base::BindRepeating(
...@@ -186,6 +180,9 @@ bool UtilityServiceFactory::HandleServiceRequest( ...@@ -186,6 +180,9 @@ bool UtilityServiceFactory::HandleServiceRequest(
content::UtilityThread::Get()->EnsureBlinkInitialized(); content::UtilityThread::Get()->EnsureBlinkInitialized();
running_service_ = running_service_ =
std::make_unique<data_decoder::DataDecoderService>(std::move(request)); std::make_unique<data_decoder::DataDecoderService>(std::move(request));
} else if (name == video_capture::mojom::kServiceName) {
running_service_ =
std::make_unique<video_capture::ServiceImpl>(std::move(request));
} }
if (running_service_) { if (running_service_) {
......
...@@ -141,7 +141,9 @@ class MockSandboxedUnpackerClient : public SandboxedUnpackerClient { ...@@ -141,7 +141,9 @@ class MockSandboxedUnpackerClient : public SandboxedUnpackerClient {
class SandboxedUnpackerTest : public ExtensionsTest { class SandboxedUnpackerTest : public ExtensionsTest {
public: public:
SandboxedUnpackerTest() SandboxedUnpackerTest()
: SandboxedUnpackerTest(content::TestBrowserThreadBundle::IO_MAINLOOP) {} : SandboxedUnpackerTest(content::TestBrowserThreadBundle::IO_MAINLOOP) {
test_connector_factory_.set_ignore_quit_requests(true);
}
SandboxedUnpackerTest(content::TestBrowserThreadBundle::Options options) SandboxedUnpackerTest(content::TestBrowserThreadBundle::Options options)
: ExtensionsTest(options) {} : ExtensionsTest(options) {}
......
...@@ -22,11 +22,9 @@ ServiceKeepalive::ServiceKeepalive(ServiceBinding* binding, ...@@ -22,11 +22,9 @@ ServiceKeepalive::ServiceKeepalive(ServiceBinding* binding,
} }
ServiceKeepalive::ServiceKeepalive(ServiceContext* context, ServiceKeepalive::ServiceKeepalive(ServiceContext* context,
base::Optional<base::TimeDelta> idle_timeout, base::Optional<base::TimeDelta> idle_timeout)
TimeoutObserver* timeout_observer)
: context_(context), : context_(context),
idle_timeout_(idle_timeout), idle_timeout_(idle_timeout),
timeout_observer_(timeout_observer),
ref_factory_(base::BindRepeating(&ServiceKeepalive::OnRefCountZero, ref_factory_(base::BindRepeating(&ServiceKeepalive::OnRefCountZero,
base::Unretained(this))) { base::Unretained(this))) {
ref_factory_.SetRefAddedCallback(base::BindRepeating( ref_factory_.SetRefAddedCallback(base::BindRepeating(
...@@ -43,10 +41,20 @@ bool ServiceKeepalive::HasNoRefs() { ...@@ -43,10 +41,20 @@ bool ServiceKeepalive::HasNoRefs() {
return ref_factory_.HasNoRefs(); return ref_factory_.HasNoRefs();
} }
void ServiceKeepalive::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void ServiceKeepalive::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void ServiceKeepalive::OnRefAdded() { void ServiceKeepalive::OnRefAdded() {
if (idle_timer_ && timeout_observer_) if (idle_timer_) {
timeout_observer_->OnTimeoutCancelled();
idle_timer_.reset(); idle_timer_.reset();
for (auto& observer : observers_)
observer.OnIdleTimeoutCancelled();
}
} }
void ServiceKeepalive::OnRefCountZero() { void ServiceKeepalive::OnRefCountZero() {
...@@ -59,8 +67,9 @@ void ServiceKeepalive::OnRefCountZero() { ...@@ -59,8 +67,9 @@ void ServiceKeepalive::OnRefCountZero() {
} }
void ServiceKeepalive::OnTimerExpired() { void ServiceKeepalive::OnTimerExpired() {
if (timeout_observer_) for (auto& observer : observers_)
timeout_observer_->OnTimeoutExpired(); observer.OnIdleTimeout();
if (context_) if (context_)
context_->CreateQuitClosure().Run(); context_->CreateQuitClosure().Run();
else else
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "services/service_manager/public/cpp/service_context_ref.h" #include "services/service_manager/public/cpp/service_context_ref.h"
...@@ -33,11 +35,18 @@ class ServiceContext; ...@@ -33,11 +35,18 @@ class ServiceContext;
// service references to different endpoints in your service. // service references to different endpoints in your service.
class SERVICE_MANAGER_PUBLIC_CPP_EXPORT ServiceKeepalive { class SERVICE_MANAGER_PUBLIC_CPP_EXPORT ServiceKeepalive {
public: public:
class TimeoutObserver { class Observer : public base::CheckedObserver {
public: public:
virtual ~TimeoutObserver() {} ~Observer() override {}
virtual void OnTimeoutExpired() = 0;
virtual void OnTimeoutCancelled() = 0; // Invoked whenever the ServiceKeepalive detects that the service has been
// idle for at least the idle time delta specified (if any) upon
// construction of the ServiceKeepalive.
virtual void OnIdleTimeout() = 0;
// Invoked whenever the ServiceKeepalive detects new activity again after
// having been idle for any amount of time.
virtual void OnIdleTimeoutCancelled() = 0;
}; };
ServiceKeepalive(ServiceBinding* binding, ServiceKeepalive(ServiceBinding* binding,
...@@ -52,13 +61,15 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT ServiceKeepalive { ...@@ -52,13 +61,15 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT ServiceKeepalive {
// DEPRECATED: Please consider switching from ServiceContext to ServiceBinding // DEPRECATED: Please consider switching from ServiceContext to ServiceBinding
// and using the constructor above. // and using the constructor above.
ServiceKeepalive(ServiceContext* context, ServiceKeepalive(ServiceContext* context,
base::Optional<base::TimeDelta> idle_timeout, base::Optional<base::TimeDelta> idle_timeout);
TimeoutObserver* timeout_observer = nullptr);
~ServiceKeepalive(); ~ServiceKeepalive();
std::unique_ptr<ServiceContextRef> CreateRef(); std::unique_ptr<ServiceContextRef> CreateRef();
bool HasNoRefs(); bool HasNoRefs();
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
private: private:
void OnRefAdded(); void OnRefAdded();
void OnRefCountZero(); void OnRefCountZero();
...@@ -68,7 +79,7 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT ServiceKeepalive { ...@@ -68,7 +79,7 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT ServiceKeepalive {
ServiceContext* const context_ = nullptr; ServiceContext* const context_ = nullptr;
const base::Optional<base::TimeDelta> idle_timeout_; const base::Optional<base::TimeDelta> idle_timeout_;
base::Optional<base::OneShotTimer> idle_timer_; base::Optional<base::OneShotTimer> idle_timer_;
TimeoutObserver* const timeout_observer_ = nullptr; base::ObserverList<Observer> observers_;
ServiceContextRefFactory ref_factory_; ServiceContextRefFactory ref_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceKeepalive); DISALLOW_COPY_AND_ASSIGN(ServiceKeepalive);
......
...@@ -189,23 +189,41 @@ class MultipleServiceConnector : public TestConnectorImplBase { ...@@ -189,23 +189,41 @@ class MultipleServiceConnector : public TestConnectorImplBase {
class ProxiedServiceConnector : public mojom::Connector { class ProxiedServiceConnector : public mojom::Connector {
public: public:
ProxiedServiceConnector(TestConnectorFactory::NameToServiceProxyMap* proxies, ProxiedServiceConnector(
TestConnectorFactory::NameToServiceProxyMap* proxies,
TestConnectorFactory::NameToServiceHandlerMap* handlers,
const std::string& test_user_id) const std::string& test_user_id)
: proxies_(proxies), test_user_id_(test_user_id) {} : proxies_(proxies), handlers_(handlers), test_user_id_(test_user_id) {}
~ProxiedServiceConnector() override = default; ~ProxiedServiceConnector() override = default;
private: private:
mojom::Service* GetServiceProxy(const std::string& service_name) {
auto proxy_it = proxies_->find(service_name);
if (proxy_it == proxies_->end()) {
auto handler_it = handlers_->find(service_name);
if (handler_it == handlers_->end())
return nullptr;
mojom::ServicePtr proxy;
handler_it->second.Run(mojo::MakeRequest(&proxy));
auto result = proxies_->emplace(service_name, std::move(proxy));
DCHECK(result.second);
proxy_it = result.first;
}
return proxy_it->second.get();
}
// mojom::Connector: // mojom::Connector:
void BindInterface(const Identity& target, void BindInterface(const Identity& target,
const std::string& interface_name, const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe, mojo::ScopedMessagePipeHandle interface_pipe,
BindInterfaceCallback callback) override { BindInterfaceCallback callback) override {
auto it = proxies_->find(target.name()); auto* proxy = GetServiceProxy(target.name());
CHECK(it != proxies_->end()) CHECK(proxy)
<< "TestConnectorFactory received a BindInterface request for an " << "TestConnectorFactory received a BindInterface request for an "
<< "unregistered service '" << target.name() << "'"; << "unregistered service '" << target.name() << "'";
mojom::ServicePtr& proxy = it->second;
proxy->OnBindInterface( proxy->OnBindInterface(
BindSourceInfo(Identity("TestConnectorFactory", test_user_id_), BindSourceInfo(Identity("TestConnectorFactory", test_user_id_),
CapabilitySet()), CapabilitySet()),
...@@ -243,23 +261,19 @@ class ProxiedServiceConnector : public mojom::Connector { ...@@ -243,23 +261,19 @@ class ProxiedServiceConnector : public mojom::Connector {
} }
TestConnectorFactory::NameToServiceProxyMap* const proxies_; TestConnectorFactory::NameToServiceProxyMap* const proxies_;
TestConnectorFactory::NameToServiceHandlerMap* const handlers_;
const std::string test_user_id_; const std::string test_user_id_;
mojo::BindingSet<mojom::Connector> bindings_; mojo::BindingSet<mojom::Connector> bindings_;
DISALLOW_COPY_AND_ASSIGN(ProxiedServiceConnector); DISALLOW_COPY_AND_ASSIGN(ProxiedServiceConnector);
}; };
void OnStartResponse(mojom::Connector* connector,
mojom::ConnectorRequest connector_request,
mojom::ServiceControlAssociatedRequest control_request) {
connector->Clone(std::move(connector_request));
}
} // namespace } // namespace
TestConnectorFactory::TestConnectorFactory() { TestConnectorFactory::TestConnectorFactory() {
std::string guid = base::GenerateGUID(); std::string guid = base::GenerateGUID();
impl_ = std::make_unique<ProxiedServiceConnector>(&service_proxies_, guid); impl_ = std::make_unique<ProxiedServiceConnector>(&service_proxies_,
&service_handlers_, guid);
test_user_id_ = guid; test_user_id_ = guid;
} }
...@@ -306,9 +320,34 @@ mojom::ServiceRequest TestConnectorFactory::RegisterInstance( ...@@ -306,9 +320,34 @@ mojom::ServiceRequest TestConnectorFactory::RegisterInstance(
mojom::ServicePtr proxy; mojom::ServicePtr proxy;
mojom::ServiceRequest request = mojo::MakeRequest(&proxy); mojom::ServiceRequest request = mojo::MakeRequest(&proxy);
proxy->OnStart(Identity(service_name, test_user_id_), proxy->OnStart(Identity(service_name, test_user_id_),
base::BindOnce(&OnStartResponse, impl_.get())); base::BindOnce(&TestConnectorFactory::OnStartResponseHandler,
base::Unretained(this), service_name));
service_proxies_[service_name] = std::move(proxy); service_proxies_[service_name] = std::move(proxy);
return request; return request;
} }
void TestConnectorFactory::RegisterServiceHandler(
const std::string& service_name,
const ServiceHandler& handler) {
service_handlers_[service_name] = handler;
}
void TestConnectorFactory::OnStartResponseHandler(
const std::string& service_name,
mojom::ConnectorRequest connector_request,
mojom::ServiceControlAssociatedRequest control_request) {
impl_->Clone(std::move(connector_request));
service_control_bindings_.AddBinding(this, std::move(control_request),
service_name);
}
void TestConnectorFactory::RequestQuit() {
if (ignore_quit_requests_)
return;
service_proxies_.erase(service_control_bindings_.dispatch_context());
service_control_bindings_.RemoveBinding(
service_control_bindings_.dispatch_binding());
}
} // namespace service_manager } // namespace service_manager
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/mojom/connector.mojom.h" #include "services/service_manager/public/mojom/connector.mojom.h"
#include "services/service_manager/public/mojom/service_control.mojom.h"
namespace service_manager { namespace service_manager {
...@@ -50,17 +52,23 @@ class Service; ...@@ -50,17 +52,23 @@ class Service;
// std::unique_ptr<service_manager::Connector> connector = // std::unique_ptr<service_manager::Connector> connector =
// connector_factory->CreateConnector(); // connector_factory->CreateConnector();
// ... // ...
class TestConnectorFactory { class TestConnectorFactory : public mojom::ServiceControl {
public: public:
// Creates a simple TestConnectorFactory which can be used register unowned // Creates a simple TestConnectorFactory which can be used register unowned
// Service instances and vend Connectors which can connect to them. // Service instances and vend Connectors which can connect to them.
TestConnectorFactory(); TestConnectorFactory();
~TestConnectorFactory(); ~TestConnectorFactory() override;
// A mapping from service names to Service proxies for unowned Service // A mapping from service names to Service proxies for unowned Service
// instances. // instances.
using NameToServiceProxyMap = std::map<std::string, mojom::ServicePtr>; using NameToServiceProxyMap = std::map<std::string, mojom::ServicePtr>;
// Used to hold a mapping from service names to callbacks which can
// instantiate an instance of those services.
using ServiceHandler =
base::RepeatingCallback<void(service_manager::mojom::ServiceRequest)>;
using NameToServiceHandlerMap = std::map<std::string, ServiceHandler>;
// Used to hold a mapping from service names to owned Service instances. // Used to hold a mapping from service names to owned Service instances.
using NameToServiceMap = std::map<std::string, std::unique_ptr<Service>>; using NameToServiceMap = std::map<std::string, std::unique_ptr<Service>>;
...@@ -90,12 +98,38 @@ class TestConnectorFactory { ...@@ -90,12 +98,38 @@ class TestConnectorFactory {
// simulated events from this object. // simulated events from this object.
mojom::ServiceRequest RegisterInstance(const std::string& service_name); mojom::ServiceRequest RegisterInstance(const std::string& service_name);
// Registers a callback to start an instance of a specific named service
// whenever it's needed by this TestConnectorFactory. This may be used instead
// of a one-time registration via |RegisterInstance()| in cases where a
// service-under-test may be stopped and restarted multiple times during a
// single test.
void RegisterServiceHandler(const std::string& service_name,
const ServiceHandler& handler);
const std::string& test_user_id() const { return test_user_id_; } const std::string& test_user_id() const { return test_user_id_; }
// Normally when a service instance registered via either |RegisterInstance()|
// or |RegisterServiceHandler()| requests termination from the Service
// Manager, TestConnectorFactory immediately severs the service instance's
// connection, typically triggering the service's shutdown path.
//
// If this is set to |true| (defaults to |false|), quit requests are ignored
// and each service instance will remain connected to the TestConnectorFactory
// until either it or the TestConnoctorFactory is destroyed.
void set_ignore_quit_requests(bool ignore) { ignore_quit_requests_ = ignore; }
private: private:
explicit TestConnectorFactory(std::unique_ptr<mojom::Connector> impl, explicit TestConnectorFactory(std::unique_ptr<mojom::Connector> impl,
std::string test_user_id); std::string test_user_id);
void OnStartResponseHandler(
const std::string& service_name,
mojom::ConnectorRequest connector_request,
mojom::ServiceControlAssociatedRequest control_request);
// mojom::ServiceControl:
void RequestQuit() override;
NameToServiceMap names_to_services_; NameToServiceMap names_to_services_;
std::unique_ptr<mojom::Connector> impl_; std::unique_ptr<mojom::Connector> impl_;
...@@ -106,6 +140,17 @@ class TestConnectorFactory { ...@@ -106,6 +140,17 @@ class TestConnectorFactory {
// proxies. // proxies.
NameToServiceProxyMap service_proxies_; NameToServiceProxyMap service_proxies_;
// Maps service names to handlers which can construct service instances.
NameToServiceHandlerMap service_handlers_;
// ServiceControl bindings which receive and process RequestQuit requests from
// connected service instances. The associated service name is used as
// context.
mojo::AssociatedBindingSet<mojom::ServiceControl, std::string>
service_control_bindings_;
bool ignore_quit_requests_ = false;
DISALLOW_COPY_AND_ASSIGN(TestConnectorFactory); DISALLOW_COPY_AND_ASSIGN(TestConnectorFactory);
}; };
......
...@@ -14,30 +14,32 @@ ...@@ -14,30 +14,32 @@
namespace video_capture { namespace video_capture {
ServiceImpl::ServiceImpl(base::Optional<base::TimeDelta> shutdown_delay) namespace {
: shutdown_delay_(shutdown_delay), weak_factory_(this) {}
ServiceImpl::~ServiceImpl() {
DCHECK(thread_checker_.CalledOnValidThread());
if (destruction_cb_)
std::move(destruction_cb_).Run();
}
// static
std::unique_ptr<service_manager::Service> ServiceImpl::Create() {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
// On Android, we do not use automatic service shutdown, because when shutting // On Android, we do not use automatic service shutdown, because when shutting
// down the service, we lose caching of the supported formats, and re-querying // down the service, we lose caching of the supported formats, and re-querying
// these can take several seconds on certain Android devices. // these can take several seconds on certain Android devices.
return std::make_unique<ServiceImpl>(base::Optional<base::TimeDelta>()); constexpr base::Optional<base::TimeDelta> kDefaultIdleTimeout;
#else #else
return std::make_unique<ServiceImpl>(base::TimeDelta::FromSeconds(5)); constexpr base::Optional<base::TimeDelta> kDefaultIdleTimeout =
base::TimeDelta::FromSeconds(5);
#endif #endif
} // namespace
ServiceImpl::ServiceImpl(service_manager::mojom::ServiceRequest request)
: ServiceImpl(std::move(request), kDefaultIdleTimeout) {}
ServiceImpl::ServiceImpl(service_manager::mojom::ServiceRequest request,
base::Optional<base::TimeDelta> idle_timeout)
: binding_(this, std::move(request)), keepalive_(&binding_, idle_timeout) {
keepalive_.AddObserver(this);
} }
void ServiceImpl::SetDestructionObserver(base::OnceClosure observer_cb) { ServiceImpl::~ServiceImpl() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
destruction_cb_ = std::move(observer_cb); keepalive_.RemoveObserver(this);
} }
void ServiceImpl::SetFactoryProviderClientConnectedObserver( void ServiceImpl::SetFactoryProviderClientConnectedObserver(
...@@ -60,7 +62,7 @@ void ServiceImpl::SetShutdownTimeoutCancelledObserver( ...@@ -60,7 +62,7 @@ void ServiceImpl::SetShutdownTimeoutCancelledObserver(
bool ServiceImpl::HasNoContextRefs() { bool ServiceImpl::HasNoContextRefs() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
return ref_factory_->HasNoRefs(); return keepalive_.HasNoRefs();
} }
void ServiceImpl::OnStart() { void ServiceImpl::OnStart() {
...@@ -69,20 +71,13 @@ void ServiceImpl::OnStart() { ...@@ -69,20 +71,13 @@ void ServiceImpl::OnStart() {
video_capture::uma::LogVideoCaptureServiceEvent( video_capture::uma::LogVideoCaptureServiceEvent(
video_capture::uma::SERVICE_STARTED); video_capture::uma::SERVICE_STARTED);
// Do not replace |ref_factory_| if one has already been set via
// SetServiceContextRefProviderForTesting().
if (!ref_factory_) {
ref_factory_ = std::make_unique<service_manager::ServiceKeepalive>(
context(), shutdown_delay_, this);
}
registry_.AddInterface<mojom::DeviceFactoryProvider>( registry_.AddInterface<mojom::DeviceFactoryProvider>(
// Unretained |this| is safe because |registry_| is owned by |this|. // Unretained |this| is safe because |registry_| is owned by |this|.
base::Bind(&ServiceImpl::OnDeviceFactoryProviderRequest, base::BindRepeating(&ServiceImpl::OnDeviceFactoryProviderRequest,
base::Unretained(this))); base::Unretained(this)));
registry_.AddInterface<mojom::TestingControls>( registry_.AddInterface<mojom::TestingControls>(
// Unretained |this| is safe because |registry_| is owned by |this|. // Unretained |this| is safe because |registry_| is owned by |this|.
base::Bind(&ServiceImpl::OnTestingControlsRequest, base::BindRepeating(&ServiceImpl::OnTestingControlsRequest,
base::Unretained(this))); base::Unretained(this)));
// Unretained |this| is safe because |factory_provider_bindings_| is owned by // Unretained |this| is safe because |factory_provider_bindings_| is owned by
...@@ -104,12 +99,12 @@ bool ServiceImpl::OnServiceManagerConnectionLost() { ...@@ -104,12 +99,12 @@ bool ServiceImpl::OnServiceManagerConnectionLost() {
return true; return true;
} }
void ServiceImpl::OnTimeoutExpired() { void ServiceImpl::OnIdleTimeout() {
video_capture::uma::LogVideoCaptureServiceEvent( video_capture::uma::LogVideoCaptureServiceEvent(
video_capture::uma::SERVICE_SHUTTING_DOWN_BECAUSE_NO_CLIENT); video_capture::uma::SERVICE_SHUTTING_DOWN_BECAUSE_NO_CLIENT);
} }
void ServiceImpl::OnTimeoutCancelled() { void ServiceImpl::OnIdleTimeoutCancelled() {
video_capture::uma::LogVideoCaptureServiceEvent( video_capture::uma::LogVideoCaptureServiceEvent(
video_capture::uma::SERVICE_SHUTDOWN_TIMEOUT_CANCELED); video_capture::uma::SERVICE_SHUTDOWN_TIMEOUT_CANCELED);
if (shutdown_timeout_cancelled_cb_) if (shutdown_timeout_cancelled_cb_)
...@@ -121,7 +116,7 @@ void ServiceImpl::OnDeviceFactoryProviderRequest( ...@@ -121,7 +116,7 @@ void ServiceImpl::OnDeviceFactoryProviderRequest(
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
LazyInitializeDeviceFactoryProvider(); LazyInitializeDeviceFactoryProvider();
if (factory_provider_bindings_.empty()) if (factory_provider_bindings_.empty())
device_factory_provider_->SetServiceRef(ref_factory_->CreateRef()); device_factory_provider_->SetServiceRef(keepalive_.CreateRef());
factory_provider_bindings_.AddBinding(device_factory_provider_.get(), factory_provider_bindings_.AddBinding(device_factory_provider_.get(),
std::move(request)); std::move(request));
...@@ -134,7 +129,7 @@ void ServiceImpl::OnTestingControlsRequest( ...@@ -134,7 +129,7 @@ void ServiceImpl::OnTestingControlsRequest(
mojom::TestingControlsRequest request) { mojom::TestingControlsRequest request) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
mojo::MakeStrongBinding( mojo::MakeStrongBinding(
std::make_unique<TestingControlsImpl>(ref_factory_->CreateRef()), std::make_unique<TestingControlsImpl>(keepalive_.CreateRef()),
std::move(request)); std::move(request));
} }
......
...@@ -7,10 +7,13 @@ ...@@ -7,10 +7,13 @@
#include <memory> #include <memory>
#include "base/optional.h"
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/binding_set.h"
#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/service.h" #include "services/service_manager/public/cpp/service.h"
#include "services/service_manager/public/cpp/service_binding.h"
#include "services/service_manager/public/cpp/service_keepalive.h" #include "services/service_manager/public/cpp/service_keepalive.h"
#include "services/video_capture/device_factory_provider_impl.h" #include "services/video_capture/device_factory_provider_impl.h"
#include "services/video_capture/public/mojom/device_factory_provider.mojom.h" #include "services/video_capture/public/mojom/device_factory_provider.mojom.h"
...@@ -23,16 +26,17 @@ ...@@ -23,16 +26,17 @@
namespace video_capture { namespace video_capture {
class ServiceImpl : public service_manager::Service, class ServiceImpl : public service_manager::Service,
public service_manager::ServiceKeepalive::TimeoutObserver { public service_manager::ServiceKeepalive::Observer {
public: public:
// If |shutdown_delay| is provided, the service will shut itself down as soon explicit ServiceImpl(service_manager::mojom::ServiceRequest request);
// as no client was connect for the corresponding duration.
explicit ServiceImpl(base::Optional<base::TimeDelta> shutdown_delay); // Constructs a service instance which overrides the default idle timeout
~ServiceImpl() override; // behavior.
ServiceImpl(service_manager::mojom::ServiceRequest request,
base::Optional<base::TimeDelta> idle_timeout);
static std::unique_ptr<service_manager::Service> Create(); ~ServiceImpl() override;
void SetDestructionObserver(base::OnceClosure observer_cb);
void SetFactoryProviderClientConnectedObserver( void SetFactoryProviderClientConnectedObserver(
base::RepeatingClosure observer_cb); base::RepeatingClosure observer_cb);
void SetFactoryProviderClientDisconnectedObserver( void SetFactoryProviderClientDisconnectedObserver(
...@@ -47,9 +51,9 @@ class ServiceImpl : public service_manager::Service, ...@@ -47,9 +51,9 @@ class ServiceImpl : public service_manager::Service,
mojo::ScopedMessagePipeHandle interface_pipe) override; mojo::ScopedMessagePipeHandle interface_pipe) override;
bool OnServiceManagerConnectionLost() override; bool OnServiceManagerConnectionLost() override;
// service_manager::ServiceKeepalive::TimeoutObserver implementation. // service_manager::ServiceKeepalive::Observer implementation.
void OnTimeoutExpired() override; void OnIdleTimeout() override;
void OnTimeoutCancelled() override; void OnIdleTimeoutCancelled() override;
private: private:
void OnDeviceFactoryProviderRequest( void OnDeviceFactoryProviderRequest(
...@@ -60,7 +64,9 @@ class ServiceImpl : public service_manager::Service, ...@@ -60,7 +64,9 @@ class ServiceImpl : public service_manager::Service,
void LazyInitializeDeviceFactoryProvider(); void LazyInitializeDeviceFactoryProvider();
void OnProviderClientDisconnected(); void OnProviderClientDisconnected();
const base::Optional<base::TimeDelta> shutdown_delay_; service_manager::ServiceBinding binding_;
service_manager::ServiceKeepalive keepalive_;
#if defined(OS_WIN) #if defined(OS_WIN)
// COM must be initialized in order to access the video capture devices. // COM must be initialized in order to access the video capture devices.
base::win::ScopedCOMInitializer com_initializer_; base::win::ScopedCOMInitializer com_initializer_;
...@@ -68,16 +74,13 @@ class ServiceImpl : public service_manager::Service, ...@@ -68,16 +74,13 @@ class ServiceImpl : public service_manager::Service,
service_manager::BinderRegistry registry_; service_manager::BinderRegistry registry_;
mojo::BindingSet<mojom::DeviceFactoryProvider> factory_provider_bindings_; mojo::BindingSet<mojom::DeviceFactoryProvider> factory_provider_bindings_;
std::unique_ptr<DeviceFactoryProviderImpl> device_factory_provider_; std::unique_ptr<DeviceFactoryProviderImpl> device_factory_provider_;
std::unique_ptr<service_manager::ServiceKeepalive> ref_factory_;
// Callbacks that can optionally be set by clients. // Callbacks that can optionally be set by clients.
base::OnceClosure destruction_cb_;
base::RepeatingClosure factory_provider_client_connected_cb_; base::RepeatingClosure factory_provider_client_connected_cb_;
base::RepeatingClosure factory_provider_client_disconnected_cb_; base::RepeatingClosure factory_provider_client_disconnected_cb_;
base::RepeatingClosure shutdown_timeout_cancelled_cb_; base::RepeatingClosure shutdown_timeout_cancelled_cb_;
base::ThreadChecker thread_checker_; base::ThreadChecker thread_checker_;
base::WeakPtrFactory<ServiceImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceImpl); DISALLOW_COPY_AND_ASSIGN(ServiceImpl);
}; };
......
...@@ -2,12 +2,19 @@ ...@@ -2,12 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "services/service_manager/public/c/main.h" #include "services/service_manager/public/c/main.h"
#include "services/service_manager/public/cpp/service_runner.h" #include "services/service_manager/public/mojom/service.mojom.h"
#include "services/video_capture/service_impl.h" #include "services/video_capture/service_impl.h"
MojoResult ServiceMain(MojoHandle service_request_handle) { MojoResult ServiceMain(MojoHandle service_request_handle) {
return service_manager::ServiceRunner( base::MessageLoop message_loop;
video_capture::ServiceImpl::Create().release()) base::RunLoop run_loop;
.Run(service_request_handle); video_capture::ServiceImpl service{service_manager::mojom::ServiceRequest(
mojo::MakeScopedHandle(mojo::MessagePipeHandle(service_request_handle)))};
service.set_termination_closure(run_loop.QuitClosure());
run_loop.Run();
return MOJO_RESULT_OK;
} }
...@@ -33,26 +33,21 @@ class DeviceFactoryProviderConnectorTest : public ::testing::Test { ...@@ -33,26 +33,21 @@ class DeviceFactoryProviderConnectorTest : public ::testing::Test {
void SetUp() override { void SetUp() override {
base::CommandLine::ForCurrentProcess()->AppendSwitch( base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream); switches::kUseFakeDeviceForMediaStream);
std::unique_ptr<ServiceImpl> service_impl = std::make_unique<ServiceImpl>( service_impl_ = std::make_unique<ServiceImpl>(
connector_factory_.RegisterInstance(video_capture::mojom::kServiceName),
DeviceFactoryProviderConnectorTestTraits::shutdown_delay()); DeviceFactoryProviderConnectorTestTraits::shutdown_delay());
service_impl->SetDestructionObserver(base::BindOnce( service_impl_->set_termination_closure(
[](base::RunLoop* service_destroyed_wait_loop) { base::BindOnce(&DeviceFactoryProviderConnectorTest::OnServiceQuit,
service_destroyed_wait_loop->Quit(); base::Unretained(this)));
},
&service_destroyed_wait_loop_)); connector_ = connector_factory_.CreateConnector();
service_impl_ = service_impl.get();
connector_factory_ =
service_manager::TestConnectorFactory::CreateForUniqueService(
std::move(service_impl), true /*release_service_on_quit_request*/);
connector_ = connector_factory_->CreateConnector();
{
base::RunLoop wait_loop; base::RunLoop wait_loop;
service_impl_->SetFactoryProviderClientConnectedObserver( service_impl_->SetFactoryProviderClientConnectedObserver(
wait_loop.QuitClosure()); wait_loop.QuitClosure());
connector_->BindInterface(mojom::kServiceName, &factory_provider_); connector_->BindInterface(mojom::kServiceName, &factory_provider_);
wait_loop.Run(); wait_loop.Run();
} }
}
void TearDown() override { void TearDown() override {
if (factory_provider_.is_bound() && if (factory_provider_.is_bound() &&
...@@ -65,15 +60,25 @@ class DeviceFactoryProviderConnectorTest : public ::testing::Test { ...@@ -65,15 +60,25 @@ class DeviceFactoryProviderConnectorTest : public ::testing::Test {
protected: protected:
base::test::ScopedTaskEnvironment scoped_task_environment_; base::test::ScopedTaskEnvironment scoped_task_environment_;
ServiceImpl* service_impl_; std::unique_ptr<ServiceImpl> service_impl_;
mojom::DeviceFactoryProviderPtr factory_provider_; mojom::DeviceFactoryProviderPtr factory_provider_;
base::MockCallback<mojom::DeviceFactory::GetDeviceInfosCallback> base::MockCallback<mojom::DeviceFactory::GetDeviceInfosCallback>
device_info_receiver_; device_info_receiver_;
std::unique_ptr<service_manager::Connector> connector_; std::unique_ptr<service_manager::Connector> connector_;
base::RunLoop service_destroyed_wait_loop_; base::RunLoop service_destroyed_wait_loop_;
base::OnceClosure service_quit_callback_;
private: private:
std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_; void OnServiceQuit() {
service_impl_.reset();
service_destroyed_wait_loop_.Quit();
if (service_quit_callback_)
std::move(service_quit_callback_).Run();
}
service_manager::TestConnectorFactory connector_factory_;
DISALLOW_COPY_AND_ASSIGN(DeviceFactoryProviderConnectorTest);
}; };
// We need to set the shutdown delay to at least some epsilon > 0 in order // We need to set the shutdown delay to at least some epsilon > 0 in order
...@@ -233,7 +238,7 @@ TEST_F(NoAutomaticShutdownDeviceFactoryProviderConnectorTest, ...@@ -233,7 +238,7 @@ TEST_F(NoAutomaticShutdownDeviceFactoryProviderConnectorTest,
} }
base::MockCallback<base::OnceClosure> service_impl_destructor_cb; base::MockCallback<base::OnceClosure> service_impl_destructor_cb;
service_impl_->SetDestructionObserver(service_impl_destructor_cb.Get()); service_quit_callback_ = service_impl_destructor_cb.Get();
EXPECT_CALL(service_impl_destructor_cb, Run()).Times(0); EXPECT_CALL(service_impl_destructor_cb, Run()).Times(0);
// Wait for an arbitrary short extra time after which we are convinced that // Wait for an arbitrary short extra time after which we are convinced that
...@@ -246,7 +251,7 @@ TEST_F(NoAutomaticShutdownDeviceFactoryProviderConnectorTest, ...@@ -246,7 +251,7 @@ TEST_F(NoAutomaticShutdownDeviceFactoryProviderConnectorTest,
wait_loop.Run(); wait_loop.Run();
} }
service_impl_->SetDestructionObserver(base::DoNothing()); service_quit_callback_.Reset();
} }
} // namespace video_capture } // namespace video_capture
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