| 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 std::vector<BluetoothScanFilter> filters; |
| 78 std::vector<BluetoothUUID> optional_services; |
| 79 }; |
| 80 |
| 75 void BluetoothDispatcherHost::set_adapter( | 81 void BluetoothDispatcherHost::set_adapter( |
| 76 scoped_refptr<device::BluetoothAdapter> adapter) { | 82 scoped_refptr<device::BluetoothAdapter> adapter) { |
| 77 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 83 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 78 if (adapter_.get()) | 84 if (adapter_.get()) |
| 79 adapter_->RemoveObserver(this); | 85 adapter_->RemoveObserver(this); |
| 80 adapter_ = adapter; | 86 adapter_ = adapter; |
| 81 if (adapter_.get()) | 87 if (adapter_.get()) |
| 82 adapter_->AddObserver(this); | 88 adapter_->AddObserver(this); |
| 83 } | 89 } |
| 84 | 90 |
| 85 void BluetoothDispatcherHost::OnRequestDevice(int thread_id, int request_id) { | 91 static scoped_ptr<device::BluetoothDiscoveryFilter> ComputeScanFilter( |
| 92 const std::vector<BluetoothScanFilter>& filters) { |
| 93 std::set<BluetoothUUID> services; |
| 94 for (const BluetoothScanFilter& filter : filters) { |
| 95 services.insert(filter.services.begin(), filter.services.end()); |
| 96 } |
| 97 scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter( |
| 98 new device::BluetoothDiscoveryFilter( |
| 99 device::BluetoothDiscoveryFilter::TRANSPORT_DUAL)); |
| 100 for (const BluetoothUUID& service : services) { |
| 101 discovery_filter->AddUUID(service); |
| 102 } |
| 103 return discovery_filter.Pass(); |
| 104 } |
| 105 |
| 106 void BluetoothDispatcherHost::OnRequestDevice( |
| 107 int thread_id, |
| 108 int request_id, |
| 109 const std::vector<BluetoothScanFilter>& filters, |
| 110 const std::vector<BluetoothUUID>& optional_services) { |
| 86 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 111 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 | 112 // TODO(scheib): Device selection UI: crbug.com/436280 |
| 89 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. | 113 // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. |
| 90 if (adapter_.get()) { | 114 if (adapter_.get()) { |
| 91 adapter_->StartDiscoverySession( | 115 adapter_->StartDiscoverySessionWithFilter( |
| 116 ComputeScanFilter(filters), |
| 92 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, | 117 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, |
| 93 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 118 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 119 base::Passed(make_scoped_ptr(new DiscoverySessionOptions{ |
| 120 filters, optional_services}))), |
| 94 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, | 121 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, |
| 95 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 122 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 96 } else { | 123 } else { |
| 97 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; | 124 DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; |
| 98 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 125 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 99 BluetoothError::NOT_FOUND)); | 126 BluetoothError::NOT_FOUND)); |
| 100 } | 127 } |
| 101 return; | 128 return; |
| 102 } | 129 } |
| 103 | 130 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 BrowserThread::UI, FROM_HERE, | 172 BrowserThread::UI, FROM_HERE, |
| 146 base::Bind(&BluetoothDispatcherHost::OnServicesDiscovered, | 173 base::Bind(&BluetoothDispatcherHost::OnServicesDiscovered, |
| 147 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 174 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 148 device_instance_id, service_uuid), | 175 device_instance_id, service_uuid), |
| 149 base::TimeDelta::FromSeconds(current_delay_time_)); | 176 base::TimeDelta::FromSeconds(current_delay_time_)); |
| 150 } | 177 } |
| 151 | 178 |
| 152 void BluetoothDispatcherHost::OnDiscoverySessionStarted( | 179 void BluetoothDispatcherHost::OnDiscoverySessionStarted( |
| 153 int thread_id, | 180 int thread_id, |
| 154 int request_id, | 181 int request_id, |
| 182 scoped_ptr<DiscoverySessionOptions> options, |
| 155 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | 183 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 156 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 184 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 157 BrowserThread::PostDelayedTask( | 185 BrowserThread::PostDelayedTask( |
| 158 BrowserThread::UI, FROM_HERE, | 186 BrowserThread::UI, FROM_HERE, |
| 159 base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, | 187 base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, |
| 160 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 188 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 161 base::Passed(&discovery_session)), | 189 base::Passed(&options), base::Passed(&discovery_session)), |
| 162 base::TimeDelta::FromSeconds(current_delay_time_)); | 190 base::TimeDelta::FromSeconds(current_delay_time_)); |
| 163 } | 191 } |
| 164 | 192 |
| 165 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, | 193 void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, |
| 166 int request_id) { | 194 int request_id) { |
| 167 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 195 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 168 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; | 196 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; |
| 169 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 197 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 170 BluetoothError::NOT_FOUND)); | 198 BluetoothError::NOT_FOUND)); |
| 171 } | 199 } |
| 172 | 200 |
| 173 void BluetoothDispatcherHost::StopDiscoverySession( | 201 void BluetoothDispatcherHost::StopDiscoverySession( |
| 174 int thread_id, | 202 int thread_id, |
| 175 int request_id, | 203 int request_id, |
| 204 scoped_ptr<DiscoverySessionOptions> options, |
| 176 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | 205 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 177 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 206 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 178 discovery_session->Stop( | 207 discovery_session->Stop( |
| 179 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, | 208 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, |
| 180 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 209 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| 210 base::Passed(&options)), |
| 181 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, | 211 base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, |
| 182 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 212 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| 183 } | 213 } |
| 184 | 214 |
| 185 void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, | 215 // Defined at |
| 186 int request_id) { | 216 // https://webbluetoothcg.github.io/web-bluetooth/#dfn-matches-a-filter |
| 217 static bool MatchesFilter(const std::set<BluetoothUUID>& device_uuids, |
| 218 const BluetoothScanFilter& filter) { |
| 219 if (filter.services.empty()) |
| 220 return false; |
| 221 for (const BluetoothUUID& service : filter.services) { |
| 222 if (!ContainsKey(device_uuids, service)) { |
| 223 return false; |
| 224 } |
| 225 } |
| 226 return true; |
| 227 } |
| 228 |
| 229 static bool MatchesFilters(const device::BluetoothDevice& device, |
| 230 const std::vector<BluetoothScanFilter>& filters) { |
| 231 const std::vector<BluetoothUUID>& device_uuid_list = device.GetUUIDs(); |
| 232 const std::set<BluetoothUUID> device_uuids(device_uuid_list.begin(), |
| 233 device_uuid_list.end()); |
| 234 for (const BluetoothScanFilter& filter : filters) { |
| 235 if (MatchesFilter(device_uuids, filter)) { |
| 236 return true; |
| 237 } |
| 238 } |
| 239 return false; |
| 240 } |
| 241 void BluetoothDispatcherHost::OnDiscoverySessionStopped( |
| 242 int thread_id, |
| 243 int request_id, |
| 244 scoped_ptr<DiscoverySessionOptions> options) { |
| 187 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 245 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 188 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); | 246 BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| 189 if (devices.begin() == devices.end()) { | 247 for (device::BluetoothDevice* device : devices) { |
| 190 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 248 if (MatchesFilters(*device, options->filters)) { |
| 191 BluetoothError::NOT_FOUND)); | 249 content::BluetoothDevice device_ipc( |
| 192 } else { | 250 device->GetAddress(), // instance_id |
| 193 device::BluetoothDevice* device = *devices.begin(); | 251 device->GetName(), // name |
| 194 content::BluetoothDevice device_ipc( | 252 device->GetBluetoothClass(), // device_class |
| 195 device->GetAddress(), // instance_id | 253 device->GetVendorIDSource(), // vendor_id_source |
| 196 device->GetName(), // name | 254 device->GetVendorID(), // vendor_id |
| 197 device->GetBluetoothClass(), // device_class | 255 device->GetProductID(), // product_id |
| 198 device->GetVendorIDSource(), // vendor_id_source | 256 device->GetDeviceID(), // product_version |
| 199 device->GetVendorID(), // vendor_id | 257 device->IsPaired(), // paired |
| 200 device->GetProductID(), // product_id | 258 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( |
| 201 device->GetDeviceID(), // product_version | 259 device->GetUUIDs())); // uuids |
| 202 device->IsPaired(), // paired | 260 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, |
| 203 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( | 261 device_ipc)); |
| 204 device->GetUUIDs())); // uuids | 262 return; |
| 205 Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, | 263 } |
| 206 device_ipc)); | |
| 207 } | 264 } |
| 265 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 266 BluetoothError::NOT_FOUND)); |
| 208 } | 267 } |
| 209 | 268 |
| 210 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, | 269 void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, |
| 211 int request_id) { | 270 int request_id) { |
| 212 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 271 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 213 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; | 272 DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; |
| 214 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, | 273 Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| 215 BluetoothError::NOT_FOUND)); | 274 BluetoothError::NOT_FOUND)); |
| 216 } | 275 } |
| 217 | 276 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 Send(new BluetoothMsg_GetPrimaryServiceSuccess(thread_id, request_id, | 315 Send(new BluetoothMsg_GetPrimaryServiceSuccess(thread_id, request_id, |
| 257 service->GetIdentifier())); | 316 service->GetIdentifier())); |
| 258 return; | 317 return; |
| 259 } | 318 } |
| 260 } | 319 } |
| 261 Send(new BluetoothMsg_GetPrimaryServiceError(thread_id, request_id, | 320 Send(new BluetoothMsg_GetPrimaryServiceError(thread_id, request_id, |
| 262 BluetoothError::NOT_FOUND)); | 321 BluetoothError::NOT_FOUND)); |
| 263 } | 322 } |
| 264 | 323 |
| 265 } // namespace content | 324 } // namespace content |
| OLD | NEW |