// 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_pump_type.h"
#include "base/system/sys_info.h"
#include "base/threading/thread.h"
#include "chromeos/dbus/arc_keymaster_client.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/debug_daemon_client.h"
#include "chromeos/dbus/easy_unlock_client.h"
#include "chromeos/dbus/gnubby_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_pump_type = base::MessagePumpType::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;
}

ArcKeymasterClient* DBusThreadManager::GetArcKeymasterClient() {
  return clients_browser_ ? clients_browser_->arc_keymaster_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;
}

GnubbyClient* DBusThreadManager::GetGnubbyClient() {
  return clients_browser_ ? clients_browser_->gnubby_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::SetGnubbyClient(
    std::unique_ptr<GnubbyClient> client) {
  DBusThreadManager::Get()->clients_browser_->gnubby_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
