dbus_thread_manager.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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 "chromeos/dbus/dbus_thread_manager.h" 6 7#include <map> 8 9#include "base/command_line.h" 10#include "base/observer_list.h" 11#include "base/sys_info.h" 12#include "base/threading/thread.h" 13#include "chromeos/chromeos_switches.h" 14#include "chromeos/dbus/bluetooth_adapter_client.h" 15#include "chromeos/dbus/bluetooth_agent_manager_client.h" 16#include "chromeos/dbus/bluetooth_device_client.h" 17#include "chromeos/dbus/bluetooth_input_client.h" 18#include "chromeos/dbus/bluetooth_profile_manager_client.h" 19#include "chromeos/dbus/cras_audio_client.h" 20#include "chromeos/dbus/cros_disks_client.h" 21#include "chromeos/dbus/cryptohome_client.h" 22#include "chromeos/dbus/dbus_client_implementation_type.h" 23#include "chromeos/dbus/dbus_thread_manager_observer.h" 24#include "chromeos/dbus/debug_daemon_client.h" 25#include "chromeos/dbus/gsm_sms_client.h" 26#include "chromeos/dbus/ibus/ibus_client.h" 27#include "chromeos/dbus/ibus/ibus_engine_factory_service.h" 28#include "chromeos/dbus/ibus/ibus_engine_service.h" 29#include "chromeos/dbus/image_burner_client.h" 30#include "chromeos/dbus/introspectable_client.h" 31#include "chromeos/dbus/modem_messaging_client.h" 32#include "chromeos/dbus/permission_broker_client.h" 33#include "chromeos/dbus/power_manager_client.h" 34#include "chromeos/dbus/power_policy_controller.h" 35#include "chromeos/dbus/session_manager_client.h" 36#include "chromeos/dbus/shill_device_client.h" 37#include "chromeos/dbus/shill_ipconfig_client.h" 38#include "chromeos/dbus/shill_manager_client.h" 39#include "chromeos/dbus/shill_profile_client.h" 40#include "chromeos/dbus/shill_service_client.h" 41#include "chromeos/dbus/shill_stub_helper.h" 42#include "chromeos/dbus/sms_client.h" 43#include "chromeos/dbus/system_clock_client.h" 44#include "chromeos/dbus/update_engine_client.h" 45#include "dbus/bus.h" 46#include "dbus/dbus_statistics.h" 47 48namespace chromeos { 49 50static DBusThreadManager* g_dbus_thread_manager = NULL; 51static bool g_dbus_thread_manager_set_for_testing = false; 52 53// The DBusThreadManager implementation used in production. 54class DBusThreadManagerImpl : public DBusThreadManager { 55 public: 56 explicit DBusThreadManagerImpl(DBusClientImplementationType client_type) { 57 DBusClientImplementationType client_type_override = client_type; 58 // If --dbus-stub was requested, pass STUB to specific components; 59 // Many components like login are not useful with a stub implementation. 60 if (CommandLine::ForCurrentProcess()->HasSwitch( 61 chromeos::switches::kDbusStub)) { 62 client_type_override = STUB_DBUS_CLIENT_IMPLEMENTATION; 63 } 64 65 // Create the D-Bus thread. 66 base::Thread::Options thread_options; 67 thread_options.message_loop_type = base::MessageLoop::TYPE_IO; 68 dbus_thread_.reset(new base::Thread("D-Bus thread")); 69 dbus_thread_->StartWithOptions(thread_options); 70 71 // Create the connection to the system bus. 72 dbus::Bus::Options system_bus_options; 73 system_bus_options.bus_type = dbus::Bus::SYSTEM; 74 system_bus_options.connection_type = dbus::Bus::PRIVATE; 75 system_bus_options.dbus_task_runner = dbus_thread_->message_loop_proxy(); 76 system_bus_ = new dbus::Bus(system_bus_options); 77 78 CreateDefaultClients(client_type, client_type_override); 79 } 80 81 // InitializeClients gets called after g_dbus_thread_manager is set. 82 // NOTE: Clients that access other clients in their Init() must be 83 // initialized in the correct order. This is the only place where Clients' 84 // Init() should be called if DBusThreadManager is being used. 85 void InitializeClients() { 86 InitClient(bluetooth_adapter_client_.get()); 87 InitClient(bluetooth_agent_manager_client_.get()); 88 InitClient(bluetooth_device_client_.get()); 89 InitClient(bluetooth_input_client_.get()); 90 InitClient(bluetooth_profile_manager_client_.get()); 91 InitClient(cras_audio_client_.get()); 92 InitClient(cros_disks_client_.get()); 93 InitClient(cryptohome_client_.get()); 94 InitClient(debug_daemon_client_.get()); 95 InitClient(shill_manager_client_.get()); 96 InitClient(shill_device_client_.get()); 97 InitClient(shill_ipconfig_client_.get()); 98 InitClient(shill_service_client_.get()); 99 InitClient(shill_profile_client_.get()); 100 InitClient(gsm_sms_client_.get()); 101 InitClient(image_burner_client_.get()); 102 InitClient(introspectable_client_.get()); 103 InitClient(modem_messaging_client_.get()); 104 InitClient(permission_broker_client_.get()); 105 InitClient(power_manager_client_.get()); 106 InitClient(session_manager_client_.get()); 107 InitClient(sms_client_.get()); 108 InitClient(system_clock_client_.get()); 109 InitClient(update_engine_client_.get()); 110 111 // PowerPolicyController is dependent on PowerManagerClient, so 112 // initialize it after the main list of clients. 113 power_policy_controller_.reset( 114 new PowerPolicyController(this, power_manager_client_.get())); 115 116 shill_stub_helper::SetupDefaultEnvironment(); 117 118 // This must be called after the list of clients so they've each had a 119 // chance to register with their object managers. 120 system_bus_->GetManagedObjects(); 121 } 122 123 virtual ~DBusThreadManagerImpl() { 124 FOR_EACH_OBSERVER(DBusThreadManagerObserver, observers_, 125 OnDBusThreadManagerDestroying(this)); 126 127 // Shut down the bus. During the browser shutdown, it's ok to shut down 128 // the bus synchronously. 129 system_bus_->ShutdownOnDBusThreadAndBlock(); 130 if (ibus_bus_.get()) 131 ibus_bus_->ShutdownOnDBusThreadAndBlock(); 132 133 // Release IBusEngineService instances. 134 for (std::map<dbus::ObjectPath, IBusEngineService*>::iterator it 135 = ibus_engine_services_.begin(); 136 it != ibus_engine_services_.end(); it++) { 137 delete it->second; 138 } 139 140 // Stop the D-Bus thread. 141 dbus_thread_->Stop(); 142 } 143 144 // DBusThreadManager override. 145 virtual void AddObserver(DBusThreadManagerObserver* observer) OVERRIDE { 146 DCHECK(observer); 147 observers_.AddObserver(observer); 148 } 149 150 // DBusThreadManager override. 151 virtual void RemoveObserver(DBusThreadManagerObserver* observer) OVERRIDE { 152 DCHECK(observer); 153 observers_.RemoveObserver(observer); 154 } 155 156 // DBusThreadManager override. 157 virtual void InitIBusBus( 158 const std::string &ibus_address, 159 const base::Closure& on_disconnected_callback) OVERRIDE { 160 DCHECK(!ibus_bus_.get()); 161 dbus::Bus::Options ibus_bus_options; 162 ibus_bus_options.bus_type = dbus::Bus::CUSTOM_ADDRESS; 163 ibus_bus_options.address = ibus_address; 164 ibus_bus_options.connection_type = dbus::Bus::PRIVATE; 165 ibus_bus_options.dbus_task_runner = dbus_thread_->message_loop_proxy(); 166 ibus_bus_options.disconnected_callback = on_disconnected_callback; 167 ibus_bus_ = new dbus::Bus(ibus_bus_options); 168 ibus_address_ = ibus_address; 169 VLOG(1) << "Connected to ibus-daemon: " << ibus_address; 170 171 DBusClientImplementationType client_type = STUB_DBUS_CLIENT_IMPLEMENTATION; 172 173 ibus_client_.reset( 174 IBusClient::Create(client_type, ibus_bus_.get())); 175 ibus_engine_factory_service_.reset( 176 IBusEngineFactoryService::Create(ibus_bus_.get(), client_type)); 177 178 ibus_engine_services_.clear(); 179 } 180 181 // DBusThreadManager overrides: 182 virtual dbus::Bus* GetSystemBus() OVERRIDE { 183 return system_bus_.get(); 184 } 185 186 virtual dbus::Bus* GetIBusBus() OVERRIDE { 187 return ibus_bus_.get(); 188 } 189 190 virtual BluetoothAdapterClient* GetBluetoothAdapterClient() OVERRIDE { 191 return bluetooth_adapter_client_.get(); 192 } 193 194 virtual BluetoothAgentManagerClient* GetBluetoothAgentManagerClient() 195 OVERRIDE { 196 return bluetooth_agent_manager_client_.get(); 197 } 198 199 virtual BluetoothDeviceClient* GetBluetoothDeviceClient() OVERRIDE { 200 return bluetooth_device_client_.get(); 201 } 202 203 virtual BluetoothInputClient* GetBluetoothInputClient() OVERRIDE { 204 return bluetooth_input_client_.get(); 205 } 206 207 virtual BluetoothProfileManagerClient* GetBluetoothProfileManagerClient() 208 OVERRIDE { 209 return bluetooth_profile_manager_client_.get(); 210 } 211 212 virtual CrasAudioClient* GetCrasAudioClient() OVERRIDE { 213 return cras_audio_client_.get(); 214 } 215 216 virtual CrosDisksClient* GetCrosDisksClient() OVERRIDE { 217 return cros_disks_client_.get(); 218 } 219 220 virtual CryptohomeClient* GetCryptohomeClient() OVERRIDE { 221 return cryptohome_client_.get(); 222 } 223 224 virtual DebugDaemonClient* GetDebugDaemonClient() OVERRIDE { 225 return debug_daemon_client_.get(); 226 } 227 228 virtual ShillDeviceClient* GetShillDeviceClient() OVERRIDE { 229 return shill_device_client_.get(); 230 } 231 232 virtual ShillIPConfigClient* GetShillIPConfigClient() OVERRIDE { 233 return shill_ipconfig_client_.get(); 234 } 235 236 virtual ShillManagerClient* GetShillManagerClient() OVERRIDE { 237 return shill_manager_client_.get(); 238 } 239 240 virtual ShillServiceClient* GetShillServiceClient() OVERRIDE { 241 return shill_service_client_.get(); 242 } 243 244 virtual ShillProfileClient* GetShillProfileClient() OVERRIDE { 245 return shill_profile_client_.get(); 246 } 247 248 virtual GsmSMSClient* GetGsmSMSClient() OVERRIDE { 249 return gsm_sms_client_.get(); 250 } 251 252 virtual ImageBurnerClient* GetImageBurnerClient() OVERRIDE { 253 return image_burner_client_.get(); 254 } 255 256 virtual IntrospectableClient* GetIntrospectableClient() OVERRIDE { 257 return introspectable_client_.get(); 258 } 259 260 virtual ModemMessagingClient* GetModemMessagingClient() OVERRIDE { 261 return modem_messaging_client_.get(); 262 } 263 264 virtual PermissionBrokerClient* GetPermissionBrokerClient() OVERRIDE { 265 return permission_broker_client_.get(); 266 } 267 268 virtual PowerManagerClient* GetPowerManagerClient() OVERRIDE { 269 return power_manager_client_.get(); 270 } 271 272 virtual PowerPolicyController* GetPowerPolicyController() OVERRIDE { 273 return power_policy_controller_.get(); 274 } 275 276 virtual SessionManagerClient* GetSessionManagerClient() OVERRIDE { 277 return session_manager_client_.get(); 278 } 279 280 virtual SMSClient* GetSMSClient() OVERRIDE { 281 return sms_client_.get(); 282 } 283 284 virtual SystemClockClient* GetSystemClockClient() OVERRIDE { 285 return system_clock_client_.get(); 286 } 287 288 virtual UpdateEngineClient* GetUpdateEngineClient() OVERRIDE { 289 return update_engine_client_.get(); 290 } 291 292 virtual IBusClient* GetIBusClient() OVERRIDE { 293 return ibus_client_.get(); 294 } 295 296 virtual IBusEngineFactoryService* GetIBusEngineFactoryService() OVERRIDE { 297 return ibus_engine_factory_service_.get(); 298 } 299 300 virtual IBusEngineService* GetIBusEngineService( 301 const dbus::ObjectPath& object_path) OVERRIDE { 302 if (ibus_engine_services_.find(object_path) 303 == ibus_engine_services_.end()) { 304 ibus_engine_services_[object_path] = IBusEngineService::Create(); 305 } 306 return ibus_engine_services_[object_path]; 307 } 308 309 virtual void RemoveIBusEngineService( 310 const dbus::ObjectPath& object_path) OVERRIDE { 311 if (ibus_engine_services_.find(object_path) != 312 ibus_engine_services_.end()) { 313 LOG(WARNING) << "Object path not found: " << object_path.value(); 314 return; 315 } 316 delete ibus_engine_services_[object_path]; 317 ibus_engine_services_.erase(object_path); 318 } 319 320 private: 321 // Initializes |client| with the |system_bus_|. 322 void InitClient(DBusClient* client) { 323 client->Init(system_bus_.get()); 324 } 325 326 // Constructs all clients -- stub or real implementation according to 327 // |client_type| and |client_type_override| -- and stores them in the 328 // respective *_client_ member variable. 329 void CreateDefaultClients(DBusClientImplementationType client_type, 330 DBusClientImplementationType client_type_override) { 331 bluetooth_adapter_client_.reset( 332 BluetoothAdapterClient::Create(client_type)); 333 bluetooth_agent_manager_client_.reset( 334 BluetoothAgentManagerClient::Create(client_type)); 335 bluetooth_device_client_.reset(BluetoothDeviceClient::Create(client_type)); 336 bluetooth_input_client_.reset(BluetoothInputClient::Create(client_type)); 337 bluetooth_profile_manager_client_.reset( 338 BluetoothProfileManagerClient::Create(client_type)); 339 cras_audio_client_.reset(CrasAudioClient::Create(client_type)); 340 cros_disks_client_.reset(CrosDisksClient::Create(client_type)); 341 cryptohome_client_.reset(CryptohomeClient::Create(client_type)); 342 debug_daemon_client_.reset(DebugDaemonClient::Create(client_type)); 343 shill_manager_client_.reset( 344 ShillManagerClient::Create(client_type_override)); 345 shill_device_client_.reset( 346 ShillDeviceClient::Create(client_type_override)); 347 shill_ipconfig_client_.reset( 348 ShillIPConfigClient::Create(client_type_override)); 349 shill_service_client_.reset( 350 ShillServiceClient::Create(client_type_override)); 351 shill_profile_client_.reset( 352 ShillProfileClient::Create(client_type_override)); 353 gsm_sms_client_.reset(GsmSMSClient::Create(client_type_override)); 354 image_burner_client_.reset(ImageBurnerClient::Create(client_type)); 355 introspectable_client_.reset(IntrospectableClient::Create(client_type)); 356 modem_messaging_client_.reset(ModemMessagingClient::Create(client_type)); 357 permission_broker_client_.reset( 358 PermissionBrokerClient::Create(client_type)); 359 power_manager_client_.reset( 360 PowerManagerClient::Create(client_type_override)); 361 session_manager_client_.reset(SessionManagerClient::Create(client_type)); 362 sms_client_.reset(SMSClient::Create(client_type)); 363 system_clock_client_.reset(SystemClockClient::Create(client_type)); 364 update_engine_client_.reset(UpdateEngineClient::Create(client_type)); 365 } 366 367 // Note: Keep this before other members so they can call AddObserver() in 368 // their c'tors. 369 ObserverList<DBusThreadManagerObserver> observers_; 370 371 scoped_ptr<base::Thread> dbus_thread_; 372 scoped_refptr<dbus::Bus> system_bus_; 373 scoped_refptr<dbus::Bus> ibus_bus_; 374 scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_; 375 scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_; 376 scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_; 377 scoped_ptr<BluetoothInputClient> bluetooth_input_client_; 378 scoped_ptr<BluetoothProfileManagerClient> bluetooth_profile_manager_client_; 379 scoped_ptr<CrasAudioClient> cras_audio_client_; 380 scoped_ptr<CrosDisksClient> cros_disks_client_; 381 scoped_ptr<CryptohomeClient> cryptohome_client_; 382 scoped_ptr<DebugDaemonClient> debug_daemon_client_; 383 scoped_ptr<ShillDeviceClient> shill_device_client_; 384 scoped_ptr<ShillIPConfigClient> shill_ipconfig_client_; 385 scoped_ptr<ShillManagerClient> shill_manager_client_; 386 scoped_ptr<ShillServiceClient> shill_service_client_; 387 scoped_ptr<ShillProfileClient> shill_profile_client_; 388 scoped_ptr<GsmSMSClient> gsm_sms_client_; 389 scoped_ptr<ImageBurnerClient> image_burner_client_; 390 scoped_ptr<IntrospectableClient> introspectable_client_; 391 scoped_ptr<ModemMessagingClient> modem_messaging_client_; 392 scoped_ptr<PermissionBrokerClient> permission_broker_client_; 393 scoped_ptr<SystemClockClient> system_clock_client_; 394 scoped_ptr<PowerManagerClient> power_manager_client_; 395 scoped_ptr<SessionManagerClient> session_manager_client_; 396 scoped_ptr<SMSClient> sms_client_; 397 scoped_ptr<UpdateEngineClient> update_engine_client_; 398 scoped_ptr<IBusClient> ibus_client_; 399 scoped_ptr<IBusEngineFactoryService> ibus_engine_factory_service_; 400 std::map<dbus::ObjectPath, IBusEngineService*> ibus_engine_services_; 401 scoped_ptr<PowerPolicyController> power_policy_controller_; 402 403 std::string ibus_address_; 404}; 405 406// static 407void DBusThreadManager::Initialize() { 408 // Ignore Initialize() if we set a test DBusThreadManager. 409 if (g_dbus_thread_manager_set_for_testing) 410 return; 411 // If we initialize DBusThreadManager twice we may also be shutting it down 412 // early; do not allow that. 413 CHECK(g_dbus_thread_manager == NULL); 414 // Determine whether we use stub or real client implementations. 415 DBusThreadManagerImpl* dbus_thread_manager_impl; 416 if (base::SysInfo::IsRunningOnChromeOS()) { 417 dbus_thread_manager_impl = 418 new DBusThreadManagerImpl(REAL_DBUS_CLIENT_IMPLEMENTATION); 419 VLOG(1) << "DBusThreadManager initialized for ChromeOS"; 420 } else { 421 dbus_thread_manager_impl = 422 new DBusThreadManagerImpl(STUB_DBUS_CLIENT_IMPLEMENTATION); 423 VLOG(1) << "DBusThreadManager initialized with Stub"; 424 } 425 g_dbus_thread_manager = dbus_thread_manager_impl; 426 dbus_thread_manager_impl->InitializeClients(); 427} 428 429// static 430void DBusThreadManager::InitializeForTesting( 431 DBusThreadManager* dbus_thread_manager) { 432 // If we initialize DBusThreadManager twice we may also be shutting it down 433 // early; do not allow that. 434 CHECK(g_dbus_thread_manager == NULL); 435 CHECK(dbus_thread_manager); 436 g_dbus_thread_manager = dbus_thread_manager; 437 g_dbus_thread_manager_set_for_testing = true; 438 VLOG(1) << "DBusThreadManager initialized with test implementation"; 439} 440 441// static 442void DBusThreadManager::InitializeWithStub() { 443 // If we initialize DBusThreadManager twice we may also be shutting it down 444 // early; do not allow that. 445 CHECK(g_dbus_thread_manager == NULL); 446 DBusThreadManagerImpl* dbus_thread_manager_impl = 447 new DBusThreadManagerImpl(STUB_DBUS_CLIENT_IMPLEMENTATION); 448 g_dbus_thread_manager = dbus_thread_manager_impl; 449 dbus_thread_manager_impl->InitializeClients(); 450 VLOG(1) << "DBusThreadManager initialized with stub implementation"; 451} 452 453// static 454bool DBusThreadManager::IsInitialized() { 455 return g_dbus_thread_manager != NULL; 456} 457 458// static 459void DBusThreadManager::Shutdown() { 460 // If we called InitializeForTesting, this may get called more than once. 461 // Ensure that we only shutdown DBusThreadManager once. 462 CHECK(g_dbus_thread_manager || g_dbus_thread_manager_set_for_testing); 463 DBusThreadManager* dbus_thread_manager = g_dbus_thread_manager; 464 g_dbus_thread_manager = NULL; 465 delete dbus_thread_manager; 466 VLOG(1) << "DBusThreadManager Shutdown completed"; 467} 468 469DBusThreadManager::DBusThreadManager() { 470 dbus::statistics::Initialize(); 471} 472 473DBusThreadManager::~DBusThreadManager() { 474 dbus::statistics::Shutdown(); 475 if (g_dbus_thread_manager == NULL) 476 return; // Called form Shutdown() or local test instance. 477 // There should never be both a global instance and a local instance. 478 CHECK(this == g_dbus_thread_manager); 479 if (g_dbus_thread_manager_set_for_testing) { 480 g_dbus_thread_manager = NULL; 481 g_dbus_thread_manager_set_for_testing = false; 482 VLOG(1) << "DBusThreadManager destroyed"; 483 } else { 484 LOG(FATAL) << "~DBusThreadManager() called outside of Shutdown()"; 485 } 486} 487 488// static 489DBusThreadManager* DBusThreadManager::Get() { 490 CHECK(g_dbus_thread_manager) 491 << "DBusThreadManager::Get() called before Initialize()"; 492 return g_dbus_thread_manager; 493} 494 495} // namespace chromeos 496