| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" | 5 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
| 6 | 6 |
| 7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
| 8 #include "content/common/bluetooth/bluetooth_messages.h" | 8 #include "content/common/bluetooth/bluetooth_messages.h" |
| 9 #include "device/bluetooth/bluetooth_adapter.h" | 9 #include "device/bluetooth/bluetooth_adapter.h" |
| 10 #include "device/bluetooth/bluetooth_adapter_factory.h" | 10 #include "device/bluetooth/bluetooth_adapter_factory.h" |
| 11 #include "device/bluetooth/bluetooth_device.h" | 11 #include "device/bluetooth/bluetooth_device.h" |
| 12 #include "device/bluetooth/bluetooth_discovery_session.h" | 12 #include "device/bluetooth/bluetooth_discovery_session.h" |
| 13 #include "device/bluetooth/bluetooth_gatt_service.h" | 13 #include "device/bluetooth/bluetooth_gatt_service.h" |
| 14 | 14 |
| 15 using device::BluetoothAdapter; | 15 using device::BluetoothAdapter; |
| 16 using device::BluetoothAdapterFactory; | 16 using device::BluetoothAdapterFactory; |
| 17 using device::BluetoothGattService; | 17 using device::BluetoothGattService; |
| 18 using device::BluetoothUUID; |
| 18 | 19 |
| 19 namespace content { | 20 namespace content { |
| 20 | 21 |
| 21 // TODO(ortuno): Once we have a chooser for scanning and the right | 22 // TODO(ortuno): Once we have a chooser for scanning and the right |
| 22 // callback for discovered services we should delete these constants. | 23 // callback for discovered services we should delete these constants. |
| 23 // https://crbug.com/436280 and https://crbug.com/484504 | 24 // https://crbug.com/436280 and https://crbug.com/484504 |
| 24 const int kDelayTime = 5; // 5 seconds for scanning and discovering | 25 const int kDelayTime = 5; // 5 seconds for scanning and discovering |
| 25 const int kTestingDelayTime = 0; // No need to wait during tests | 26 const int kTestingDelayTime = 0; // No need to wait during tests |
| 26 | 27 |
| 27 BluetoothDispatcherHost::BluetoothDispatcherHost() | 28 BluetoothDispatcherHost::BluetoothDispatcherHost() |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 current_delay_time_ = kTestingDelayTime; | 66 current_delay_time_ = kTestingDelayTime; |
| 66 set_adapter(mock_adapter.Pass()); | 67 set_adapter(mock_adapter.Pass()); |
| 67 } | 68 } |
| 68 | 69 |
| 69 BluetoothDispatcherHost::~BluetoothDispatcherHost() { | 70 BluetoothDispatcherHost::~BluetoothDispatcherHost() { |
| 70 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 71 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 71 // Clear adapter, releasing observer references. | 72 // Clear adapter, releasing observer references. |
| 72 set_adapter(scoped_refptr<device::BluetoothAdapter>()); | 73 set_adapter(scoped_refptr<device::BluetoothAdapter>()); |
| 73 } | 74 } |
| 74 | 75 |
| 76 struct BluetoothDispatcherHost::DiscoverySessionOptions { |
| 77 DiscoverySessionOptions(const std::vector<BluetoothScanFilter>& filters, |
| 78 const std::vector<BluetoothUUID>& optional_services) |
| 79 : filters(filters), optional_services(optional_services) {} |
| 80 |
| 81 std::vector<BluetoothScanFilter> filters; |
| 82 std::vector<BluetoothUUID> optional_services; |
| 83 }; |
| 84 |
| 75 void BluetoothDispatcherHost::set_adapter( | 85 void BluetoothDispatcherHost::set_adapter( |
| 76 scoped_refptr<device::BluetoothAdapter> adapter) { | 86 scoped_refptr<device::BluetoothAdapter> adapter) { |
| 77 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 87 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 78 if (adapter_.get()) | 88 if (adapter_.get()) |
| 79 adapter_->RemoveObserver(this); | 89 adapter_->RemoveObserver(this); |
| 80 adapter_ = adapter; | 90 adapter_ = adapter; |
| 81 if (adapter_.get()) | 91 if (adapter_.get()) |
| 82 adapter_->AddObserver(this); | 92 adapter_->AddObserver(this); |
| 83 } | 93 } |
| 84 | 94 |
| 85 void BluetoothDispatcherHost::OnRequestDevice(int thread_id, int request_id) { | 95 static scoped_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter( |
| 96 const std::vector<BluetoothScanFilter>& filters) { |
| 97 std::set<BluetoothUUID> services; |
| 98 for (const BluetoothScanFilter& filter : filters) { |
| 99 services.insert(filter.services.begin(), filter.services.end()); |
| 100 } |
| 101 scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter( |
| 102 new device::BluetoothDiscoveryFilter( |
| 103 device::BluetoothDiscoveryFilter::TRANSPORT_DUAL)); |
| 104 for (const BluetoothUUID& service : services) { |
| 105 discovery_filter->AddUUID(service); |
| 106 } |
| 107 return discovery_filter.Pass(); |
| 108 } |
| 109 |
| 110 void BluetoothDispatcherHost::OnRequestDevice( |
| 111 int thread_id, |
| 112 int request_id, |
| 113 const std::vector<BluetoothScanFilter>& filters, |
| 114 const std::vector<BluetoothUUID>& optional_services) { |
| 86 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 115 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 87 // TODO(scheib): Filter devices by services: crbug.com/440594 | |
| 88 // TODO(scheib): Device selection UI: crbug.com/436280 | 116 // TODO(scheib): Device selection UI: crbug.com/436280 |
| 89 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. | 117 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. |
| 90 if (adapter_.get()) { | 118 if (adapter_.get()) { |
| 91 adapter_->StartDiscoverySession( | 119 adapter_->StartDiscoverySessionWithFilter( |
| 120 ComputeScanFilter(filters), |
| 92 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, | 121 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, |
| 93 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 122 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 123 base::Passed(make_scoped_ptr(new DiscoverySessionOptions( |
| 124 filters, optional_services)))), |
| 94 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, | 125 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, |
| 95 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 126 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 96 } else { | 127 } else { |
| 97 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; | 128 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; |
| 98 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 129 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 99 BluetoothError::NOT_FOUND)); | 130 BluetoothError::NOT_FOUND)); |
| 100 } | 131 } |
| 101 return; | 132 return; |
| 102 } | 133 } |
| 103 | 134 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 BrowserThread::UI, FROM_HERE, | 176 BrowserThread::UI, FROM_HERE, |
| 146 base::Bind(&BluetoothDispatcherHost::OnServicesDiscovered, | 177 base::Bind(&BluetoothDispatcherHost::OnServicesDiscovered, |
| 147 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 178 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 148 device_instance_id, service_uuid), | 179 device_instance_id, service_uuid), |
| 149 base::TimeDelta::FromSeconds(current_delay_time_)); | 180 base::TimeDelta::FromSeconds(current_delay_time_)); |
| 150 } | 181 } |
| 151 | 182 |
| 152 void BluetoothDispatcherHost::OnDiscoverySessionStarted( | 183 void BluetoothDispatcherHost::OnDiscoverySessionStarted( |
| 153 int thread_id, | 184 int thread_id, |
| 154 int request_id, | 185 int request_id, |
| 186 scoped_ptr<DiscoverySessionOptions> options, |
| 155 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | 187 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 156 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 188 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 157 BrowserThread::PostDelayedTask( | 189 BrowserThread::PostDelayedTask( |
| 158 BrowserThread::UI, FROM_HERE, | 190 BrowserThread::UI, FROM_HERE, |
| 159 base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, | 191 base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, |
| 160 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 192 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 161 base::Passed(&discovery_session)), | 193 base::Passed(&options), base::Passed(&discovery_session)), |
| 162 base::TimeDelta::FromSeconds(current_delay_time_)); | 194 base::TimeDelta::FromSeconds(current_delay_time_)); |
| 163 } | 195 } |
| 164 | 196 |
| 165 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, | 197 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, |
| 166 int request_id) { | 198 int request_id) { |
| 167 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 199 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 168 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; | 200 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; |
| 169 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 201 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 170 BluetoothError::NOT_FOUND)); | 202 BluetoothError::NOT_FOUND)); |
| 171 } | 203 } |
| 172 | 204 |
| 173 void BluetoothDispatcherHost::StopDiscoverySession( | 205 void BluetoothDispatcherHost::StopDiscoverySession( |
| 174 int thread_id, | 206 int thread_id, |
| 175 int request_id, | 207 int request_id, |
| 208 scoped_ptr<DiscoverySessionOptions> options, |
| 176 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | 209 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 177 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 210 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 178 discovery_session->Stop( | 211 discovery_session->Stop( |
| 179 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, | 212 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, |
| 180 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 213 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 214 base::Passed(&options)), |
| 181 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, | 215 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, |
| 182 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 216 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 183 } | 217 } |
| 184 | 218 |
| 185 void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, | 219 // Defined at |
| 186 int request_id) { | 220 // https://webbluetoothcg.github.io/web-bluetooth/#dfn-matches-a-filter |
| 221 static bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids, |
| 222 const BluetoothScanFilter& filter) { |
| 223 if (filter.services.empty()) |
| 224 return false; |
| 225 for (const BluetoothUUID& service : filter.services) { |
| 226 if (!ContainsKey(device_uuids, service)) { |
| 227 return false; |
| 228 } |
| 229 } |
| 230 return true; |
| 231 } |
| 232 |
| 233 static bool MatchesFilters(const device::BluetoothDevice& device, |
| 234 const std::vector<BluetoothScanFilter>& filters) { |
| 235 const std::vector<BluetoothUUID>& device_uuid_list = device.GetUUIDs(); |
| 236 const std::set<BluetoothUUID> device_uuids(device_uuid_list.begin(), |
| 237 device_uuid_list.end()); |
| 238 for (const BluetoothScanFilter& filter : filters) { |
| 239 if (MatchesFilter(device_uuids, filter)) { |
| 240 return true; |
| 241 } |
| 242 } |
| 243 return false; |
| 244 } |
| 245 void BluetoothDispatcherHost::OnDiscoverySessionStopped( |
| 246 int thread_id, |
| 247 int request_id, |
| 248 scoped_ptr<DiscoverySessionOptions> options) { |
| 187 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 249 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 188 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); | 250 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| 189 if (devices.begin() == devices.end()) { | 251 for (device::BluetoothDevice* device : devices) { |
| 190 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 252 if (MatchesFilters(*device, options->filters)) { |
| 191 BluetoothError::NOT_FOUND)); | 253 content::BluetoothDevice device_ipc( |
| 192 } else { | 254 device->GetAddress(), // instance_id |
| 193 device::BluetoothDevice* device = *devices.begin(); | 255 device->GetName(), // name |
| 194 content::BluetoothDevice device_ipc( | 256 device->GetBluetoothClass(), // device_class |
| 195 device->GetAddress(), // instance_id | 257 device->GetVendorIDSource(), // vendor_id_source |
| 196 device->GetName(), // name | 258 device->GetVendorID(), // vendor_id |
| 197 device->GetBluetoothClass(), // device_class | 259 device->GetProductID(), // product_id |
| 198 device->GetVendorIDSource(), // vendor_id_source | 260 device->GetDeviceID(), // product_version |
| 199 device->GetVendorID(), // vendor_id | 261 device->IsPaired(), // paired |
| 200 device->GetProductID(), // product_id | 262 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( |
| 201 device->GetDeviceID(), // product_version | 263 device->GetUUIDs())); // uuids |
| 202 device->IsPaired(), // paired | 264 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, |
| 203 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( | 265 device_ipc)); |
| 204 device->GetUUIDs())); // uuids | 266 return; |
| 205 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, | 267 } |
| 206 device_ipc)); | |
| 207 } | 268 } |
| 269 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 270 BluetoothError::NOT_FOUND)); |
| 208 } | 271 } |
| 209 | 272 |
| 210 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, | 273 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, |
| 211 int request_id) { | 274 int request_id) { |
| 212 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 275 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 213 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; | 276 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; |
| 214 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 277 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 215 BluetoothError::NOT_FOUND)); | 278 BluetoothError::NOT_FOUND)); |
| 216 } | 279 } |
| 217 | 280 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 Send(new BluetoothMsg_GetPrimaryServiceSuccess(thread_id, request_id, | 319 Send(new BluetoothMsg_GetPrimaryServiceSuccess(thread_id, request_id, |
| 257 service->GetIdentifier())); | 320 service->GetIdentifier())); |
| 258 return; | 321 return; |
| 259 } | 322 } |
| 260 } | 323 } |
| 261 Send(new BluetoothMsg_GetPrimaryServiceError(thread_id, request_id, | 324 Send(new BluetoothMsg_GetPrimaryServiceError(thread_id, request_id, |
| 262 BluetoothError::NOT_FOUND)); | 325 BluetoothError::NOT_FOUND)); |
| 263 } | 326 } |
| 264 | 327 |
| 265 } // namespace content | 328 } // namespace content |
| OLD | NEW |