// 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 "extensions/browser/api/bluetooth/bluetooth_event_router.h"

#include <map>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/contains.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/device_event_log/device_event_log.h"
#include "content/public/browser/browser_thread.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
#include "extensions/browser/api/bluetooth/bluetooth_api_pairing_delegate.h"
#include "extensions/browser/api/bluetooth/bluetooth_api_utils.h"
#include "extensions/browser/api/bluetooth/bluetooth_private_api.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_host.h"
#include "extensions/common/api/bluetooth.h"
#include "extensions/common/api/bluetooth_private.h"

namespace extensions {

namespace {

constexpr char kScanClientName[] = "Chrome Extension";

void IgnoreAdapterResult(scoped_refptr<device::BluetoothAdapter> adapter) {}

void IgnoreAdapterResultAndThen(
    base::OnceClosure callback,
    scoped_refptr<device::BluetoothAdapter> adapter) {
  std::move(callback).Run();
}

std::string GetListenerId(const extensions::EventListenerInfo& details) {
  return !details.extension_id.empty() ? details.extension_id
                                       : details.listener_url.host();
}

}  // namespace

namespace bluetooth = api::bluetooth;
namespace bt_private = api::bluetooth_private;

BluetoothEventRouter::BluetoothEventRouter(content::BrowserContext* context)
    : browser_context_(context), adapter_(nullptr) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  BLUETOOTH_LOG(USER) << "BluetoothEventRouter()";
  DCHECK(browser_context_);
  extension_registry_observation_.Observe(
      ExtensionRegistry::Get(browser_context_));
  extension_host_registry_observation_.Observe(
      ExtensionHostRegistry::Get(browser_context_));
}

BluetoothEventRouter::~BluetoothEventRouter() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  BLUETOOTH_LOG(USER) << "~BluetoothEventRouter()";
  if (adapter_.get()) {
    adapter_->RemoveObserver(this);
    adapter_ = nullptr;
  }
  CleanUpAllExtensions();
}

bool BluetoothEventRouter::IsBluetoothSupported() const {
  return device::BluetoothAdapterFactory::IsBluetoothSupported();
}

