• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/chromeos/dbus/cros_dbus_service.h"
6 
7 #include "base/bind.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"
17 #include "dbus/bus.h"
18 #include "dbus/exported_object.h"
19 #include "dbus/object_path.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h"
21 
22 namespace chromeos {
23 
24 namespace {
25 
26 CrosDBusService* g_cros_dbus_service = NULL;
27 
28 }  // namespace
29 
30 // The CrosDBusService implementation used in production, and unit tests.
31 class CrosDBusServiceImpl : public CrosDBusService {
32  public:
CrosDBusServiceImpl(dbus::Bus * bus)33   explicit CrosDBusServiceImpl(dbus::Bus* bus)
34       : service_started_(false),
35         origin_thread_id_(base::PlatformThread::CurrentId()),
36         bus_(bus) {
37   }
38 
~CrosDBusServiceImpl()39   virtual ~CrosDBusServiceImpl() {
40     STLDeleteElements(&service_providers_);
41   }
42 
43   // Starts the D-Bus service.
Start()44   void Start() {
45     // Make sure we're running on the origin thread (i.e. the UI thread in
46     // production).
47     DCHECK(OnOriginThread());
48 
49     // Return if the service has been already started.
50     if (service_started_)
51       return;
52 
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)));
65 
66     exported_object_ = bus_->GetExportedObject(
67         dbus::ObjectPath(kLibCrosServicePath));
68 
69     for (size_t i = 0; i < service_providers_.size(); ++i)
70       service_providers_[i]->Start(exported_object_);
71 
72     service_started_ = true;
73 
74     VLOG(1) << "CrosDBusServiceImpl started.";
75   }
76 
77   // Registers a service provider. This must be done before Start().
78   // |provider| will be owned by CrosDBusService.
RegisterServiceProvider(ServiceProviderInterface * provider)79   void RegisterServiceProvider(ServiceProviderInterface* provider) {
80     service_providers_.push_back(provider);
81   }
82 
83  private:
84   // Returns true if the current thread is on the origin thread.
OnOriginThread()85   bool OnOriginThread() {
86     return base::PlatformThread::CurrentId() == origin_thread_id_;
87   }
88 
89   // Called when an ownership request is completed.
OnOwnership(const std::string & service_name,bool success)90   void OnOwnership(const std::string& service_name,
91                    bool success) {
92     LOG_IF(FATAL, !success) << "Failed to own: " << service_name;
93   }
94 
95   bool service_started_;
96   base::PlatformThreadId origin_thread_id_;
97   dbus::Bus* bus_;
98   scoped_refptr<dbus::ExportedObject> exported_object_;
99 
100   // Service providers that form CrosDBusService.
101   std::vector<ServiceProviderInterface*> service_providers_;
102 };
103 
104 // The stub CrosDBusService implementation used on Linux desktop,
105 // which does nothing as of now.
106 class CrosDBusServiceStubImpl : public CrosDBusService {
107  public:
CrosDBusServiceStubImpl()108   CrosDBusServiceStubImpl() {
109   }
110 
~CrosDBusServiceStubImpl()111   virtual ~CrosDBusServiceStubImpl() {
112   }
113 };
114 
115 // static
Initialize()116 void CrosDBusService::Initialize() {
117   if (g_cros_dbus_service) {
118     LOG(WARNING) << "CrosDBusService was already initialized";
119     return;
120   }
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)
126     // crbug.com/413897
127     service->RegisterServiceProvider(new DisplayPowerServiceProvider);
128     // crbug.com/401285
129     service->RegisterServiceProvider(new PrinterServiceProvider);
130 #endif
131     service->RegisterServiceProvider(new LivenessServiceProvider);
132     service->RegisterServiceProvider(new ScreenLockServiceProvider);
133     g_cros_dbus_service = service;
134     service->Start();
135   } else {
136     g_cros_dbus_service = new CrosDBusServiceStubImpl;
137   }
138   VLOG(1) << "CrosDBusService initialized";
139 }
140 
141 // static
InitializeForTesting(dbus::Bus * bus,ServiceProviderInterface * proxy_resolution_service)142 void CrosDBusService::InitializeForTesting(
143     dbus::Bus* bus,
144     ServiceProviderInterface* proxy_resolution_service) {
145   if (g_cros_dbus_service) {
146     LOG(WARNING) << "CrosDBusService was already initialized";
147     return;
148   }
149   CrosDBusServiceImpl* service =  new CrosDBusServiceImpl(bus);
150   service->RegisterServiceProvider(proxy_resolution_service);
151   service->Start();
152   g_cros_dbus_service = service;
153   VLOG(1) << "CrosDBusService initialized";
154 }
155 
156 // static
Shutdown()157 void CrosDBusService::Shutdown() {
158   delete g_cros_dbus_service;
159   g_cros_dbus_service = NULL;
160   VLOG(1) << "CrosDBusService Shutdown completed";
161 }
162 
~CrosDBusService()163 CrosDBusService::~CrosDBusService() {
164 }
165 
~ServiceProviderInterface()166 CrosDBusService::ServiceProviderInterface::~ServiceProviderInterface() {
167 }
168 
169 }  // namespace chromeos
170