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 "chromeos/dbus/services/cros_dbus_service.h"
8 #include "base/stl_util.h"
9 #include "base/sys_info.h"
10 #include "chromeos/dbus/dbus_thread_manager.h"
12 #include "dbus/exported_object.h"
13 #include "dbus/object_path.h"
14 #include "third_party/cros_system_api/dbus/service_constants.h"
20 CrosDBusService
* g_cros_dbus_service
= NULL
;
24 // The CrosDBusService implementation used in production, and unit tests.
25 class CrosDBusServiceImpl
: public CrosDBusService
{
27 CrosDBusServiceImpl(dbus::Bus
* bus
,
28 ScopedVector
<ServiceProviderInterface
> service_providers
)
29 : service_started_(false),
30 origin_thread_id_(base::PlatformThread::CurrentId()),
32 service_providers_(service_providers
.Pass()) {
35 ~CrosDBusServiceImpl() override
{
38 // Starts the D-Bus service.
40 // Make sure we're running on the origin thread (i.e. the UI thread in
42 DCHECK(OnOriginThread());
44 // Return if the service has been already started.
48 // There are some situations, described in http://crbug.com/234382#c27,
49 // where processes on Linux can wind up stuck in an uninterruptible state
50 // for tens of seconds. If this happens when Chrome is trying to exit,
51 // this unkillable process can wind up clinging to ownership of
52 // kLibCrosServiceName while the system is trying to restart the browser.
53 // This leads to a fatal situation if we don't allow the new browser
54 // instance to replace the old as the owner of kLibCrosServiceName as seen
55 // in http://crbug.com/234382. Hence, REQUIRE_PRIMARY_ALLOW_REPLACEMENT.
56 bus_
->RequestOwnership(kLibCrosServiceName
,
57 dbus::Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT
,
58 base::Bind(&CrosDBusServiceImpl::OnOwnership
,
59 base::Unretained(this)));
61 exported_object_
= bus_
->GetExportedObject(
62 dbus::ObjectPath(kLibCrosServicePath
));
64 for (size_t i
= 0; i
< service_providers_
.size(); ++i
)
65 service_providers_
[i
]->Start(exported_object_
);
67 service_started_
= true;
69 VLOG(1) << "CrosDBusServiceImpl started.";
73 // Returns true if the current thread is on the origin thread.
74 bool OnOriginThread() {
75 return base::PlatformThread::CurrentId() == origin_thread_id_
;
78 // Called when an ownership request is completed.
79 void OnOwnership(const std::string
& service_name
,
81 LOG_IF(FATAL
, !success
) << "Failed to own: " << service_name
;
84 bool service_started_
;
85 base::PlatformThreadId origin_thread_id_
;
87 scoped_refptr
<dbus::ExportedObject
> exported_object_
;
89 // Service providers that form CrosDBusService.
90 ScopedVector
<ServiceProviderInterface
> service_providers_
;
93 // The stub CrosDBusService implementation used on Linux desktop,
94 // which does nothing as of now.
95 class CrosDBusServiceStubImpl
: public CrosDBusService
{
97 CrosDBusServiceStubImpl() {
100 ~CrosDBusServiceStubImpl() override
{}
104 void CrosDBusService::Initialize(
105 ScopedVector
<ServiceProviderInterface
> service_providers
) {
106 if (g_cros_dbus_service
) {
107 LOG(WARNING
) << "CrosDBusService was already initialized";
110 dbus::Bus
* bus
= DBusThreadManager::Get()->GetSystemBus();
111 if (base::SysInfo::IsRunningOnChromeOS() && bus
) {
112 auto* service
= new CrosDBusServiceImpl(bus
, service_providers
.Pass());
113 g_cros_dbus_service
= service
;
116 g_cros_dbus_service
= new CrosDBusServiceStubImpl
;
118 VLOG(1) << "CrosDBusService initialized";
122 void CrosDBusService::InitializeForTesting(
124 ScopedVector
<ServiceProviderInterface
> service_providers
) {
125 if (g_cros_dbus_service
) {
126 LOG(WARNING
) << "CrosDBusService was already initialized";
129 auto* service
= new CrosDBusServiceImpl(bus
, service_providers
.Pass());
131 g_cros_dbus_service
= service
;
132 VLOG(1) << "CrosDBusService initialized";
136 void CrosDBusService::Shutdown() {
137 delete g_cros_dbus_service
;
138 g_cros_dbus_service
= NULL
;
139 VLOG(1) << "CrosDBusService Shutdown completed";
142 CrosDBusService::~CrosDBusService() {
145 CrosDBusService::ServiceProviderInterface::~ServiceProviderInterface() {
148 } // namespace chromeos