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