dbus_thread_manager.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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/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/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 = base::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 bluetooth_adapter_client_.reset( 87 BluetoothAdapterClient::Create(client_type_, system_bus_.get())); 88 bluetooth_agent_manager_client_.reset( 89 BluetoothAgentManagerClient::Create(client_type_, system_bus_.get())); 90 bluetooth_device_client_.reset( 91 BluetoothDeviceClient::Create(client_type_, system_bus_.get())); 92 bluetooth_input_client_.reset( 93 BluetoothInputClient::Create(client_type_, system_bus_.get())); 94 bluetooth_profile_manager_client_.reset( 95 BluetoothProfileManagerClient::Create(client_type_, system_bus_.get())); 96 cras_audio_client_.reset(CrasAudioClient::Create( 97 client_type_, system_bus_.get())); 98 cros_disks_client_.reset( 99 CrosDisksClient::Create(client_type_, system_bus_.get())); 100 cryptohome_client_.reset( 101 CryptohomeClient::Create(client_type_, system_bus_.get())); 102 debug_daemon_client_.reset( 103 DebugDaemonClient::Create(client_type_, system_bus_.get())); 104 105 shill_manager_client_.reset( 106 ShillManagerClient::Create(client_type_override_, system_bus_.get())); 107 shill_device_client_.reset( 108 ShillDeviceClient::Create(client_type_override_, system_bus_.get())); 109 shill_ipconfig_client_.reset( 110 ShillIPConfigClient::Create(client_type_override_, system_bus_.get())); 111 shill_profile_client_.reset( 112 ShillProfileClient::Create(client_type_override_, system_bus_.get())); 113 shill_service_client_.reset( 114 ShillServiceClient::Create(client_type_override_, system_bus_.get())); 115 gsm_sms_client_.reset( 116 GsmSMSClient::Create(client_type_override_, system_bus_.get())); 117 118 image_burner_client_.reset(ImageBurnerClient::Create(client_type_, 119 system_bus_.get())); 120 introspectable_client_.reset( 121 IntrospectableClient::Create(client_type_, system_bus_.get())); 122 modem_messaging_client_.reset( 123 ModemMessagingClient::Create(client_type_, system_bus_.get())); 124 permission_broker_client_.reset( 125 PermissionBrokerClient::Create(client_type_, system_bus_.get())); 126 power_manager_client_.reset( 127 PowerManagerClient::Create(client_type_override_, system_bus_.get())); 128 session_manager_client_.reset( 129 SessionManagerClient::Create(client_type_, system_bus_.get())); 130 sms_client_.reset( 131 SMSClient::Create(client_type_, system_bus_.get())); 132 system_clock_client_.reset( 133 SystemClockClient::Create(client_type_, system_bus_.get())); 134 update_engine_client_.reset( 135 UpdateEngineClient::Create(client_type_, system_bus_.get())); 136 137 // PowerPolicyController is dependent on PowerManagerClient, so 138 // initialize it after the main list of clients. 139 power_policy_controller_.reset( 140 new PowerPolicyController(this, power_manager_client_.get())); 141 142 // This must be called after the list of clients so they've each had a 143 // chance to register with their object managers. 144 system_bus_->GetManagedObjects(); 145 } 146 147 virtual ~DBusThreadManagerImpl() { 148 FOR_EACH_OBSERVER(DBusThreadManagerObserver, observers_, 149 OnDBusThreadManagerDestroying(this)); 150 151 // Shut down the bus. During the browser shutdown, it's ok to shut down 152 // the bus synchronously. 153 system_bus_->ShutdownOnDBusThreadAndBlock(); 154 if (ibus_bus_.get()) 155 ibus_bus_->ShutdownOnDBusThreadAndBlock(); 156 157 // Release IBusEngineService instances. 158 for (std::map<dbus::ObjectPath, IBusEngineService*>::iterator it 159 = ibus_engine_services_.begin(); 160 it != ibus_engine_services_.end(); it++) { 161 delete it->second; 162 } 163 164 // Stop the D-Bus thread. 165 dbus_thread_->Stop(); 166 } 167 168 // DBusThreadManager override. 169 virtual void AddObserver(DBusThreadManagerObserver* observer) OVERRIDE { 170 DCHECK(observer); 171 observers_.AddObserver(observer); 172 } 173 174 // DBusThreadManager override. 175 virtual void RemoveObserver(DBusThreadManagerObserver* observer) OVERRIDE { 176 DCHECK(observer); 177 observers_.RemoveObserver(observer); 178 } 179 180 // DBusThreadManager override. 181 virtual void InitIBusBus( 182 const std::string &ibus_address, 183 const base::Closure& on_disconnected_callback) OVERRIDE { 184 DCHECK(!ibus_bus_.get()); 185 dbus::Bus::Options ibus_bus_options; 186 ibus_bus_options.bus_type = dbus::Bus::CUSTOM_ADDRESS; 187 ibus_bus_options.address = ibus_address; 188 ibus_bus_options.connection_type = dbus::Bus::PRIVATE; 189 ibus_bus_options.dbus_task_runner = dbus_thread_->message_loop_proxy(); 190 ibus_bus_options.disconnected_callback = on_disconnected_callback; 191 ibus_bus_ = new dbus::Bus(ibus_bus_options); 192 ibus_address_ = ibus_address; 193 VLOG(1) << "Connected to ibus-daemon: " << ibus_address; 194 195 DBusClientImplementationType client_type = 196 base::chromeos::IsRunningOnChromeOS() ? REAL_DBUS_CLIENT_IMPLEMENTATION 197 : STUB_DBUS_CLIENT_IMPLEMENTATION; 198 199 ibus_client_.reset( 200 IBusClient::Create(client_type, ibus_bus_.get())); 201 ibus_config_client_.reset( 202 IBusConfigClient::Create(client_type, ibus_bus_.get())); 203 ibus_input_context_client_.reset( 204 IBusInputContextClient::Create(client_type)); 205 ibus_engine_factory_service_.reset( 206 IBusEngineFactoryService::Create(ibus_bus_.get(), client_type)); 207 ibus_panel_service_.reset( 208 IBusPanelService::Create(client_type, 209 ibus_bus_.get(), 210 ibus_input_context_client_.get())); 211 212 ibus_engine_services_.clear(); 213 } 214 215 // DBusThreadManager overrides: 216 virtual dbus::Bus* GetSystemBus() OVERRIDE { 217 return system_bus_.get(); 218 } 219 220 virtual dbus::Bus* GetIBusBus() OVERRIDE { 221 return ibus_bus_.get(); 222 } 223 224 virtual BluetoothAdapterClient* GetBluetoothAdapterClient() OVERRIDE { 225 return bluetooth_adapter_client_.get(); 226 } 227 228 virtual BluetoothAgentManagerClient* GetBluetoothAgentManagerClient() 229 OVERRIDE { 230 return bluetooth_agent_manager_client_.get(); 231 } 232 233 virtual BluetoothDeviceClient* GetBluetoothDeviceClient() OVERRIDE { 234 return bluetooth_device_client_.get(); 235 } 236 237 virtual BluetoothInputClient* GetBluetoothInputClient() OVERRIDE { 238 return bluetooth_input_client_.get(); 239 } 240 241 virtual BluetoothProfileManagerClient* GetBluetoothProfileManagerClient() 242 OVERRIDE { 243 return bluetooth_profile_manager_client_.get(); 244 } 245 246 virtual CrasAudioClient* GetCrasAudioClient() OVERRIDE { 247 return cras_audio_client_.get(); 248 } 249 250 virtual CrosDisksClient* GetCrosDisksClient() OVERRIDE { 251 return cros_disks_client_.get(); 252 } 253 254 virtual CryptohomeClient* GetCryptohomeClient() OVERRIDE { 255 return cryptohome_client_.get(); 256 } 257 258 virtual DebugDaemonClient* GetDebugDaemonClient() OVERRIDE { 259 return debug_daemon_client_.get(); 260 } 261 262 virtual ShillDeviceClient* GetShillDeviceClient() OVERRIDE { 263 return shill_device_client_.get(); 264 } 265 266 virtual ShillIPConfigClient* GetShillIPConfigClient() OVERRIDE { 267 return shill_ipconfig_client_.get(); 268 } 269 270 virtual ShillManagerClient* GetShillManagerClient() OVERRIDE { 271 return shill_manager_client_.get(); 272 } 273 274 virtual ShillProfileClient* GetShillProfileClient() OVERRIDE { 275 return shill_profile_client_.get(); 276 } 277 278 virtual ShillServiceClient* GetShillServiceClient() OVERRIDE { 279 return shill_service_client_.get(); 280 } 281 282 virtual GsmSMSClient* GetGsmSMSClient() OVERRIDE { 283 return gsm_sms_client_.get(); 284 } 285 286 virtual ImageBurnerClient* GetImageBurnerClient() OVERRIDE { 287 return image_burner_client_.get(); 288 } 289 290 virtual IntrospectableClient* GetIntrospectableClient() OVERRIDE { 291 return introspectable_client_.get(); 292 } 293 294 virtual ModemMessagingClient* GetModemMessagingClient() OVERRIDE { 295 return modem_messaging_client_.get(); 296 } 297 298 virtual PermissionBrokerClient* GetPermissionBrokerClient() OVERRIDE { 299 return permission_broker_client_.get(); 300 } 301 302 virtual PowerManagerClient* GetPowerManagerClient() OVERRIDE { 303 return power_manager_client_.get(); 304 } 305 306 virtual PowerPolicyController* GetPowerPolicyController() OVERRIDE { 307 return power_policy_controller_.get(); 308 } 309 310 virtual SessionManagerClient* GetSessionManagerClient() OVERRIDE { 311 return session_manager_client_.get(); 312 } 313 314 virtual SMSClient* GetSMSClient() OVERRIDE { 315 return sms_client_.get(); 316 } 317 318 virtual SystemClockClient* GetSystemClockClient() OVERRIDE { 319 return system_clock_client_.get(); 320 } 321 322 virtual UpdateEngineClient* GetUpdateEngineClient() OVERRIDE { 323 return update_engine_client_.get(); 324 } 325 326 virtual IBusClient* GetIBusClient() OVERRIDE { 327 return ibus_client_.get(); 328 } 329 330 virtual IBusConfigClient* GetIBusConfigClient() OVERRIDE { 331 return ibus_config_client_.get(); 332 } 333 334 virtual IBusInputContextClient* GetIBusInputContextClient() OVERRIDE { 335 return ibus_input_context_client_.get(); 336 } 337 338 virtual IBusEngineFactoryService* GetIBusEngineFactoryService() OVERRIDE { 339 return ibus_engine_factory_service_.get(); 340 } 341 342 virtual IBusEngineService* GetIBusEngineService( 343 const dbus::ObjectPath& object_path) OVERRIDE { 344 const DBusClientImplementationType client_type = 345 base::chromeos::IsRunningOnChromeOS() ? REAL_DBUS_CLIENT_IMPLEMENTATION 346 : STUB_DBUS_CLIENT_IMPLEMENTATION; 347 348 if (ibus_engine_services_.find(object_path) 349 == ibus_engine_services_.end()) { 350 ibus_engine_services_[object_path] = 351 IBusEngineService::Create(client_type, ibus_bus_.get(), object_path); 352 } 353 return ibus_engine_services_[object_path]; 354 } 355 356 virtual void RemoveIBusEngineService( 357 const dbus::ObjectPath& object_path) OVERRIDE { 358 if (ibus_engine_services_.find(object_path) != 359 ibus_engine_services_.end()) { 360 LOG(WARNING) << "Object path not found: " << object_path.value(); 361 return; 362 } 363 delete ibus_engine_services_[object_path]; 364 ibus_engine_services_.erase(object_path); 365 } 366 367 virtual IBusPanelService* GetIBusPanelService() OVERRIDE { 368 return ibus_panel_service_.get(); 369 } 370 371 DBusClientImplementationType client_type_; 372 DBusClientImplementationType client_type_override_; 373 374 // Note: Keep this before other members so they can call AddObserver() in 375 // their c'tors. 376 ObserverList<DBusThreadManagerObserver> observers_; 377 378 scoped_ptr<base::Thread> dbus_thread_; 379 scoped_refptr<dbus::Bus> system_bus_; 380 scoped_refptr<dbus::Bus> ibus_bus_; 381 scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_; 382 scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_; 383 scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_; 384 scoped_ptr<BluetoothInputClient> bluetooth_input_client_; 385 scoped_ptr<BluetoothProfileManagerClient> bluetooth_profile_manager_client_; 386 scoped_ptr<CrasAudioClient> cras_audio_client_; 387 scoped_ptr<CrosDisksClient> cros_disks_client_; 388 scoped_ptr<CryptohomeClient> cryptohome_client_; 389 scoped_ptr<DebugDaemonClient> debug_daemon_client_; 390 scoped_ptr<ShillDeviceClient> shill_device_client_; 391 scoped_ptr<ShillIPConfigClient> shill_ipconfig_client_; 392 scoped_ptr<ShillManagerClient> shill_manager_client_; 393 scoped_ptr<ShillProfileClient> shill_profile_client_; 394 scoped_ptr<ShillServiceClient> shill_service_client_; 395 scoped_ptr<GsmSMSClient> gsm_sms_client_; 396 scoped_ptr<ImageBurnerClient> image_burner_client_; 397 scoped_ptr<IntrospectableClient> introspectable_client_; 398 scoped_ptr<ModemMessagingClient> modem_messaging_client_; 399 scoped_ptr<PermissionBrokerClient> permission_broker_client_; 400 scoped_ptr<SystemClockClient> system_clock_client_; 401 scoped_ptr<PowerManagerClient> power_manager_client_; 402 scoped_ptr<SessionManagerClient> session_manager_client_; 403 scoped_ptr<SMSClient> sms_client_; 404 scoped_ptr<UpdateEngineClient> update_engine_client_; 405 scoped_ptr<IBusClient> ibus_client_; 406 scoped_ptr<IBusConfigClient> ibus_config_client_; 407 scoped_ptr<IBusInputContextClient> ibus_input_context_client_; 408 scoped_ptr<IBusEngineFactoryService> ibus_engine_factory_service_; 409 std::map<dbus::ObjectPath, IBusEngineService*> ibus_engine_services_; 410 scoped_ptr<IBusPanelService> ibus_panel_service_; 411 scoped_ptr<PowerPolicyController> power_policy_controller_; 412 413 std::string ibus_address_; 414}; 415 416// static 417void DBusThreadManager::Initialize() { 418 // Ignore Initialize() if we set a test DBusThreadManager. 419 if (g_dbus_thread_manager_set_for_testing) 420 return; 421 // If we initialize DBusThreadManager twice we may also be shutting it down 422 // early; do not allow that. 423 CHECK(g_dbus_thread_manager == NULL); 424 // Determine whether we use stub or real client implementations. 425 DBusThreadManagerImpl* dbus_thread_manager_impl; 426 if (base::chromeos::IsRunningOnChromeOS()) { 427 dbus_thread_manager_impl = 428 new DBusThreadManagerImpl(REAL_DBUS_CLIENT_IMPLEMENTATION); 429 VLOG(1) << "DBusThreadManager initialized for ChromeOS"; 430 } else { 431 dbus_thread_manager_impl = 432 new DBusThreadManagerImpl(STUB_DBUS_CLIENT_IMPLEMENTATION); 433 VLOG(1) << "DBusThreadManager initialized with Stub"; 434 } 435 g_dbus_thread_manager = dbus_thread_manager_impl; 436 dbus_thread_manager_impl->InitializeClients(); 437} 438 439// static 440void DBusThreadManager::InitializeForTesting( 441 DBusThreadManager* dbus_thread_manager) { 442 // If we initialize DBusThreadManager twice we may also be shutting it down 443 // early; do not allow that. 444 CHECK(g_dbus_thread_manager == NULL); 445 CHECK(dbus_thread_manager); 446 g_dbus_thread_manager = dbus_thread_manager; 447 g_dbus_thread_manager_set_for_testing = true; 448 VLOG(1) << "DBusThreadManager initialized with test implementation"; 449} 450 451// static 452void DBusThreadManager::InitializeWithStub() { 453 // If we initialize DBusThreadManager twice we may also be shutting it down 454 // early; do not allow that. 455 CHECK(g_dbus_thread_manager == NULL); 456 DBusThreadManagerImpl* dbus_thread_manager_impl = 457 new DBusThreadManagerImpl(STUB_DBUS_CLIENT_IMPLEMENTATION); 458 g_dbus_thread_manager = dbus_thread_manager_impl; 459 dbus_thread_manager_impl->InitializeClients(); 460 VLOG(1) << "DBusThreadManager initialized with stub implementation"; 461} 462 463// static 464bool DBusThreadManager::IsInitialized() { 465 return g_dbus_thread_manager != NULL; 466} 467 468// static 469void DBusThreadManager::Shutdown() { 470 // If we called InitializeForTesting, this may get called more than once. 471 // Ensure that we only shutdown DBusThreadManager once. 472 CHECK(g_dbus_thread_manager || g_dbus_thread_manager_set_for_testing); 473 DBusThreadManager* dbus_thread_manager = g_dbus_thread_manager; 474 g_dbus_thread_manager = NULL; 475 delete dbus_thread_manager; 476 VLOG(1) << "DBusThreadManager Shutdown completed"; 477} 478 479DBusThreadManager::DBusThreadManager() { 480 dbus::statistics::Initialize(); 481} 482 483DBusThreadManager::~DBusThreadManager() { 484 dbus::statistics::Shutdown(); 485 if (g_dbus_thread_manager == NULL) 486 return; // Called form Shutdown() or local test instance. 487 // There should never be both a global instance and a local instance. 488 CHECK(this == g_dbus_thread_manager); 489 if (g_dbus_thread_manager_set_for_testing) { 490 g_dbus_thread_manager = NULL; 491 g_dbus_thread_manager_set_for_testing = false; 492 VLOG(1) << "DBusThreadManager destroyed"; 493 } else { 494 LOG(FATAL) << "~DBusThreadManager() called outside of Shutdown()"; 495 } 496} 497 498// static 499DBusThreadManager* DBusThreadManager::Get() { 500 CHECK(g_dbus_thread_manager) 501 << "DBusThreadManager::Get() called before Initialize()"; 502 return g_dbus_thread_manager; 503} 504 505} // namespace chromeos 506