Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromeos/dbus/services/cros_dbus_service.h" | 5 #include "chromeos/dbus/services/cros_dbus_service.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/memory/ptr_util.h" | |
| 11 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 12 #include "base/sys_info.h" | 13 #include "base/sys_info.h" |
| 13 #include "chromeos/dbus/dbus_thread_manager.h" | 14 #include "chromeos/dbus/dbus_thread_manager.h" |
| 14 #include "dbus/bus.h" | 15 #include "dbus/bus.h" |
| 15 #include "dbus/exported_object.h" | 16 #include "dbus/exported_object.h" |
| 16 #include "dbus/object_path.h" | 17 #include "dbus/object_path.h" |
| 17 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 18 | 18 |
| 19 namespace chromeos { | 19 namespace chromeos { |
| 20 | 20 |
| 21 namespace { | |
| 22 | |
| 23 CrosDBusService* g_cros_dbus_service = NULL; | |
| 24 | |
| 25 } // namespace | |
| 26 | |
| 27 // The CrosDBusService implementation used in production, and unit tests. | 21 // The CrosDBusService implementation used in production, and unit tests. |
| 28 class CrosDBusServiceImpl : public CrosDBusService { | 22 class CrosDBusServiceImpl : public CrosDBusService { |
| 29 public: | 23 public: |
| 30 CrosDBusServiceImpl(dbus::Bus* bus, ServiceProviderList service_providers) | 24 CrosDBusServiceImpl(dbus::Bus* bus, |
| 25 const std::string& service_name, | |
| 26 const dbus::ObjectPath& object_path, | |
| 27 ServiceProviderList service_providers) | |
| 31 : service_started_(false), | 28 : service_started_(false), |
| 32 origin_thread_id_(base::PlatformThread::CurrentId()), | 29 origin_thread_id_(base::PlatformThread::CurrentId()), |
| 33 bus_(bus), | 30 bus_(bus), |
| 31 service_name_(service_name), | |
| 32 object_path_(object_path), | |
| 34 service_providers_(std::move(service_providers)) {} | 33 service_providers_(std::move(service_providers)) {} |
|
James Cook
2017/02/15 01:53:34
nit: Is there anything useful you can DCHECK here,
Daniel Erat
2017/02/15 16:56:59
Done.
| |
| 35 | 34 |
| 36 ~CrosDBusServiceImpl() override { | 35 ~CrosDBusServiceImpl() override = default; |
| 37 } | |
| 38 | 36 |
| 39 // Starts the D-Bus service. | 37 // Starts the D-Bus service. |
| 40 void Start() { | 38 void Start() { |
| 41 // Make sure we're running on the origin thread (i.e. the UI thread in | 39 // Make sure we're running on the origin thread (i.e. the UI thread in |
| 42 // production). | 40 // production). |
| 43 DCHECK(OnOriginThread()); | 41 DCHECK(OnOriginThread()); |
| 44 | 42 DCHECK(!service_started_); |
| 45 // Return if the service has been already started. | |
| 46 if (service_started_) | |
| 47 return; | |
| 48 | 43 |
| 49 // There are some situations, described in http://crbug.com/234382#c27, | 44 // There are some situations, described in http://crbug.com/234382#c27, |
| 50 // where processes on Linux can wind up stuck in an uninterruptible state | 45 // where processes on Linux can wind up stuck in an uninterruptible state |
| 51 // for tens of seconds. If this happens when Chrome is trying to exit, | 46 // for tens of seconds. If this happens when Chrome is trying to exit, this |
| 52 // this unkillable process can wind up clinging to ownership of | 47 // unkillable process can wind up clinging to ownership of |service_name_| |
| 53 // kLibCrosServiceName while the system is trying to restart the browser. | 48 // while the system is trying to restart the browser. This leads to a fatal |
| 54 // This leads to a fatal situation if we don't allow the new browser | 49 // situation if we don't allow the new browser instance to replace the old |
| 55 // instance to replace the old as the owner of kLibCrosServiceName as seen | 50 // as the owner of |service_name_| as seen in http://crbug.com/234382. |
| 56 // in http://crbug.com/234382. Hence, REQUIRE_PRIMARY_ALLOW_REPLACEMENT. | 51 // Hence, REQUIRE_PRIMARY_ALLOW_REPLACEMENT. |
| 57 bus_->RequestOwnership(kLibCrosServiceName, | 52 bus_->RequestOwnership( |
| 58 dbus::Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT, | 53 service_name_, dbus::Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT, |
| 59 base::Bind(&CrosDBusServiceImpl::OnOwnership, | 54 base::Bind(&CrosDBusServiceImpl::OnOwnership, base::Unretained(this))); |
| 60 base::Unretained(this))); | |
| 61 | 55 |
| 62 exported_object_ = bus_->GetExportedObject( | 56 exported_object_ = bus_->GetExportedObject(object_path_); |
| 63 dbus::ObjectPath(kLibCrosServicePath)); | |
| 64 | |
| 65 for (size_t i = 0; i < service_providers_.size(); ++i) | 57 for (size_t i = 0; i < service_providers_.size(); ++i) |
| 66 service_providers_[i]->Start(exported_object_); | 58 service_providers_[i]->Start(exported_object_); |
| 67 | 59 |
| 60 VLOG(1) << "CrosDBusServiceImpl started for " << service_name_; | |
| 68 service_started_ = true; | 61 service_started_ = true; |
| 69 | |
| 70 VLOG(1) << "CrosDBusServiceImpl started."; | |
| 71 } | 62 } |
| 72 | 63 |
| 73 private: | 64 private: |
| 74 // Returns true if the current thread is on the origin thread. | 65 // Returns true if the current thread is on the origin thread. |
| 75 bool OnOriginThread() { | 66 bool OnOriginThread() { |
| 76 return base::PlatformThread::CurrentId() == origin_thread_id_; | 67 return base::PlatformThread::CurrentId() == origin_thread_id_; |
| 77 } | 68 } |
| 78 | 69 |
| 79 // Called when an ownership request is completed. | 70 // Called when an ownership request is completed. |
| 80 void OnOwnership(const std::string& service_name, | 71 void OnOwnership(const std::string& service_name, |
| 81 bool success) { | 72 bool success) { |
| 82 LOG_IF(FATAL, !success) << "Failed to own: " << service_name; | 73 LOG_IF(FATAL, !success) << "Failed to own: " << service_name; |
| 83 } | 74 } |
| 84 | 75 |
| 85 bool service_started_; | 76 bool service_started_; |
| 86 base::PlatformThreadId origin_thread_id_; | 77 base::PlatformThreadId origin_thread_id_; |
| 87 dbus::Bus* bus_; | 78 dbus::Bus* bus_; |
| 79 std::string service_name_; | |
| 80 dbus::ObjectPath object_path_; | |
| 88 scoped_refptr<dbus::ExportedObject> exported_object_; | 81 scoped_refptr<dbus::ExportedObject> exported_object_; |
| 89 | 82 |
| 90 // Service providers that form CrosDBusService. | 83 // Service providers that form CrosDBusService. |
| 91 ServiceProviderList service_providers_; | 84 ServiceProviderList service_providers_; |
| 85 | |
| 86 DISALLOW_COPY_AND_ASSIGN(CrosDBusServiceImpl); | |
| 92 }; | 87 }; |
| 93 | 88 |
| 94 // The stub CrosDBusService implementation used on Linux desktop, | 89 // The stub CrosDBusService implementation used on Linux desktop, |
| 95 // which does nothing as of now. | 90 // which does nothing as of now. |
| 96 class CrosDBusServiceStubImpl : public CrosDBusService { | 91 class CrosDBusServiceStubImpl : public CrosDBusService { |
| 97 public: | 92 public: |
| 98 CrosDBusServiceStubImpl() { | 93 CrosDBusServiceStubImpl() {} |
|
hashimoto
2017/02/15 08:44:06
nit: =default here doesn't work?
Daniel Erat
2017/02/15 16:56:59
hmm. i thought i'd seen compiler errors from one t
| |
| 99 } | 94 ~CrosDBusServiceStubImpl() override = default; |
| 100 | 95 |
| 101 ~CrosDBusServiceStubImpl() override {} | 96 private: |
| 97 DISALLOW_COPY_AND_ASSIGN(CrosDBusServiceStubImpl); | |
| 102 }; | 98 }; |
| 103 | 99 |
| 104 // static | 100 // static |
| 105 void CrosDBusService::Initialize(ServiceProviderList service_providers) { | 101 std::unique_ptr<CrosDBusService> CrosDBusService::Create( |
| 106 if (g_cros_dbus_service) { | 102 const std::string& service_name, |
| 107 LOG(WARNING) << "CrosDBusService was already initialized"; | 103 const dbus::ObjectPath& object_path, |
| 108 return; | 104 ServiceProviderList service_providers) { |
| 109 } | |
| 110 dbus::Bus* bus = DBusThreadManager::Get()->GetSystemBus(); | 105 dbus::Bus* bus = DBusThreadManager::Get()->GetSystemBus(); |
| 111 if (base::SysInfo::IsRunningOnChromeOS() && bus) { | 106 if (!base::SysInfo::IsRunningOnChromeOS() || !bus) |
|
hashimoto
2017/02/15 08:44:06
How about using DBusThreadManager::IsUsingFakes in
Daniel Erat
2017/02/15 16:56:59
i'll give it a try; hopefully it detects the same
| |
| 112 auto* service = new CrosDBusServiceImpl(bus, std::move(service_providers)); | 107 return std::unique_ptr<CrosDBusService>(new CrosDBusServiceStubImpl()); |
|
hashimoto
2017/02/15 08:44:06
nit: base::MakeUnique?
Daniel Erat
2017/02/15 16:56:59
ah, thanks. i wasn't sure about the rules around h
| |
| 113 g_cros_dbus_service = service; | 108 |
| 114 service->Start(); | 109 return CreateRealImpl(bus, service_name, object_path, |
| 115 } else { | 110 std::move(service_providers)); |
| 116 g_cros_dbus_service = new CrosDBusServiceStubImpl; | |
| 117 } | |
| 118 VLOG(1) << "CrosDBusService initialized"; | |
| 119 } | 111 } |
| 120 | 112 |
| 121 // static | 113 // static |
| 122 void CrosDBusService::InitializeForTesting( | 114 std::unique_ptr<CrosDBusService> CrosDBusService::CreateRealImpl( |
|
satorux1
2017/02/15 06:48:01
nit: this function looks pretty short. maybe just
Daniel Erat
2017/02/15 16:56:59
i would, except it's also needed by a test (see co
| |
| 123 dbus::Bus* bus, | 115 dbus::Bus* bus, |
| 116 const std::string& service_name, | |
| 117 const dbus::ObjectPath& object_path, | |
| 124 ServiceProviderList service_providers) { | 118 ServiceProviderList service_providers) { |
| 125 if (g_cros_dbus_service) { | 119 auto service = base::MakeUnique<CrosDBusServiceImpl>( |
| 126 LOG(WARNING) << "CrosDBusService was already initialized"; | 120 bus, service_name, object_path, std::move(service_providers)); |
| 127 return; | |
| 128 } | |
| 129 auto* service = new CrosDBusServiceImpl(bus, std::move(service_providers)); | |
| 130 service->Start(); | 121 service->Start(); |
| 131 g_cros_dbus_service = service; | 122 return std::move(service); |
| 132 VLOG(1) << "CrosDBusService initialized"; | |
| 133 } | 123 } |
| 134 | 124 |
| 135 // static | 125 CrosDBusService::~CrosDBusService() = default; |
| 136 void CrosDBusService::Shutdown() { | |
| 137 delete g_cros_dbus_service; | |
| 138 g_cros_dbus_service = NULL; | |
| 139 VLOG(1) << "CrosDBusService Shutdown completed"; | |
|
James Cook
2017/02/15 01:53:34
Was this VLOG not useful? It kinda feels like we e
Daniel Erat
2017/02/15 16:57:00
uh... well, _i_ never used it. :-P i've deleted th
| |
| 140 } | |
| 141 | 126 |
| 142 CrosDBusService::~CrosDBusService() { | 127 CrosDBusService::CrosDBusService() = default; |
| 143 } | |
| 144 | 128 |
| 145 CrosDBusService::ServiceProviderInterface::~ServiceProviderInterface() { | 129 CrosDBusService::ServiceProviderInterface::~ServiceProviderInterface() = |
| 146 } | 130 default; |
| 147 | 131 |
| 148 } // namespace chromeos | 132 } // namespace chromeos |
| OLD | NEW |