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