Home | History | Annotate | Download | only in dbus
      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