void BluetoothEventRouter::GetAdapter(
    device::BluetoothAdapterFactory::AdapterCallback callback) {
  if (adapter_.get()) {
    std::move(callback).Run(adapter_);
    return;
  }

  // Note: On ChromeOS this will return an adapter that also supports Bluetooth
  // Low Energy.
  device::BluetoothAdapterFactory::Get()->GetClassicAdapter(
      base::BindOnce(&BluetoothEventRouter::OnAdapterInitialized,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void BluetoothEventRouter::StartDiscoverySession(
    device::BluetoothAdapter* adapter,
    const std::string& extension_id,
    base::OnceClosure callback,
    base::OnceClosure error_callback) {
  if (!adapter_.get() && IsBluetoothSupported()) {
    // If |adapter_| isn't set yet, call GetAdapter() which will synchronously
    // invoke the callback (StartDiscoverySessionImpl).
    GetAdapter(base::BindOnce(
        &IgnoreAdapterResultAndThen,
        base::BindOnce(&BluetoothEventRouter::StartDiscoverySessionImpl,
                       weak_ptr_factory_.GetWeakPtr(),
                       base::RetainedRef(adapter), extension_id,
                       std::move(callback), std::move(error_callback))));
    return;
  }
  StartDiscoverySessionImpl(adapter, extension_id, std::move(callback),
                            std::move(error_callback));
}

void BluetoothEventRouter::StartDiscoverySessionImpl(
    device::BluetoothAdapter* adapter,
    const std::string& extension_id,
    base::OnceClosure callback,
    base::OnceClosure error_callback) {
  if (!adapter_.get()) {
    BLUETOOTH_LOG(ERROR) << "Unable to get Bluetooth adapter.";
    std::move(error_callback).Run();
    return;
  }
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(ERROR) << "Bluetooth adapter mismatch.";
    std::move(error_callback).Run();
    return;
  }
  auto iter = discovery_session_map_.find(extension_id);
  if (iter != discovery_session_map_.end() && iter->second->IsActive()) {
    BLUETOOTH_LOG(DEBUG) << "An active discovery session exists for extension: "
                         << extension_id;
    std::move(error_callback).Run();
    return;
  }

  BLUETOOTH_LOG(USER) << "StartDiscoverySession: " << extension_id;

  // Check whether user pre set discovery filter by calling SetDiscoveryFilter
  // before. If the user has set a discovery filter then start a filtered
  // discovery session, otherwise start a regular session
  auto pre_set_iter = pre_set_filter_map_.find(extension_id);
  if (pre_set_iter != pre_set_filter_map_.end()) {
    adapter->StartDiscoverySessionWithFilter(
        std::unique_ptr<device::BluetoothDiscoveryFilter>(pre_set_iter->second),
        kScanClientName,
        base::BindOnce(&BluetoothEventRouter::OnStartDiscoverySession,
                       weak_ptr_factory_.GetWeakPtr(), extension_id,
                       std::move(callback)),
        std::move(error_callback));
    pre_set_filter_map_.erase(pre_set_iter);
    return;
  }
  adapter->StartDiscoverySession(
      kScanClientName,
      base::BindOnce(&BluetoothEventRouter::OnStartDiscoverySession,
                     weak_ptr_factory_.GetWeakPtr(), extension_id,
                     std::move(callback)),
      std::move(error_callback));
}

void BluetoothEventRouter::StopDiscoverySession(
    device::BluetoothAdapter* adapter,
    const std::string& extension_id,
    base::OnceClosure callback,
    base::OnceClosure error_callback) {
  if (adapter != adapter_.get()) {
    std::move(error_callback).Run();
    return;
  }
  auto iter = discovery_session_map_.find(extension_id);
  if (iter == discovery_session_map_.end() || !iter->second->IsActive()) {
    BLUETOOTH_LOG(DEBUG) << "No active discovery session exists for extension.";
    std::move(error_callback).Run();
    return;
  }
  BLUETOOTH_LOG(USER) << "StopDiscoverySession: " << extension_id;
  device::BluetoothDiscoverySession* session = iter->second;
  session->Stop();
  std::move(callback).Run();
}

void BluetoothEventRouter::SetDiscoveryFilter(
    std::unique_ptr<device::BluetoothDiscoveryFilter> discovery_filter,
    device::BluetoothAdapter* adapter,
    const std::string& extension_id,
    base::OnceClosure callback,
    base::OnceClosure error_callback) {
  BLUETOOTH_LOG(USER) << "SetDiscoveryFilter";
  if (!adapter_.get()) {
    BLUETOOTH_LOG(ERROR) << "Unable to get Bluetooth adapter.";
    std::move(error_callback).Run();
    return;
  }
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(ERROR) << "Bluetooth adapter mismatch.";
    std::move(error_callback).Run();
    return;
  }

  auto iter = discovery_session_map_.find(extension_id);
  if (iter == discovery_session_map_.end() || !iter->second->IsActive()) {
    BLUETOOTH_LOG(DEBUG) << "No active discovery session exists for extension, "
                         << "so caching filter for later use.";
    pre_set_filter_map_[extension_id] = discovery_filter.release();
    std::move(callback).Run();
    return;
  }

  // If the session has already started simply start a new one. The callback
  // will automatically delete the old session and put the new session (with its
  // new filter) in as this extension's session
  adapter->StartDiscoverySessionWithFilter(
      std::move(discovery_filter), kScanClientName,
      base::BindOnce(&BluetoothEventRouter::OnStartDiscoverySession,
                     weak_ptr_factory_.GetWeakPtr(), extension_id,
                     std::move(callback)),
      std::move(error_callback));
}

BluetoothApiPairingDelegate* BluetoothEventRouter::GetPairingDelegate(
    const std::string& extension_id) {
  return base::Contains(pairing_delegate_map_, extension_id)
             ? pairing_delegate_map_[extension_id]
             : nullptr;
}

void BluetoothEventRouter::OnAdapterInitialized(
    device::BluetoothAdapterFactory::AdapterCallback callback,
    scoped_refptr<device::BluetoothAdapter> adapter) {
  if (!adapter_.get()) {
    adapter_ = adapter;
    adapter_->AddObserver(this);
  }

  std::move(callback).Run(adapter);
}

void BluetoothEventRouter::MaybeReleaseAdapter() {
  if (adapter_.get() && event_listener_count_.empty() &&
      pairing_delegate_map_.empty()) {
    BLUETOOTH_LOG(EVENT) << "Releasing Adapter.";
    adapter_->RemoveObserver(this);
    adapter_ = nullptr;
  }
}

void BluetoothEventRouter::AddPairingDelegate(const std::string& extension_id) {
  if (!adapter_.get() && IsBluetoothSupported()) {
    GetAdapter(base::BindOnce(
        &IgnoreAdapterResultAndThen,
        base::BindOnce(&BluetoothEventRouter::AddPairingDelegateImpl,
                       weak_ptr_factory_.GetWeakPtr(), extension_id)));
    return;
  }
  AddPairingDelegateImpl(extension_id);
}

void BluetoothEventRouter::AddPairingDelegateImpl(
    const std::string& extension_id) {
  if (!adapter_.get()) {
    LOG(ERROR) << "Unable to get adapter for extension_id: " << extension_id;
    return;
  }

  if (base::Contains(pairing_delegate_map_, extension_id)) {
    // For WebUI there may be more than one page open to the same url
    // (e.g. chrome://settings). These will share the same pairing delegate.
    BLUETOOTH_LOG(EVENT) << "Pairing delegate already exists for extension_id: "
                         << extension_id;
    return;
  }
  BluetoothApiPairingDelegate* delegate =
      new BluetoothApiPairingDelegate(browser_context_);
  DCHECK(adapter_.get());
  adapter_->AddPairingDelegate(
      delegate, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
  pairing_delegate_map_[extension_id] = delegate;
}

void BluetoothEventRouter::RemovePairingDelegate(
    const std::string& extension_id) {
  if (base::Contains(pairing_delegate_map_, extension_id)) {
    BluetoothApiPairingDelegate* delegate = pairing_delegate_map_[extension_id];
    if (adapter_.get())
      adapter_->RemovePairingDelegate(delegate);
    pairing_delegate_map_.erase(extension_id);
    delete delegate;
    MaybeReleaseAdapter();
  }
}

void BluetoothEventRouter::AdapterPresentChanged(
    device::BluetoothAdapter* adapter,
    bool present) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(DEBUG) << "Ignoring event for adapter "
                         << adapter->GetAddress();
    return;
  }
  DispatchAdapterStateEvent();
}

