cros_dbus_service.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/dbus/cros_dbus_service.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/chromeos/chromeos_version.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/dbus/display_power_service_provider.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/dbus/liveness_service_provider.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/dbus/printer_service_provider.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/dbus/proxy_resolution_service_provider.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/bus.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/exported_object.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrosDBusService* g_cros_dbus_service = NULL; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The CrosDBusService implementation used in production, and unit tests. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CrosDBusServiceImpl : public CrosDBusService { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CrosDBusServiceImpl(dbus::Bus* bus) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : service_started_(false), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origin_thread_id_(base::PlatformThread::CurrentId()), 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_(bus) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~CrosDBusServiceImpl() { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&service_providers_); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Starts the D-Bus service. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Start() { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we're running on the origin thread (i.e. the UI thread in 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // production). 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(OnOriginThread()); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return if the service has been already started. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (service_started_) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // There are some situations, described in http://crbug.com/234382#c27, 53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // where processes on Linux can wind up stuck in an uninterruptible state 54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // for tens of seconds. If this happens when Chrome is trying to exit, 55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // this unkillable process can wind up clinging to ownership of 56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // kLibCrosServiceName while the system is trying to restart the browser. 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // This leads to a fatal situation if we don't allow the new browser 58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // instance to replace the old as the owner of kLibCrosServiceName as seen 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // in http://crbug.com/234382. Hence, REQUIRE_PRIMARY_ALLOW_REPLACEMENT. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bus_->RequestOwnership(kLibCrosServiceName, 61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) dbus::Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CrosDBusServiceImpl::OnOwnership, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exported_object_ = bus_->GetExportedObject( 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus::ObjectPath(kLibCrosServicePath)); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < service_providers_.size(); ++i) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_providers_[i]->Start(exported_object_); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_started_ = true; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CrosDBusServiceImpl started."; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Registers a service provider. This must be done before Start(). 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |provider| will be owned by CrosDBusService. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RegisterServiceProvider(ServiceProviderInterface* provider) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_providers_.push_back(provider); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the current thread is on the origin thread. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool OnOriginThread() { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::PlatformThread::CurrentId() == origin_thread_id_; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called when an ownership request is completed. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnOwnership(const std::string& service_name, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success) { 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG_IF(FATAL, !success) << "Failed to own: " << service_name; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool service_started_; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThreadId origin_thread_id_; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus::Bus* bus_; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<dbus::ExportedObject> exported_object_; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Service providers that form CrosDBusService. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ServiceProviderInterface*> service_providers_; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The stub CrosDBusService implementation used on Linux desktop, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which does nothing as of now. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CrosDBusServiceStubImpl : public CrosDBusService { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrosDBusServiceStubImpl() { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~CrosDBusServiceStubImpl() { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosDBusService::Initialize() { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (g_cros_dbus_service) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "CrosDBusService was already initialized"; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus::Bus* bus = DBusThreadManager::Get()->GetSystemBus(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::chromeos::IsRunningOnChromeOS() && bus) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrosDBusServiceImpl* service = new CrosDBusServiceImpl(bus); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service->RegisterServiceProvider(ProxyResolutionServiceProvider::Create()); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service->RegisterServiceProvider(new DisplayPowerServiceProvider); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service->RegisterServiceProvider(new LivenessServiceProvider); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service->RegisterServiceProvider(new PrinterServiceProvider); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_cros_dbus_service = service; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service->Start(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_cros_dbus_service = new CrosDBusServiceStubImpl; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CrosDBusService initialized"; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosDBusService::InitializeForTesting( 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dbus::Bus* bus, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceProviderInterface* proxy_resolution_service) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (g_cros_dbus_service) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "CrosDBusService was already initialized"; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrosDBusServiceImpl* service = new CrosDBusServiceImpl(bus); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service->RegisterServiceProvider(proxy_resolution_service); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service->Start(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_cros_dbus_service = service; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CrosDBusService initialized"; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrosDBusService::Shutdown() { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete g_cros_dbus_service; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_cros_dbus_service = NULL; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CrosDBusService Shutdown completed"; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrosDBusService::~CrosDBusService() { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrosDBusService::ServiceProviderInterface::~ServiceProviderInterface() { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chromeos 164