// 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/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/stl_util.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/notification_details.h"
#include "content/public/browser/notification_source.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/browser/extension_registry.h"
#include "extensions/browser/notification_types.h"
#include "extensions/common/api/bluetooth.h"
#include "extensions/common/api/bluetooth_private.h"

namespace extensions {

namespace {

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

void IgnoreAdapterResultAndThen(
    const base::Closure& callback,
    scoped_refptr<device::BluetoothAdapter> adapter) {
  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),
      extension_registry_observer_(this),
      weak_ptr_factory_(this) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  BLUETOOTH_LOG(USER) << "BluetoothEventRouter()";
  DCHECK(browser_context_);
  registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
                 content::Source<content::BrowserContext>(browser_context_));
  extension_registry_observer_.Add(ExtensionRegistry::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(
    const device::BluetoothAdapterFactory::AdapterCallback& callback) {
  if (adapter_.get()) {
    callback.Run(scoped_refptr<device::BluetoothAdapter>(adapter_));
    return;
  }

  device::BluetoothAdapterFactory::GetAdapter(
      base::Bind(&BluetoothEventRouter::OnAdapterInitialized,
                 weak_ptr_factory_.GetWeakPtr(), callback));
}

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

void BluetoothEventRouter::StartDiscoverySessionImpl(
    device::BluetoothAdapter* adapter,
    const std::string& extension_id,
    const base::Closure& callback,
    const base::Closure& error_callback) {
  if (!adapter_.get()) {
    BLUETOOTH_LOG(ERROR) << "Unable to get Bluetooth adapter.";
    error_callback.Run();
    return;
  }
  if (adapter != adapter_.get()) {
    BLUETOOTH_LOG(ERROR) << "Bluetooth adapter mismatch.";
    error_callback.Run();
    return;
  }
  DiscoverySessionMap::iterator 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;
    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
  PreSetFilterMap::iterator 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),
        base::Bind(&BluetoothEventRouter::OnStartDiscoverySession,
                   weak_ptr_factory_.GetWeakPtr(), extension_id, callback),
        error_callback);
    pre_set_filter_map_.erase(pre_set_iter);
    return;
  }
  adapter->StartDiscoverySession(
      base::Bind(&BluetoothEventRouter::OnStartDiscoverySession,
                 weak_ptr_factory_.GetWeakPtr(), extension_id, callback),
      error_callback);
}

void BluetoothEventRouter::StopDiscoverySession(
    device::BluetoothAdapter* adapter,
    const std::string& extension_id,
    const base::Closure& callback,
    const base::Closure& error_callback) {
  if (adapter != adapter_.get()) {
    error_callback.Run();
    return;
  }
  DiscoverySessionMap::iterator 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.";
    error_callback.Run();
    return;
  }
  BLUETOOTH_LOG(USER) << "StopDiscoverySession: " << extension_id;
  device::BluetoothDiscoverySession* session = iter->second;
  session->Stop(callback, error_callback);
}

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

  DiscoverySessionMap::iterator 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();
    callback.Run();
    return;
  }

  // extension is already running discovery, update it's discovery filter
  iter->second->SetDiscoveryFilter(std::move(discovery_filter), callback,
                                   error_callback);
}

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

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

  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::Bind(&IgnoreAdapterResultAndThen,
                   base::Bind(&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::ContainsKey(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::ContainsKey(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 (DiscoverySessionMap::iterator 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::Bind(&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::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::Bind(&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);

  std::unique_ptr<base::ListValue> 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);

  std::unique_ptr<base::ListValue> 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);

  PreSetFilterMap::iterator 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.
  DiscoverySessionMap::iterator 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();

  PairingDelegateMap::iterator 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,
    const base::Closure& callback,
    std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
  BLUETOOTH_LOG(EVENT) << "OnStartDiscoverySession: " << extension_id;
  // Clean up any existing session instance for the extension.
  DiscoverySessionMap::iterator iter =
      discovery_session_map_.find(extension_id);
  if (iter != discovery_session_map_.end())
    delete iter->second;
  discovery_session_map_[extension_id] = discovery_session.release();
  callback.Run();
}

void BluetoothEventRouter::OnSetDiscoveryFilter(const std::string& extension_id,
                                                const base::Closure& callback) {
  BLUETOOTH_LOG(DEBUG) << "Successfully set DiscoveryFilter.";
  callback.Run();
}

void BluetoothEventRouter::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, type);
  ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
  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