void BluetoothEventRouter::AdapterPoweredChanged(
    device::BluetoothAdapter* adapter,
    bool has_power) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(DEBUG) << "Ignoring event for adapter "
                         << adapter->GetAddress();
    return;
  }
  DispatchAdapterStateEvent();
}

void BluetoothEventRouter::AdapterDiscoveringChanged(
    device::BluetoothAdapter* adapter,
    bool discovering) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(DEBUG) << "Ignoring event for adapter "
                         << adapter->GetAddress();
    return;
  }

  if (!discovering) {
    // If any discovery sessions are inactive, clean them up.
    DiscoverySessionMap active_session_map;
    for (auto iter = discovery_session_map_.begin();
         iter != discovery_session_map_.end(); ++iter) {
      device::BluetoothDiscoverySession* session = iter->second;
      if (session->IsActive()) {
        active_session_map[iter->first] = session;
        continue;
      }
      delete session;
    }
    discovery_session_map_.swap(active_session_map);
  }

  DispatchAdapterStateEvent();

  // Release the adapter after dispatching the event.
  if (!discovering) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(&BluetoothEventRouter::MaybeReleaseAdapter,
                                  weak_ptr_factory_.GetWeakPtr()));
  }
}

void BluetoothEventRouter::DeviceAdded(device::BluetoothAdapter* adapter,
                                       device::BluetoothDevice* device) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(DEBUG) << "Ignoring event for adapter "
                         << adapter->GetAddress();
    return;
  }

  DispatchDeviceEvent(events::BLUETOOTH_ON_DEVICE_ADDED,
                      bluetooth::OnDeviceAdded::kEventName, device);
}

void BluetoothEventRouter::DeviceChanged(device::BluetoothAdapter* adapter,
                                         device::BluetoothDevice* device) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(DEBUG) << "Ignoring event for adapter "
                         << adapter->GetAddress();
    return;
  }

  DispatchDeviceEvent(events::BLUETOOTH_ON_DEVICE_CHANGED,
                      bluetooth::OnDeviceChanged::kEventName, device);
}

void BluetoothEventRouter::DeviceRemoved(device::BluetoothAdapter* adapter,
                                         device::BluetoothDevice* device) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(DEBUG) << "Ignoring event for adapter "
                         << adapter->GetAddress();
    return;
  }

  DispatchDeviceEvent(events::BLUETOOTH_ON_DEVICE_REMOVED,
                      bluetooth::OnDeviceRemoved::kEventName, device);
}

void BluetoothEventRouter::DeviceAddressChanged(
    device::BluetoothAdapter* adapter,
    device::BluetoothDevice* device,
    const std::string& old_address) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(DEBUG) << "Ignoring event for adapter "
                         << adapter->GetAddress();
    return;
  }
  DCHECK(device);

  bluetooth::Device extension_device;
  bluetooth::BluetoothDeviceToApiDevice(*device, &extension_device);

  auto args =
      bt_private::OnDeviceAddressChanged::Create(extension_device, old_address);
  auto event = std::make_unique<Event>(
      events::BLUETOOTH_PRIVATE_ON_DEVICE_ADDRESS_CHANGED,
      bt_private::OnDeviceAddressChanged::kEventName, std::move(args));
  EventRouter::Get(browser_context_)->BroadcastEvent(std::move(event));
}

void BluetoothEventRouter::OnListenerAdded(const EventListenerInfo& details) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  std::string id = GetListenerId(details);
  int count = ++event_listener_count_[id];
  BLUETOOTH_LOG(EVENT) << "Event Listener Added: " << id << " Count: " << count;
  if (!adapter_.get())
    GetAdapter(base::BindOnce(&IgnoreAdapterResult));
}

