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