Home | History | Annotate | Download | only in bluetooth
      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 "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h"
      6 
      7 #include <map>
      8 #include <string>
      9 
     10 #include "base/bind.h"
     11 #include "base/json/json_writer.h"
     12 #include "base/logging.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/memory/scoped_vector.h"
     15 #include "base/strings/utf_string_conversions.h"
     16 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_utils.h"
     17 #include "chrome/browser/extensions/event_names.h"
     18 #include "chrome/browser/extensions/event_router.h"
     19 #include "chrome/browser/extensions/extension_system.h"
     20 #include "chrome/common/extensions/api/bluetooth.h"
     21 #include "device/bluetooth/bluetooth_adapter.h"
     22 #include "device/bluetooth/bluetooth_adapter_factory.h"
     23 #include "device/bluetooth/bluetooth_device.h"
     24 #include "device/bluetooth/bluetooth_profile.h"
     25 #include "device/bluetooth/bluetooth_socket.h"
     26 
     27 namespace extensions {
     28 
     29 ExtensionBluetoothEventRouter::ExtensionBluetoothEventRouter(Profile* profile)
     30     : send_discovery_events_(false),
     31       responsible_for_discovery_(false),
     32       profile_(profile),
     33       adapter_(NULL),
     34       num_event_listeners_(0),
     35       next_socket_id_(1),
     36       weak_ptr_factory_(this) {
     37   DCHECK(profile_);
     38 }
     39 
     40 ExtensionBluetoothEventRouter::~ExtensionBluetoothEventRouter() {
     41   if (adapter_.get()) {
     42     adapter_->RemoveObserver(this);
     43     adapter_ = NULL;
     44   }
     45   DLOG_IF(WARNING, socket_map_.size() != 0)
     46       << "Bluetooth sockets are still open.";
     47   socket_map_.clear();
     48 
     49   for (BluetoothProfileMap::iterator iter = bluetooth_profile_map_.begin();
     50        iter != bluetooth_profile_map_.end();
     51        ++iter) {
     52     iter->second->Unregister();
     53   }
     54 }
     55 
     56 bool ExtensionBluetoothEventRouter::IsBluetoothSupported() const {
     57   return adapter_.get() ||
     58          device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
     59 }
     60 
     61 void ExtensionBluetoothEventRouter::GetAdapter(
     62     const device::BluetoothAdapterFactory::AdapterCallback& callback) {
     63   if (adapter_.get()) {
     64     callback.Run(scoped_refptr<device::BluetoothAdapter>(adapter_));
     65     return;
     66   }
     67 
     68   device::BluetoothAdapterFactory::GetAdapter(callback);
     69 }
     70 
     71 void ExtensionBluetoothEventRouter::OnListenerAdded() {
     72   num_event_listeners_++;
     73   InitializeAdapterIfNeeded();
     74 }
     75 
     76 void ExtensionBluetoothEventRouter::OnListenerRemoved() {
     77   if (num_event_listeners_ > 0)
     78     num_event_listeners_--;
     79   MaybeReleaseAdapter();
     80 }
     81 
     82 int ExtensionBluetoothEventRouter::RegisterSocket(
     83     scoped_refptr<device::BluetoothSocket> socket) {
     84   // If there is a socket registered with the same fd, just return it's id
     85   for (SocketMap::const_iterator i = socket_map_.begin();
     86       i != socket_map_.end(); ++i) {
     87     if (i->second.get() == socket.get())
     88       return i->first;
     89   }
     90   int return_id = next_socket_id_++;
     91   socket_map_[return_id] = socket;
     92   return return_id;
     93 }
     94 
     95 bool ExtensionBluetoothEventRouter::ReleaseSocket(int id) {
     96   SocketMap::iterator socket_entry = socket_map_.find(id);
     97   if (socket_entry == socket_map_.end())
     98     return false;
     99   socket_map_.erase(socket_entry);
    100   return true;
    101 }
    102 
    103 void ExtensionBluetoothEventRouter::AddProfile(
    104     const std::string& uuid,
    105     device::BluetoothProfile* bluetooth_profile) {
    106   DCHECK(!HasProfile(uuid));
    107   bluetooth_profile_map_[uuid] = bluetooth_profile;
    108 }
    109 
    110 void ExtensionBluetoothEventRouter::RemoveProfile(const std::string& uuid) {
    111   BluetoothProfileMap::iterator iter = bluetooth_profile_map_.find(uuid);
    112   if (iter != bluetooth_profile_map_.end()) {
    113     device::BluetoothProfile* bluetooth_profile = iter->second;
    114     bluetooth_profile_map_.erase(iter);
    115     bluetooth_profile->Unregister();
    116   }
    117 }
    118 
    119 bool ExtensionBluetoothEventRouter::HasProfile(const std::string& uuid) const {
    120   return bluetooth_profile_map_.find(uuid) != bluetooth_profile_map_.end();
    121 }
    122 
    123 device::BluetoothProfile* ExtensionBluetoothEventRouter::GetProfile(
    124     const std::string& uuid) const {
    125   BluetoothProfileMap::const_iterator iter = bluetooth_profile_map_.find(uuid);
    126   if (iter != bluetooth_profile_map_.end())
    127     return iter->second;
    128 
    129   return NULL;
    130 }
    131 
    132 scoped_refptr<device::BluetoothSocket>
    133 ExtensionBluetoothEventRouter::GetSocket(int id) {
    134   SocketMap::iterator socket_entry = socket_map_.find(id);
    135   if (socket_entry == socket_map_.end())
    136     return NULL;
    137   return socket_entry->second;
    138 }
    139 
    140 void ExtensionBluetoothEventRouter::SetResponsibleForDiscovery(
    141     bool responsible) {
    142   responsible_for_discovery_ = responsible;
    143 }
    144 
    145 bool ExtensionBluetoothEventRouter::IsResponsibleForDiscovery() const {
    146   return responsible_for_discovery_;
    147 }
    148 
    149 void ExtensionBluetoothEventRouter::SetSendDiscoveryEvents(bool should_send) {
    150   // At the transition into sending devices, also send past devices that
    151   // were discovered as they will not be discovered again.
    152   if (should_send && !send_discovery_events_) {
    153     for (DeviceList::const_iterator i = discovered_devices_.begin();
    154         i != discovered_devices_.end(); ++i) {
    155       DispatchDeviceEvent(extensions::event_names::kBluetoothOnDeviceDiscovered,
    156                           **i);
    157     }
    158   }
    159 
    160   send_discovery_events_ = should_send;
    161 }
    162 
    163 void ExtensionBluetoothEventRouter::DispatchDeviceEvent(
    164     const char* event_name, const extensions::api::bluetooth::Device& device) {
    165   scoped_ptr<base::ListValue> args(new base::ListValue());
    166   args->Append(device.ToValue().release());
    167   scoped_ptr<Event> event(new Event(event_name, args.Pass()));
    168   ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass());
    169 }
    170 
    171 void ExtensionBluetoothEventRouter::DispatchConnectionEvent(
    172     const std::string& extension_id,
    173     const std::string& uuid,
    174     const device::BluetoothDevice* device,
    175     scoped_refptr<device::BluetoothSocket> socket) {
    176   if (!HasProfile(uuid))
    177     return;
    178 
    179   int socket_id = RegisterSocket(socket);
    180   api::bluetooth::Socket result_socket;
    181   api::bluetooth::BluetoothDeviceToApiDevice(*device, &result_socket.device);
    182   result_socket.profile.uuid = uuid;
    183   result_socket.id = socket_id;
    184 
    185   scoped_ptr<base::ListValue> args(new base::ListValue());
    186   args->Append(result_socket.ToValue().release());
    187   scoped_ptr<Event> event(new Event(
    188       extensions::event_names::kBluetoothOnConnection, args.Pass()));
    189   ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension(
    190       extension_id, event.Pass());
    191 }
    192 
    193 void ExtensionBluetoothEventRouter::AdapterPresentChanged(
    194     device::BluetoothAdapter* adapter, bool present) {
    195   if (adapter != adapter_.get()) {
    196     DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress();
    197     return;
    198   }
    199   DispatchAdapterStateEvent();
    200 }
    201 
    202 void ExtensionBluetoothEventRouter::AdapterPoweredChanged(
    203     device::BluetoothAdapter* adapter, bool has_power) {
    204   if (adapter != adapter_.get()) {
    205     DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress();
    206     return;
    207   }
    208   DispatchAdapterStateEvent();
    209 }
    210 
    211 void ExtensionBluetoothEventRouter::AdapterDiscoveringChanged(
    212     device::BluetoothAdapter* adapter, bool discovering) {
    213   if (adapter != adapter_.get()) {
    214     DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress();
    215     return;
    216   }
    217 
    218   if (!discovering) {
    219     send_discovery_events_ = false;
    220     responsible_for_discovery_ = false;
    221     discovered_devices_.clear();
    222   }
    223 
    224   DispatchAdapterStateEvent();
    225 }
    226 
    227 void ExtensionBluetoothEventRouter::DeviceAdded(
    228     device::BluetoothAdapter* adapter,
    229     device::BluetoothDevice* device) {
    230   if (adapter != adapter_.get()) {
    231     DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress();
    232     return;
    233   }
    234 
    235   extensions::api::bluetooth::Device* extension_device =
    236       new extensions::api::bluetooth::Device();
    237   extensions::api::bluetooth::BluetoothDeviceToApiDevice(
    238       *device, extension_device);
    239   discovered_devices_.push_back(extension_device);
    240 
    241   if (!send_discovery_events_)
    242     return;
    243 
    244   DispatchDeviceEvent(extensions::event_names::kBluetoothOnDeviceDiscovered,
    245                       *extension_device);
    246 }
    247 
    248 void ExtensionBluetoothEventRouter::InitializeAdapterIfNeeded() {
    249   if (!adapter_.get()) {
    250     GetAdapter(base::Bind(&ExtensionBluetoothEventRouter::InitializeAdapter,
    251                           weak_ptr_factory_.GetWeakPtr()));
    252   }
    253 }
    254 
    255 void ExtensionBluetoothEventRouter::InitializeAdapter(
    256     scoped_refptr<device::BluetoothAdapter> adapter) {
    257   if (!adapter_.get()) {
    258     adapter_ = adapter;
    259     adapter_->AddObserver(this);
    260   }
    261 }
    262 
    263 void ExtensionBluetoothEventRouter::MaybeReleaseAdapter() {
    264   if (adapter_.get() && num_event_listeners_ == 0) {
    265     adapter_->RemoveObserver(this);
    266     adapter_ = NULL;
    267   }
    268 }
    269 
    270 void ExtensionBluetoothEventRouter::DispatchAdapterStateEvent() {
    271   api::bluetooth::AdapterState state;
    272   PopulateAdapterState(*adapter_.get(), &state);
    273 
    274   scoped_ptr<base::ListValue> args(new base::ListValue());
    275   args->Append(state.ToValue().release());
    276   scoped_ptr<Event> event(new Event(
    277       extensions::event_names::kBluetoothOnAdapterStateChanged,
    278       args.Pass()));
    279   ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent(event.Pass());
    280 }
    281 
    282 }  // namespace extensions
    283