void BluetoothEventRouter::OnListenerRemoved(const EventListenerInfo& details) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  std::string id = GetListenerId(details);
  auto iter = event_listener_count_.find(id);
  CHECK(iter != event_listener_count_.end());
  int count = --(iter->second);
  BLUETOOTH_LOG(EVENT) << "Event Listener Removed: " << id
                       << " Count: " << count;
  if (count == 0) {
    event_listener_count_.erase(iter);
    // When all listeners for a listener id have been removed, remove any
    // pairing delegate or discovery session and filters.
    CleanUpForExtension(id);
  }
  MaybeReleaseAdapter();
}

void BluetoothEventRouter::DispatchAdapterStateEvent() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  api::bluetooth::AdapterState state;
  CHECK(adapter_.get());
  PopulateAdapterState(*adapter_, &state);

  auto args = bluetooth::OnAdapterStateChanged::Create(state);
  std::unique_ptr<Event> event(
      new Event(events::BLUETOOTH_ON_ADAPTER_STATE_CHANGED,
                bluetooth::OnAdapterStateChanged::kEventName, std::move(args)));
  EventRouter::Get(browser_context_)->BroadcastEvent(std::move(event));
}

void BluetoothEventRouter::DispatchDeviceEvent(
    events::HistogramValue histogram_value,
    const std::string& event_name,
    device::BluetoothDevice* device) {
  bluetooth::Device extension_device;
  CHECK(device);
  bluetooth::BluetoothDeviceToApiDevice(*device, &extension_device);

  auto args = bluetooth::OnDeviceAdded::Create(extension_device);
  std::unique_ptr<Event> event(
      new Event(histogram_value, event_name, std::move(args)));
  EventRouter::Get(browser_context_)->BroadcastEvent(std::move(event));
}

void BluetoothEventRouter::CleanUpForExtension(
    const std::string& extension_id) {
  BLUETOOTH_LOG(DEBUG) << "CleanUpForExtension: " << extension_id;
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  RemovePairingDelegate(extension_id);

  auto pre_set_iter = pre_set_filter_map_.find(extension_id);
  if (pre_set_iter != pre_set_filter_map_.end()) {
    delete pre_set_iter->second;
    pre_set_filter_map_.erase(pre_set_iter);
  }

  // Remove any discovery session initiated by the extension.
  auto session_iter = discovery_session_map_.find(extension_id);
  if (session_iter == discovery_session_map_.end())
    return;

  // discovery_session_map.erase() should happen before
  // delete session_iter->second, because deleting the
  // BluetoothDiscoverySession object may trigger a chain reaction
  // (see http://crbug.com/711484#c9) which will modify
  // discovery_session_map_ itself.
  device::BluetoothDiscoverySession* discovery_session = session_iter->second;
  discovery_session_map_.erase(session_iter);
  delete discovery_session;
}

void BluetoothEventRouter::CleanUpAllExtensions() {
  BLUETOOTH_LOG(DEBUG) << "CleanUpAllExtensions";

  for (auto& it : pre_set_filter_map_)
    delete it.second;
  pre_set_filter_map_.clear();

  for (auto& it : discovery_session_map_) {
    BLUETOOTH_LOG(DEBUG) << "Clean up Discovery Session: " << it.first;
    delete it.second;
  }
  discovery_session_map_.clear();

  auto pairing_iter = pairing_delegate_map_.begin();
  while (pairing_iter != pairing_delegate_map_.end())
    RemovePairingDelegate(pairing_iter++->first);
}

void BluetoothEventRouter::OnStartDiscoverySession(
    const std::string& extension_id,
    base::OnceClosure callback,
    std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
  BLUETOOTH_LOG(EVENT) << "OnStartDiscoverySession: " << extension_id;
  // Clean up any existing session instance for the extension.
  auto iter = discovery_session_map_.find(extension_id);
  if (iter != discovery_session_map_.end())
    delete iter->second;
  discovery_session_map_[extension_id] = discovery_session.release();
  std::move(callback).Run();
}

void BluetoothEventRouter::OnExtensionHostDestroyed(
    content::BrowserContext* browser_context,
    ExtensionHost* host) {
  // The BluetoothEventRouter has its own context in incognito, so check
  // the context.
  if (browser_context != browser_context_)
    return;

  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  BLUETOOTH_LOG(DEBUG) << "Host Destroyed: " << host->extension_id();
  CleanUpForExtension(host->extension_id());
}

void BluetoothEventRouter::OnExtensionUnloaded(
    content::BrowserContext* browser_context,
    const Extension* extension,
    UnloadedExtensionReason reason) {
  CleanUpForExtension(extension->id());
}

}  // namespace extensions
