blob: c5b5c43b2113151802b455825b4014188ba2f39a [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/dbus/dbus_thread_manager.h"
#include <utility>
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/system/sys_info.h"
#include "base/threading/thread.h"
#include "chromeos/dbus/arc_midis_client.h"
#include "chromeos/dbus/arc_obb_mounter_client.h"
#include "chromeos/dbus/arc_oemcrypto_client.h"
#include "chromeos/dbus/cec_service_client.h"
#include "chromeos/dbus/cicerone_client.h"
#include "chromeos/dbus/concierge_client.h"
#include "chromeos/dbus/constants/dbus_switches.h"
#include "chromeos/dbus/cros_disks_client.h"
#include "chromeos/dbus/dbus_client.h"
#include "chromeos/dbus/dbus_clients_browser.h"
#include "chromeos/dbus/debug_daemon_client.h"
#include "chromeos/dbus/easy_unlock_client.h"
#include "chromeos/dbus/image_burner_client.h"
#include "chromeos/dbus/image_loader_client.h"
#include "chromeos/dbus/lorgnette_manager_client.h"
#include "chromeos/dbus/runtime_probe_client.h"
#include "chromeos/dbus/seneschal_client.h"
#include "chromeos/dbus/shill/modem_messaging_client.h"
#include "chromeos/dbus/shill/shill_clients.h"
#include "chromeos/dbus/shill/shill_device_client.h"
#include "chromeos/dbus/shill/shill_ipconfig_client.h"
#include "chromeos/dbus/shill/shill_manager_client.h"
#include "chromeos/dbus/shill/shill_profile_client.h"
#include "chromeos/dbus/shill/shill_service_client.h"
#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
#include "chromeos/dbus/shill/sms_client.h"
#include "chromeos/dbus/smb_provider_client.h"
#include "chromeos/dbus/update_engine_client.h"
#include "dbus/bus.h"
#include "dbus/dbus_statistics.h"
namespace chromeos {
static DBusThreadManager* g_dbus_thread_manager = nullptr;
static bool g_using_dbus_thread_manager_for_testing = false;
DBusThreadManager::DBusThreadManager(ClientSet client_set,
bool use_real_clients)
: use_real_clients_(use_real_clients) {
if (client_set == DBusThreadManager::kAll)
clients_browser_.reset(new DBusClientsBrowser(use_real_clients));
// NOTE: When there are clients only used by ash, create them here.
dbus::statistics::Initialize();
if (use_real_clients) {
// Create the D-Bus thread.
base::Thread::Options thread_options;
thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
dbus_thread_.reset(new base::Thread("D-Bus thread"));
dbus_thread_->StartWithOptions(thread_options);
// Create the connection to the system bus.
dbus::Bus::Options system_bus_options;
system_bus_options.bus_type = dbus::Bus::SYSTEM;
system_bus_options.connection_type = dbus::Bus::PRIVATE;
system_bus_options.dbus_task_runner = dbus_thread_->task_runner();
system_bus_ = new dbus::Bus(system_bus_options);
}
}
DBusThreadManager::~DBusThreadManager() {
// Delete all D-Bus clients before shutting down the system bus.
clients_browser_.reset();
// Shut down the bus. During the browser shutdown, it's ok to shut down
// the bus synchronously.
if (system_bus_.get())
system_bus_->ShutdownOnDBusThreadAndBlock();
// Stop the D-Bus thread.
if (dbus_thread_)
dbus_thread_->Stop();
dbus::statistics::Shutdown();
if (!g_dbus_thread_manager)
return; // Called form Shutdown() or local test instance.
// There should never be both a global instance and a local instance.
CHECK_EQ(this, g_dbus_thread_manager);
if (g_using_dbus_thread_manager_for_testing) {
g_dbus_thread_manager = nullptr;
g_using_dbus_thread_manager_for_testing = false;
VLOG(1) << "DBusThreadManager destroyed";
} else {
LOG(FATAL) << "~DBusThreadManager() called outside of Shutdown()";
}
}
dbus::Bus* DBusThreadManager::GetSystemBus() {
return system_bus_.get();
}
ArcAppfuseProviderClient* DBusThreadManager::GetArcAppfuseProviderClient() {
return clients_browser_ ? clients_browser_->arc_appfuse_provider_client_.get()
: nullptr;
}
ArcMidisClient* DBusThreadManager::GetArcMidisClient() {
return clients_browser_ ? clients_browser_->arc_midis_client_.get() : nullptr;
}
ArcObbMounterClient* DBusThreadManager::GetArcObbMounterClient() {
return clients_browser_ ? clients_browser_->arc_obb_mounter_client_.get()
: nullptr;
}
ArcOemCryptoClient* DBusThreadManager::GetArcOemCryptoClient() {
return clients_browser_ ? clients_browser_->arc_oemcrypto_client_.get()
: nullptr;
}
CecServiceClient* DBusThreadManager::GetCecServiceClient() {
return clients_browser_ ? clients_browser_->cec_service_client_.get()
: nullptr;
}
CiceroneClient* DBusThreadManager::GetCiceroneClient() {
return clients_browser_ ? clients_browser_->cicerone_client_.get() : nullptr;
}
ConciergeClient* DBusThreadManager::GetConciergeClient() {
return clients_browser_ ? clients_browser_->concierge_client_.get() : nullptr;
}
CrosDisksClient* DBusThreadManager::GetCrosDisksClient() {
return clients_browser_ ? clients_browser_->cros_disks_client_.get()
: nullptr;
}
DebugDaemonClient* DBusThreadManager::GetDebugDaemonClient() {
return clients_browser_ ? clients_browser_->debug_daemon_client_.get()
: nullptr;
}
EasyUnlockClient* DBusThreadManager::GetEasyUnlockClient() {
return clients_browser_ ? clients_browser_->easy_unlock_client_.get()
: nullptr;
}
ShillDeviceClient* DBusThreadManager::GetShillDeviceClient() {
return ShillDeviceClient::Get();
}
ShillIPConfigClient* DBusThreadManager::GetShillIPConfigClient() {
return ShillIPConfigClient::Get();
}
ShillManagerClient* DBusThreadManager::GetShillManagerClient() {
return ShillManagerClient::Get();
}
ShillServiceClient* DBusThreadManager::GetShillServiceClient() {
return ShillServiceClient::Get();
}
ShillProfileClient* DBusThreadManager::GetShillProfileClient() {
return ShillProfileClient::Get();
}
ShillThirdPartyVpnDriverClient*
DBusThreadManager::GetShillThirdPartyVpnDriverClient() {
return ShillThirdPartyVpnDriverClient::Get();
}
ImageBurnerClient* DBusThreadManager::GetImageBurnerClient() {
return clients_browser_ ? clients_browser_->image_burner_client_.get()
: nullptr;
}
ImageLoaderClient* DBusThreadManager::GetImageLoaderClient() {
return clients_browser_ ? clients_browser_->image_loader_client_.get()
: nullptr;
}
LorgnetteManagerClient* DBusThreadManager::GetLorgnetteManagerClient() {
return clients_browser_ ? clients_browser_->lorgnette_manager_client_.get()
: nullptr;
}
ModemMessagingClient* DBusThreadManager::GetModemMessagingClient() {
return ModemMessagingClient::Get();
}
OobeConfigurationClient* DBusThreadManager::GetOobeConfigurationClient() {
return clients_browser_->oobe_configuration_client_.get();
}
RuntimeProbeClient* DBusThreadManager::GetRuntimeProbeClient() {
return clients_browser_ ? clients_browser_->runtime_probe_client_.get()
: nullptr;
}
SeneschalClient* DBusThreadManager::GetSeneschalClient() {
return clients_browser_ ? clients_browser_->seneschal_client_.get() : nullptr;
}
SmbProviderClient* DBusThreadManager::GetSmbProviderClient() {
return clients_browser_ ? clients_browser_->smb_provider_client_.get()
: nullptr;
}
SMSClient* DBusThreadManager::GetSMSClient() {
return SMSClient::Get();
}
UpdateEngineClient* DBusThreadManager::GetUpdateEngineClient() {
return clients_browser_ ? clients_browser_->update_engine_client_.get()
: nullptr;
}
VirtualFileProviderClient* DBusThreadManager::GetVirtualFileProviderClient() {
return clients_browser_
? clients_browser_->virtual_file_provider_client_.get()
: nullptr;
}
WilcoDtcSupportdClient* DBusThreadManager::GetWilcoDtcSupportdClient() {
return clients_browser_ ? clients_browser_->wilco_dtc_supportd_client_.get()
: nullptr;
}
VmPluginDispatcherClient* DBusThreadManager::GetVmPluginDispatcherClient() {
return clients_browser_ ? clients_browser_->vm_plugin_dispatcher_client.get()
: nullptr;
}
void DBusThreadManager::InitializeClients() {
// Some clients call DBusThreadManager::Get() during initialization.
DCHECK(g_dbus_thread_manager);
// TODO(stevenjb): Move these to dbus_helper.cc in src/chrome and any tests
// that require Shill clients. https://crbug.com/948390.
shill_clients::Initialize(GetSystemBus());
if (clients_browser_)
clients_browser_->Initialize(GetSystemBus());
if (use_real_clients_)
VLOG(1) << "DBusThreadManager initialized for Chrome OS";
else
VLOG(1) << "DBusThreadManager created for testing";
}
bool DBusThreadManager::IsUsingFakes() {
return !use_real_clients_;
}
// static
void DBusThreadManager::Initialize(ClientSet client_set) {
// If we initialize DBusThreadManager twice we may also be shutting it down
// early; do not allow that.
if (g_using_dbus_thread_manager_for_testing)
return;
CHECK(!g_dbus_thread_manager);
#if defined(USE_REAL_DBUS_CLIENTS)
bool use_real_clients = true;
#else
// TODO(hashimoto): Always use fakes after adding
// use_real_dbus_clients=true to where needed. crbug.com/952745
bool use_real_clients = base::SysInfo::IsRunningOnChromeOS() &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kDbusStub);
#endif
g_dbus_thread_manager = new DBusThreadManager(client_set, use_real_clients);
g_dbus_thread_manager->InitializeClients();
}
// static
void DBusThreadManager::Initialize() {
Initialize(kAll);
}
// static
std::unique_ptr<DBusThreadManagerSetter>
DBusThreadManager::GetSetterForTesting() {
if (!g_using_dbus_thread_manager_for_testing) {
g_using_dbus_thread_manager_for_testing = true;
CHECK(!g_dbus_thread_manager);
// TODO(jamescook): Don't initialize clients as a side-effect of using a
// test API. For now, assume the caller wants all clients.
g_dbus_thread_manager =
new DBusThreadManager(kAll, false /* use_real_clients */);
g_dbus_thread_manager->InitializeClients();
}
return base::WrapUnique(new DBusThreadManagerSetter());
}
// static
bool DBusThreadManager::IsInitialized() {
return !!g_dbus_thread_manager;
}
// static
void DBusThreadManager::Shutdown() {
// Ensure that we only shutdown DBusThreadManager once.
CHECK(g_dbus_thread_manager);
// TODO(stevenjb): Remove. https://crbug.com/948390.
shill_clients::Shutdown();
DBusThreadManager* dbus_thread_manager = g_dbus_thread_manager;
g_dbus_thread_manager = nullptr;
g_using_dbus_thread_manager_for_testing = false;
delete dbus_thread_manager;
VLOG(1) << "DBusThreadManager Shutdown completed";
}
// static
DBusThreadManager* DBusThreadManager::Get() {
CHECK(g_dbus_thread_manager)
<< "DBusThreadManager::Get() called before Initialize()";
return g_dbus_thread_manager;
}
DBusThreadManagerSetter::DBusThreadManagerSetter() = default;
DBusThreadManagerSetter::~DBusThreadManagerSetter() = default;
void DBusThreadManagerSetter::SetCiceroneClient(
std::unique_ptr<CiceroneClient> client) {
DBusThreadManager::Get()->clients_browser_->cicerone_client_ =
std::move(client);
}
void DBusThreadManagerSetter::SetConciergeClient(
std::unique_ptr<ConciergeClient> client) {
DBusThreadManager::Get()->clients_browser_->concierge_client_ =
std::move(client);
}
void DBusThreadManagerSetter::SetCrosDisksClient(
std::unique_ptr<CrosDisksClient> client) {
DBusThreadManager::Get()->clients_browser_->cros_disks_client_ =
std::move(client);
}
void DBusThreadManagerSetter::SetDebugDaemonClient(
std::unique_ptr<DebugDaemonClient> client) {
DBusThreadManager::Get()->clients_browser_->debug_daemon_client_ =
std::move(client);
}
void DBusThreadManagerSetter::SetRuntimeProbeClient(
std::unique_ptr<RuntimeProbeClient> client) {
DBusThreadManager::Get()->clients_browser_->runtime_probe_client_ =
std::move(client);
}
void DBusThreadManagerSetter::SetSeneschalClient(
std::unique_ptr<SeneschalClient> client) {
DBusThreadManager::Get()->clients_browser_->seneschal_client_ =
std::move(client);
}
void DBusThreadManagerSetter::SetImageBurnerClient(
std::unique_ptr<ImageBurnerClient> client) {
DBusThreadManager::Get()->clients_browser_->image_burner_client_ =
std::move(client);
}
void DBusThreadManagerSetter::SetImageLoaderClient(
std::unique_ptr<ImageLoaderClient> client) {
DBusThreadManager::Get()->clients_browser_->image_loader_client_ =
std::move(client);
}
void DBusThreadManagerSetter::SetSmbProviderClient(
std::unique_ptr<SmbProviderClient> client) {
DBusThreadManager::Get()->clients_browser_->smb_provider_client_ =
std::move(client);
}
void DBusThreadManagerSetter::SetUpdateEngineClient(
std::unique_ptr<UpdateEngineClient> client) {
DBusThreadManager::Get()->clients_browser_->update_engine_client_ =
std::move(client);
}
} // namespace chromeos