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 50 namespace chromeos { 51 52 static DBusThreadManager* g_dbus_thread_manager = NULL; 53 static bool g_dbus_thread_manager_set_for_testing = false; 54 55 // The DBusThreadManager implementation used in production. 56 class 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 // Construction order of the Stub implementations of the Shill clients 106 // matters; stub clients may only have construction dependencies on clients 107 // previously constructed. 108 shill_manager_client_.reset( 109 ShillManagerClient::Create(client_type_override_, system_bus_.get())); 110 shill_device_client_.reset( 111 ShillDeviceClient::Create(client_type_override_, system_bus_.get())); 112 shill_ipconfig_client_.reset( 113 ShillIPConfigClient::Create(client_type_override_, system_bus_.get())); 114 shill_service_client_.reset( 115 ShillServiceClient::Create(client_type_override_, system_bus_.get())); 116 shill_profile_client_.reset( 117 ShillProfileClient::Create(client_type_override_, system_bus_.get())); 118 gsm_sms_client_.reset( 119 GsmSMSClient::Create(client_type_override_, system_bus_.get())); 120 121 // If the Service client has a TestInterface, add the default services. 122 ShillServiceClient::TestInterface* service_client_test = 123 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); 124 if (service_client_test) 125 service_client_test->AddDefaultServices(); 126 127 image_burner_client_.reset(ImageBurnerClient::Create(client_type_, 128 system_bus_.get())); 129 introspectable_client_.reset( 130 IntrospectableClient::Create(client_type_, system_bus_.get())); 131 modem_messaging_client_.reset( 132 ModemMessagingClient::Create(client_type_, system_bus_.get())); 133 permission_broker_client_.reset( 134 PermissionBrokerClient::Create(client_type_, system_bus_.get())); 135 power_manager_client_.reset( 136 PowerManagerClient::Create(client_type_override_, system_bus_.get())); 137 session_manager_client_.reset( 138 SessionManagerClient::Create(client_type_, system_bus_.get())); 139 sms_client_.reset( 140 SMSClient::Create(client_type_, system_bus_.get())); 141 system_clock_client_.reset( 142 SystemClockClient::Create(client_type_, system_bus_.get())); 143 update_engine_client_.reset( 144 UpdateEngineClient::Create(client_type_, system_bus_.get())); 145 146 // PowerPolicyController is dependent on PowerManagerClient, so 147 // initialize it after the main list of clients. 148 power_policy_controller_.reset( 149 new PowerPolicyController(this, power_manager_client_.get())); 150 151 // This must be called after the list of clients so they've each had a 152 // chance to register with their object managers. 153 system_bus_->GetManagedObjects(); 154 } 155 156 virtual ~DBusThreadManagerImpl() { 157 FOR_EACH_OBSERVER(DBusThreadManagerObserver, observers_, 158 OnDBusThreadManagerDestroying(this)); 159 160 // Shut down the bus. During the browser shutdown, it's ok to shut down 161 // the bus synchronously. 162 system_bus_->ShutdownOnDBusThreadAndBlock(); 163 if (ibus_bus_.get()) 164 ibus_bus_->ShutdownOnDBusThreadAndBlock(); 165 166 // Release IBusEngineService instances. 167 for (std::map<dbus::ObjectPath, IBusEngineService*>::iterator it 168 = ibus_engine_services_.begin(); 169 it != ibus_engine_services_.end(); it++) { 170 delete it->second; 171 } 172 173 // Stop the D-Bus thread. 174 dbus_thread_->Stop(); 175 } 176 177 // DBusThreadManager override. 178 virtual void AddObserver(DBusThreadManagerObserver* observer) OVERRIDE { 179 DCHECK(observer); 180 observers_.AddObserver(observer); 181 } 182 183 // DBusThreadManager override. 184 virtual void RemoveObserver(DBusThreadManagerObserver* observer) OVERRIDE { 185 DCHECK(observer); 186 observers_.RemoveObserver(observer); 187 } 188 189 // DBusThreadManager override. 190 virtual void InitIBusBus( 191 const std::string &ibus_address, 192 const base::Closure& on_disconnected_callback) OVERRIDE { 193 DCHECK(!ibus_bus_.get()); 194 dbus::Bus::Options ibus_bus_options; 195 ibus_bus_options.bus_type = dbus::Bus::CUSTOM_ADDRESS; 196 ibus_bus_options.address = ibus_address; 197 ibus_bus_options.connection_type = dbus::Bus::PRIVATE; 198 ibus_bus_options.dbus_task_runner = dbus_thread_->message_loop_proxy(); 199 ibus_bus_options.disconnected_callback = on_disconnected_callback; 200 ibus_bus_ = new dbus::Bus(ibus_bus_options); 201 ibus_address_ = ibus_address; 202 VLOG(1) << "Connected to ibus-daemon: " << ibus_address; 203 204 DBusClientImplementationType client_type = 205 base::chromeos::IsRunningOnChromeOS() ? REAL_DBUS_CLIENT_IMPLEMENTATION 206 : STUB_DBUS_CLIENT_IMPLEMENTATION; 207 208 ibus_client_.reset( 209 IBusClient::Create(client_type, ibus_bus_.get())); 210 ibus_config_client_.reset( 211 IBusConfigClient::Create(client_type, ibus_bus_.get())); 212 ibus_input_context_client_.reset( 213 IBusInputContextClient::Create(client_type)); 214 ibus_engine_factory_service_.reset( 215 IBusEngineFactoryService::Create(ibus_bus_.get(), client_type)); 216 ibus_panel_service_.reset( 217 IBusPanelService::Create(client_type, 218 ibus_bus_.get(), 219 ibus_input_context_client_.get())); 220 221 ibus_engine_services_.clear(); 222 } 223 224 // DBusThreadManager overrides: 225 virtual dbus::Bus* GetSystemBus() OVERRIDE { 226 return system_bus_.get(); 227 } 228 229 virtual dbus::Bus* GetIBusBus() OVERRIDE { 230 return ibus_bus_.get(); 231 } 232 233 virtual BluetoothAdapterClient* GetBluetoothAdapterClient() OVERRIDE { 234 return bluetooth_adapter_client_.get(); 235 } 236 237 virtual BluetoothAgentManagerClient* GetBluetoothAgentManagerClient() 238 OVERRIDE { 239 return bluetooth_agent_manager_client_.get(); 240 } 241 242 virtual BluetoothDeviceClient* GetBluetoothDeviceClient() OVERRIDE { 243 return bluetooth_device_client_.get(); 244 } 245 246 virtual BluetoothInputClient* GetBluetoothInputClient() OVERRIDE { 247 return bluetooth_input_client_.get(); 248 } 249 250 virtual BluetoothProfileManagerClient* GetBluetoothProfileManagerClient() 251 OVERRIDE { 252 return bluetooth_profile_manager_client_.get(); 253 } 254 255 virtual CrasAudioClient* GetCrasAudioClient() OVERRIDE { 256 return cras_audio_client_.get(); 257 } 258 259 virtual CrosDisksClient* GetCrosDisksClient() OVERRIDE { 260 return cros_disks_client_.get(); 261 } 262 263 virtual CryptohomeClient* GetCryptohomeClient() OVERRIDE { 264 return cryptohome_client_.get(); 265 } 266 267 virtual DebugDaemonClient* GetDebugDaemonClient() OVERRIDE { 268 return debug_daemon_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 ShillServiceClient* GetShillServiceClient() OVERRIDE { 284 return shill_service_client_.get(); 285 } 286 287 virtual ShillProfileClient* GetShillProfileClient() OVERRIDE { 288 return shill_profile_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<BluetoothAdapterClient> bluetooth_adapter_client_; 391 scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_; 392 scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_; 393 scoped_ptr<BluetoothInputClient> bluetooth_input_client_; 394 scoped_ptr<BluetoothProfileManagerClient> bluetooth_profile_manager_client_; 395 scoped_ptr<CrasAudioClient> cras_audio_client_; 396 scoped_ptr<CrosDisksClient> cros_disks_client_; 397 scoped_ptr<CryptohomeClient> cryptohome_client_; 398 scoped_ptr<DebugDaemonClient> debug_daemon_client_; 399 scoped_ptr<ShillDeviceClient> shill_device_client_; 400 scoped_ptr<ShillIPConfigClient> shill_ipconfig_client_; 401 scoped_ptr<ShillManagerClient> shill_manager_client_; 402 scoped_ptr<ShillServiceClient> shill_service_client_; 403 scoped_ptr<ShillProfileClient> shill_profile_client_; 404 scoped_ptr<GsmSMSClient> gsm_sms_client_; 405 scoped_ptr<ImageBurnerClient> image_burner_client_; 406 scoped_ptr<IntrospectableClient> introspectable_client_; 407 scoped_ptr<ModemMessagingClient> modem_messaging_client_; 408 scoped_ptr<PermissionBrokerClient> permission_broker_client_; 409 scoped_ptr<SystemClockClient> system_clock_client_; 410 scoped_ptr<PowerManagerClient> power_manager_client_; 411 scoped_ptr<SessionManagerClient> session_manager_client_; 412 scoped_ptr<SMSClient> sms_client_; 413 scoped_ptr<UpdateEngineClient> update_engine_client_; 414 scoped_ptr<IBusClient> ibus_client_; 415 scoped_ptr<IBusConfigClient> ibus_config_client_; 416 scoped_ptr<IBusInputContextClient> ibus_input_context_client_; 417 scoped_ptr<IBusEngineFactoryService> ibus_engine_factory_service_; 418 std::map<dbus::ObjectPath, IBusEngineService*> ibus_engine_services_; 419 scoped_ptr<IBusPanelService> ibus_panel_service_; 420 scoped_ptr<PowerPolicyController> power_policy_controller_; 421 422 std::string ibus_address_; 423 }; 424 425 // static 426 void DBusThreadManager::Initialize() { 427 // Ignore Initialize() if we set a test DBusThreadManager. 428 if (g_dbus_thread_manager_set_for_testing) 429 return; 430 // If we initialize DBusThreadManager twice we may also be shutting it down 431 // early; do not allow that. 432 CHECK(g_dbus_thread_manager == NULL); 433 // Determine whether we use stub or real client implementations. 434 DBusThreadManagerImpl* dbus_thread_manager_impl; 435 if (base::chromeos::IsRunningOnChromeOS()) { 436 dbus_thread_manager_impl = 437 new DBusThreadManagerImpl(REAL_DBUS_CLIENT_IMPLEMENTATION); 438 VLOG(1) << "DBusThreadManager initialized for ChromeOS"; 439 } else { 440 dbus_thread_manager_impl = 441 new DBusThreadManagerImpl(STUB_DBUS_CLIENT_IMPLEMENTATION); 442 VLOG(1) << "DBusThreadManager initialized with Stub"; 443 } 444 g_dbus_thread_manager = dbus_thread_manager_impl; 445 dbus_thread_manager_impl->InitializeClients(); 446 } 447 448 // static 449 void DBusThreadManager::InitializeForTesting( 450 DBusThreadManager* dbus_thread_manager) { 451 // If we initialize DBusThreadManager twice we may also be shutting it down 452 // early; do not allow that. 453 CHECK(g_dbus_thread_manager == NULL); 454 CHECK(dbus_thread_manager); 455 g_dbus_thread_manager = dbus_thread_manager; 456 g_dbus_thread_manager_set_for_testing = true; 457 VLOG(1) << "DBusThreadManager initialized with test implementation"; 458 } 459 460 // static 461 void DBusThreadManager::InitializeWithStub() { 462 // If we initialize DBusThreadManager twice we may also be shutting it down 463 // early; do not allow that. 464 CHECK(g_dbus_thread_manager == NULL); 465 DBusThreadManagerImpl* dbus_thread_manager_impl = 466 new DBusThreadManagerImpl(STUB_DBUS_CLIENT_IMPLEMENTATION); 467 g_dbus_thread_manager = dbus_thread_manager_impl; 468 dbus_thread_manager_impl->InitializeClients(); 469 VLOG(1) << "DBusThreadManager initialized with stub implementation"; 470 } 471 472 // static 473 bool DBusThreadManager::IsInitialized() { 474 return g_dbus_thread_manager != NULL; 475 } 476 477 // static 478 void DBusThreadManager::Shutdown() { 479 // If we called InitializeForTesting, this may get called more than once. 480 // Ensure that we only shutdown DBusThreadManager once. 481 CHECK(g_dbus_thread_manager || g_dbus_thread_manager_set_for_testing); 482 DBusThreadManager* dbus_thread_manager = g_dbus_thread_manager; 483 g_dbus_thread_manager = NULL; 484 delete dbus_thread_manager; 485 VLOG(1) << "DBusThreadManager Shutdown completed"; 486 } 487 488 DBusThreadManager::DBusThreadManager() { 489 dbus::statistics::Initialize(); 490 } 491 492 DBusThreadManager::~DBusThreadManager() { 493 dbus::statistics::Shutdown(); 494 if (g_dbus_thread_manager == NULL) 495 return; // Called form Shutdown() or local test instance. 496 // There should never be both a global instance and a local instance. 497 CHECK(this == g_dbus_thread_manager); 498 if (g_dbus_thread_manager_set_for_testing) { 499 g_dbus_thread_manager = NULL; 500 g_dbus_thread_manager_set_for_testing = false; 501 VLOG(1) << "DBusThreadManager destroyed"; 502 } else { 503 LOG(FATAL) << "~DBusThreadManager() called outside of Shutdown()"; 504 } 505 } 506 507 // static 508 DBusThreadManager* DBusThreadManager::Get() { 509 CHECK(g_dbus_thread_manager) 510 << "DBusThreadManager::Get() called before Initialize()"; 511 return g_dbus_thread_manager; 512 } 513 514 } // namespace chromeos 515