1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/dbus/cros_dbus_service.h"
8 #include "base/stl_util.h"
9 #include "base/sys_info.h"
10 #include "base/threading/platform_thread.h"
11 #include "chrome/browser/chromeos/dbus/display_power_service_provider.h"
12 #include "chrome/browser/chromeos/dbus/liveness_service_provider.h"
13 #include "chrome/browser/chromeos/dbus/printer_service_provider.h"
14 #include "chrome/browser/chromeos/dbus/proxy_resolution_service_provider.h"
15 #include "chrome/browser/chromeos/dbus/screen_lock_service_provider.h"
16 #include "chromeos/dbus/dbus_thread_manager.h"
18 #include "dbus/exported_object.h"
19 #include "dbus/object_path.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h"
26 CrosDBusService
* g_cros_dbus_service
= NULL
;
30 // The CrosDBusService implementation used in production, and unit tests.
31 class CrosDBusServiceImpl
: public CrosDBusService
{
33 explicit CrosDBusServiceImpl(dbus::Bus
* bus
)
34 : service_started_(false),
35 origin_thread_id_(base::PlatformThread::CurrentId()),
39 virtual ~CrosDBusServiceImpl() {
40 STLDeleteElements(&service_providers_
);
43 // Starts the D-Bus service.
45 // Make sure we're running on the origin thread (i.e. the UI thread in
47 DCHECK(OnOriginThread());
49 // Return if the service has been already started.
53 // There are some situations, described in http://crbug.com/234382#c27,
54 // where processes on Linux can wind up stuck in an uninterruptible state
55 // for tens of seconds. If this happens when Chrome is trying to exit,
56 // this unkillable process can wind up clinging to ownership of
57 // kLibCrosServiceName while the system is trying to restart the browser.
58 // This leads to a fatal situation if we don't allow the new browser
59 // instance to replace the old as the owner of kLibCrosServiceName as seen
60 // in http://crbug.com/234382. Hence, REQUIRE_PRIMARY_ALLOW_REPLACEMENT.
61 bus_
->RequestOwnership(kLibCrosServiceName
,
62 dbus::Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT
,
63 base::Bind(&CrosDBusServiceImpl::OnOwnership
,
64 base::Unretained(this)));
66 exported_object_
= bus_
->GetExportedObject(
67 dbus::ObjectPath(kLibCrosServicePath
));
69 for (size_t i
= 0; i
< service_providers_
.size(); ++i
)
70 service_providers_
[i
]->Start(exported_object_
);
72 service_started_
= true;
74 VLOG(1) << "CrosDBusServiceImpl started.";
77 // Registers a service provider. This must be done before Start().
78 // |provider| will be owned by CrosDBusService.
79 void RegisterServiceProvider(ServiceProviderInterface
* provider
) {
80 service_providers_
.push_back(provider
);
84 // Returns true if the current thread is on the origin thread.
85 bool OnOriginThread() {
86 return base::PlatformThread::CurrentId() == origin_thread_id_
;
89 // Called when an ownership request is completed.
90 void OnOwnership(const std::string
& service_name
,
92 LOG_IF(FATAL
, !success
) << "Failed to own: " << service_name
;
95 bool service_started_
;
96 base::PlatformThreadId origin_thread_id_
;
98 scoped_refptr
<dbus::ExportedObject
> exported_object_
;
100 // Service providers that form CrosDBusService.
101 std::vector
<ServiceProviderInterface
*> service_providers_
;
104 // The stub CrosDBusService implementation used on Linux desktop,
105 // which does nothing as of now.
106 class CrosDBusServiceStubImpl
: public CrosDBusService
{
108 CrosDBusServiceStubImpl() {
111 virtual ~CrosDBusServiceStubImpl() {
116 void CrosDBusService::Initialize() {
117 if (g_cros_dbus_service
) {
118 LOG(WARNING
) << "CrosDBusService was already initialized";
121 dbus::Bus
* bus
= DBusThreadManager::Get()->GetSystemBus();
122 if (base::SysInfo::IsRunningOnChromeOS() && bus
) {
123 CrosDBusServiceImpl
* service
= new CrosDBusServiceImpl(bus
);
124 service
->RegisterServiceProvider(ProxyResolutionServiceProvider::Create());
125 #if !defined(USE_ATHENA)
127 service
->RegisterServiceProvider(new DisplayPowerServiceProvider
);
129 service
->RegisterServiceProvider(new PrinterServiceProvider
);
131 service
->RegisterServiceProvider(new LivenessServiceProvider
);
132 service
->RegisterServiceProvider(new ScreenLockServiceProvider
);
133 g_cros_dbus_service
= service
;
136 g_cros_dbus_service
= new CrosDBusServiceStubImpl
;
138 VLOG(1) << "CrosDBusService initialized";
142 void CrosDBusService::InitializeForTesting(
144 ServiceProviderInterface
* proxy_resolution_service
) {
145 if (g_cros_dbus_service
) {
146 LOG(WARNING
) << "CrosDBusService was already initialized";
149 CrosDBusServiceImpl
* service
= new CrosDBusServiceImpl(bus
);
150 service
->RegisterServiceProvider(proxy_resolution_service
);
152 g_cros_dbus_service
= service
;
153 VLOG(1) << "CrosDBusService initialized";
157 void CrosDBusService::Shutdown() {
158 delete g_cros_dbus_service
;
159 g_cros_dbus_service
= NULL
;
160 VLOG(1) << "CrosDBusService Shutdown completed";
163 CrosDBusService::~CrosDBusService() {
166 CrosDBusService::ServiceProviderInterface::~ServiceProviderInterface() {
169 } // namespace chromeos