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