| 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 // ID Not In Map Note: | 5 // ID Not In Map Note: |
| 6 // A service, characteristic, or descriptor ID not in the corresponding | 6 // A service, characteristic, or descriptor ID not in the corresponding |
| 7 // BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_, | 7 // BluetoothDispatcherHost map [service_to_device_, characteristic_to_service_, |
| 8 // descriptor_to_characteristic_] implies a hostile renderer because a renderer | 8 // descriptor_to_characteristic_] implies a hostile renderer because a renderer |
| 9 // obtains the corresponding ID from this class and it will be added to the map | 9 // obtains the corresponding ID from this class and it will be added to the map |
| 10 // at that time. | 10 // at that time. |
| 11 | 11 |
| 12 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" | 12 #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
| 13 | 13 |
| 14 #include <stddef.h> | 14 #include <stddef.h> |
| 15 | 15 |
| 16 #include <utility> | 16 #include <utility> |
| 17 | 17 |
| 18 #include "base/bind.h" | 18 #include "base/bind.h" |
| 19 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/thread_task_runner_handle.h" | 21 #include "base/thread_task_runner_handle.h" |
| 22 #include "content/browser/bad_message.h" | |
| 23 #include "content/browser/bluetooth/bluetooth_blacklist.h" | 22 #include "content/browser/bluetooth/bluetooth_blacklist.h" |
| 24 #include "content/browser/bluetooth/bluetooth_metrics.h" | 23 #include "content/browser/bluetooth/bluetooth_metrics.h" |
| 25 #include "content/browser/bluetooth/cache_query_result.h" | 24 #include "content/browser/bluetooth/cache_query_result.h" |
| 26 #include "content/browser/bluetooth/first_device_bluetooth_chooser.h" | 25 #include "content/browser/bluetooth/first_device_bluetooth_chooser.h" |
| 27 #include "content/browser/frame_host/render_frame_host_impl.h" | 26 #include "content/browser/frame_host/render_frame_host_impl.h" |
| 28 #include "content/browser/web_contents/web_contents_impl.h" | 27 #include "content/browser/web_contents/web_contents_impl.h" |
| 29 #include "content/public/browser/content_browser_client.h" | 28 #include "content/public/browser/content_browser_client.h" |
| 30 #include "content/public/browser/web_contents.h" | 29 #include "content/public/browser/web_contents.h" |
| 31 #include "content/public/browser/web_contents_delegate.h" | 30 #include "content/public/browser/web_contents_delegate.h" |
| 32 #include "device/bluetooth/bluetooth_adapter.h" | 31 #include "device/bluetooth/bluetooth_adapter.h" |
| 33 #include "device/bluetooth/bluetooth_adapter_factory.h" | 32 #include "device/bluetooth/bluetooth_adapter_factory.h" |
| 34 #include "device/bluetooth/bluetooth_device.h" | 33 #include "device/bluetooth/bluetooth_device.h" |
| 35 #include "device/bluetooth/bluetooth_discovery_session.h" | 34 #include "device/bluetooth/bluetooth_discovery_session.h" |
| 36 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" | |
| 37 #include "device/bluetooth/bluetooth_remote_gatt_service.h" | |
| 38 | 35 |
| 39 using blink::WebBluetoothError; | 36 using blink::WebBluetoothError; |
| 40 using device::BluetoothAdapter; | 37 using device::BluetoothAdapter; |
| 41 using device::BluetoothAdapterFactory; | 38 using device::BluetoothAdapterFactory; |
| 42 using device::BluetoothRemoteGattCharacteristic; | |
| 43 using device::BluetoothRemoteGattService; | |
| 44 using device::BluetoothUUID; | 39 using device::BluetoothUUID; |
| 45 | 40 |
| 46 namespace content { | 41 namespace content { |
| 47 | 42 |
| 48 namespace { | 43 namespace { |
| 49 | 44 |
| 50 // TODO(ortuno): Once we have a chooser for scanning, a way to control that | 45 // TODO(ortuno): Once we have a chooser for scanning, a way to control that |
| 51 // chooser from tests, and the right callback for discovered services we should | 46 // chooser from tests, and the right callback for discovered services we should |
| 52 // delete these constants. | 47 // delete these constants. |
| 53 // https://crbug.com/436280 and https://crbug.com/484504 | 48 // https://crbug.com/436280 and https://crbug.com/484504 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 const std::vector<content::BluetoothScanFilter>& filters) { | 102 const std::vector<content::BluetoothScanFilter>& filters) { |
| 108 DCHECK(!HasEmptyOrInvalidFilter(filters)); | 103 DCHECK(!HasEmptyOrInvalidFilter(filters)); |
| 109 for (const content::BluetoothScanFilter& filter : filters) { | 104 for (const content::BluetoothScanFilter& filter : filters) { |
| 110 if (MatchesFilter(device, filter)) { | 105 if (MatchesFilter(device, filter)) { |
| 111 return true; | 106 return true; |
| 112 } | 107 } |
| 113 } | 108 } |
| 114 return false; | 109 return false; |
| 115 } | 110 } |
| 116 | 111 |
| 117 WebBluetoothError TranslateConnectError( | |
| 118 device::BluetoothDevice::ConnectErrorCode error_code) { | |
| 119 switch (error_code) { | |
| 120 case device::BluetoothDevice::ERROR_UNKNOWN: | |
| 121 RecordConnectGATTOutcome(UMAConnectGATTOutcome::UNKNOWN); | |
| 122 return WebBluetoothError::CONNECT_UNKNOWN_ERROR; | |
| 123 case device::BluetoothDevice::ERROR_INPROGRESS: | |
| 124 RecordConnectGATTOutcome(UMAConnectGATTOutcome::IN_PROGRESS); | |
| 125 return WebBluetoothError::CONNECT_ALREADY_IN_PROGRESS; | |
| 126 case device::BluetoothDevice::ERROR_FAILED: | |
| 127 RecordConnectGATTOutcome(UMAConnectGATTOutcome::FAILED); | |
| 128 return WebBluetoothError::CONNECT_UNKNOWN_FAILURE; | |
| 129 case device::BluetoothDevice::ERROR_AUTH_FAILED: | |
| 130 RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_FAILED); | |
| 131 return WebBluetoothError::CONNECT_AUTH_FAILED; | |
| 132 case device::BluetoothDevice::ERROR_AUTH_CANCELED: | |
| 133 RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_CANCELED); | |
| 134 return WebBluetoothError::CONNECT_AUTH_CANCELED; | |
| 135 case device::BluetoothDevice::ERROR_AUTH_REJECTED: | |
| 136 RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_REJECTED); | |
| 137 return WebBluetoothError::CONNECT_AUTH_REJECTED; | |
| 138 case device::BluetoothDevice::ERROR_AUTH_TIMEOUT: | |
| 139 RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_TIMEOUT); | |
| 140 return WebBluetoothError::CONNECT_AUTH_TIMEOUT; | |
| 141 case device::BluetoothDevice::ERROR_UNSUPPORTED_DEVICE: | |
| 142 RecordConnectGATTOutcome(UMAConnectGATTOutcome::UNSUPPORTED_DEVICE); | |
| 143 return WebBluetoothError::CONNECT_UNSUPPORTED_DEVICE; | |
| 144 case device::BluetoothDevice::ERROR_ATTRIBUTE_LENGTH_INVALID: | |
| 145 RecordConnectGATTOutcome(UMAConnectGATTOutcome::ATTRIBUTE_LENGTH_INVALID); | |
| 146 return WebBluetoothError::CONNECT_ATTRIBUTE_LENGTH_INVALID; | |
| 147 case device::BluetoothDevice::ERROR_CONNECTION_CONGESTED: | |
| 148 RecordConnectGATTOutcome(UMAConnectGATTOutcome::CONNECTION_CONGESTED); | |
| 149 return WebBluetoothError::CONNECT_CONNECTION_CONGESTED; | |
| 150 case device::BluetoothDevice::ERROR_INSUFFICIENT_ENCRYPTION: | |
| 151 RecordConnectGATTOutcome(UMAConnectGATTOutcome::INSUFFICIENT_ENCRYPTION); | |
| 152 return WebBluetoothError::CONNECT_INSUFFICIENT_ENCRYPTION; | |
| 153 case device::BluetoothDevice::ERROR_OFFSET_INVALID: | |
| 154 RecordConnectGATTOutcome(UMAConnectGATTOutcome::OFFSET_INVALID); | |
| 155 return WebBluetoothError::CONNECT_OFFSET_INVALID; | |
| 156 case device::BluetoothDevice::ERROR_READ_NOT_PERMITTED: | |
| 157 RecordConnectGATTOutcome(UMAConnectGATTOutcome::READ_NOT_PERMITTED); | |
| 158 return WebBluetoothError::CONNECT_READ_NOT_PERMITTED; | |
| 159 case device::BluetoothDevice::ERROR_REQUEST_NOT_SUPPORTED: | |
| 160 RecordConnectGATTOutcome(UMAConnectGATTOutcome::REQUEST_NOT_SUPPORTED); | |
| 161 return WebBluetoothError::CONNECT_REQUEST_NOT_SUPPORTED; | |
| 162 case device::BluetoothDevice::ERROR_WRITE_NOT_PERMITTED: | |
| 163 RecordConnectGATTOutcome(UMAConnectGATTOutcome::WRITE_NOT_PERMITTED); | |
| 164 return WebBluetoothError::CONNECT_WRITE_NOT_PERMITTED; | |
| 165 case device::BluetoothDevice::NUM_CONNECT_ERROR_CODES: | |
| 166 NOTREACHED(); | |
| 167 return WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE; | |
| 168 } | |
| 169 NOTREACHED(); | |
| 170 return WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE; | |
| 171 } | |
| 172 | |
| 173 void StopDiscoverySession( | 112 void StopDiscoverySession( |
| 174 std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) { | 113 std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| 175 // Nothing goes wrong if the discovery session fails to stop, and we don't | 114 // Nothing goes wrong if the discovery session fails to stop, and we don't |
| 176 // need to wait for it before letting the user's script proceed, so we ignore | 115 // need to wait for it before letting the user's script proceed, so we ignore |
| 177 // the results here. | 116 // the results here. |
| 178 discovery_session->Stop(base::Bind(&base::DoNothing), | 117 discovery_session->Stop(base::Bind(&base::DoNothing), |
| 179 base::Bind(&base::DoNothing)); | 118 base::Bind(&base::DoNothing)); |
| 180 } | 119 } |
| 181 | 120 |
| 182 UMARequestDeviceOutcome OutcomeFromChooserEvent(BluetoothChooser::Event event) { | 121 UMARequestDeviceOutcome OutcomeFromChooserEvent(BluetoothChooser::Event event) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 // directly, and change this to a reasonable discovery timeout. | 158 // directly, and change this to a reasonable discovery timeout. |
| 220 base::TimeDelta::FromSecondsD(current_delay_time_), | 159 base::TimeDelta::FromSecondsD(current_delay_time_), |
| 221 base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery, | 160 base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery, |
| 222 // base::Timer guarantees it won't call back after its | 161 // base::Timer guarantees it won't call back after its |
| 223 // destructor starts. | 162 // destructor starts. |
| 224 base::Unretained(this)), | 163 base::Unretained(this)), |
| 225 /*is_repeating=*/false), | 164 /*is_repeating=*/false), |
| 226 weak_ptr_factory_(this) { | 165 weak_ptr_factory_(this) { |
| 227 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 166 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 228 | 167 |
| 229 connected_devices_map_.reset(new ConnectedDevicesMap(render_process_id)); | |
| 230 | |
| 231 // Bind all future weak pointers to the UI thread. | 168 // Bind all future weak pointers to the UI thread. |
| 232 weak_ptr_on_ui_thread_ = weak_ptr_factory_.GetWeakPtr(); | 169 weak_ptr_on_ui_thread_ = weak_ptr_factory_.GetWeakPtr(); |
| 233 weak_ptr_on_ui_thread_.get(); // Associates with UI thread. | 170 weak_ptr_on_ui_thread_.get(); // Associates with UI thread. |
| 234 } | 171 } |
| 235 | 172 |
| 236 void BluetoothDispatcherHost::OnDestruct() const { | 173 void BluetoothDispatcherHost::OnDestruct() const { |
| 237 // See class comment: UI Thread Note. | 174 // See class comment: UI Thread Note. |
| 238 BrowserThread::DeleteOnUIThread::Destruct(this); | 175 BrowserThread::DeleteOnUIThread::Destruct(this); |
| 239 } | 176 } |
| 240 | 177 |
| 241 void BluetoothDispatcherHost::OverrideThreadForMessage( | 178 void BluetoothDispatcherHost::OverrideThreadForMessage( |
| 242 const IPC::Message& message, | 179 const IPC::Message& message, |
| 243 content::BrowserThread::ID* thread) { | 180 content::BrowserThread::ID* thread) { |
| 244 // See class comment: UI Thread Note. | 181 // See class comment: UI Thread Note. |
| 245 *thread = BrowserThread::UI; | 182 *thread = BrowserThread::UI; |
| 246 } | 183 } |
| 247 | 184 |
| 248 bool BluetoothDispatcherHost::OnMessageReceived(const IPC::Message& message) { | 185 bool BluetoothDispatcherHost::OnMessageReceived(const IPC::Message& message) { |
| 249 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 186 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 250 bool handled = true; | 187 bool handled = true; |
| 251 IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcherHost, message) | 188 IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcherHost, message) |
| 252 IPC_MESSAGE_HANDLER(BluetoothHostMsg_RequestDevice, OnRequestDevice) | 189 IPC_MESSAGE_HANDLER(BluetoothHostMsg_RequestDevice, OnRequestDevice) |
| 253 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GATTServerConnect, OnGATTServerConnect) | |
| 254 IPC_MESSAGE_HANDLER(BluetoothHostMsg_GATTServerDisconnect, | |
| 255 OnGATTServerDisconnect) | |
| 256 IPC_MESSAGE_UNHANDLED(handled = false) | 190 IPC_MESSAGE_UNHANDLED(handled = false) |
| 257 IPC_END_MESSAGE_MAP() | 191 IPC_END_MESSAGE_MAP() |
| 258 return handled; | 192 return handled; |
| 259 } | 193 } |
| 260 | 194 |
| 261 void BluetoothDispatcherHost::SetBluetoothAdapterForTesting( | 195 void BluetoothDispatcherHost::SetBluetoothAdapterForTesting( |
| 262 scoped_refptr<device::BluetoothAdapter> mock_adapter) { | 196 scoped_refptr<device::BluetoothAdapter> mock_adapter) { |
| 263 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 197 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 264 | 198 |
| 265 if (mock_adapter.get()) { | 199 if (mock_adapter.get()) { |
| 266 current_delay_time_ = kTestingDelayTime; | 200 current_delay_time_ = kTestingDelayTime; |
| 267 // Reset the discovery session timer to use the new delay time. | 201 // Reset the discovery session timer to use the new delay time. |
| 268 discovery_session_timer_.Start( | 202 discovery_session_timer_.Start( |
| 269 FROM_HERE, base::TimeDelta::FromSecondsD(current_delay_time_), | 203 FROM_HERE, base::TimeDelta::FromSecondsD(current_delay_time_), |
| 270 base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery, | 204 base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery, |
| 271 // base::Timer guarantees it won't call back after its | 205 // base::Timer guarantees it won't call back after its |
| 272 // destructor starts. | 206 // destructor starts. |
| 273 base::Unretained(this))); | 207 base::Unretained(this))); |
| 274 } else { | 208 } else { |
| 275 // The following data structures are used to store pending operations. | 209 // The following data structures are used to store pending operations. |
| 276 // They should never contain elements at the end of a test. | 210 // They should never contain elements at the end of a test. |
| 277 DCHECK(request_device_sessions_.IsEmpty()); | 211 DCHECK(request_device_sessions_.IsEmpty()); |
| 278 | 212 |
| 279 // The following data structures are cleaned up when a | 213 // The following data structures are cleaned up when a |
| 280 // device/service/characteristic is removed. | 214 // device/service/characteristic is removed. |
| 281 // Since this can happen after the test is done and the cleanup function is | 215 // Since this can happen after the test is done and the cleanup function is |
| 282 // called, we clean them here. | 216 // called, we clean them here. |
| 283 connected_devices_map_.reset(new ConnectedDevicesMap(render_process_id_)); | |
| 284 allowed_devices_map_ = BluetoothAllowedDevicesMap(); | 217 allowed_devices_map_ = BluetoothAllowedDevicesMap(); |
| 285 } | 218 } |
| 286 | 219 |
| 287 set_adapter(std::move(mock_adapter)); | 220 set_adapter(std::move(mock_adapter)); |
| 288 } | 221 } |
| 289 | 222 |
| 290 BluetoothDispatcherHost::~BluetoothDispatcherHost() { | 223 BluetoothDispatcherHost::~BluetoothDispatcherHost() { |
| 291 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 224 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 292 // Clear adapter, releasing observer references. | 225 // Clear adapter, releasing observer references. |
| 293 set_adapter(scoped_refptr<device::BluetoothAdapter>()); | 226 set_adapter(scoped_refptr<device::BluetoothAdapter>()); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 | 263 |
| 331 const int thread_id; | 264 const int thread_id; |
| 332 const int request_id; | 265 const int request_id; |
| 333 const url::Origin origin; | 266 const url::Origin origin; |
| 334 const std::vector<BluetoothScanFilter> filters; | 267 const std::vector<BluetoothScanFilter> filters; |
| 335 const std::vector<BluetoothUUID> optional_services; | 268 const std::vector<BluetoothUUID> optional_services; |
| 336 std::unique_ptr<BluetoothChooser> chooser; | 269 std::unique_ptr<BluetoothChooser> chooser; |
| 337 std::unique_ptr<device::BluetoothDiscoverySession> discovery_session; | 270 std::unique_ptr<device::BluetoothDiscoverySession> discovery_session; |
| 338 }; | 271 }; |
| 339 | 272 |
| 340 BluetoothDispatcherHost::ConnectedDevicesMap::ConnectedDevicesMap( | |
| 341 int render_process_id) | |
| 342 : render_process_id_(render_process_id) {} | |
| 343 | |
| 344 BluetoothDispatcherHost::ConnectedDevicesMap::~ConnectedDevicesMap() { | |
| 345 for (auto frame_id_device_id : frame_ids_device_ids_) { | |
| 346 DecrementBluetoothConnectedDeviceCount(frame_id_device_id.first); | |
| 347 } | |
| 348 } | |
| 349 | |
| 350 bool BluetoothDispatcherHost::ConnectedDevicesMap::HasActiveConnection( | |
| 351 const std::string& device_id) { | |
| 352 auto connection_iter = device_id_to_connection_map_.find(device_id); | |
| 353 if (connection_iter != device_id_to_connection_map_.end()) { | |
| 354 return connection_iter->second->IsConnected(); | |
| 355 } | |
| 356 return false; | |
| 357 } | |
| 358 | |
| 359 void BluetoothDispatcherHost::ConnectedDevicesMap::InsertOrReplace( | |
| 360 int frame_routing_id, | |
| 361 const std::string& device_id, | |
| 362 std::unique_ptr<device::BluetoothGattConnection> connection) { | |
| 363 auto connection_iter = device_id_to_connection_map_.find(device_id); | |
| 364 if (connection_iter == device_id_to_connection_map_.end()) { | |
| 365 IncrementBluetoothConnectedDeviceCount(frame_routing_id); | |
| 366 frame_ids_device_ids_.insert(std::make_pair(frame_routing_id, device_id)); | |
| 367 } else { | |
| 368 device_id_to_connection_map_.erase(connection_iter); | |
| 369 } | |
| 370 device_id_to_connection_map_[device_id] = std::move(connection); | |
| 371 } | |
| 372 | |
| 373 void BluetoothDispatcherHost::ConnectedDevicesMap::Remove( | |
| 374 int frame_routing_id, | |
| 375 const std::string& device_id) { | |
| 376 if (device_id_to_connection_map_.erase(device_id)) { | |
| 377 VLOG(1) << "Disconnecting device: " << device_id; | |
| 378 DecrementBluetoothConnectedDeviceCount(frame_routing_id); | |
| 379 frame_ids_device_ids_.erase(std::make_pair(frame_routing_id, device_id)); | |
| 380 } | |
| 381 } | |
| 382 | |
| 383 void BluetoothDispatcherHost::ConnectedDevicesMap:: | |
| 384 IncrementBluetoothConnectedDeviceCount(int frame_routing_id) { | |
| 385 RenderFrameHostImpl* render_frame_host = | |
| 386 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); | |
| 387 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( | |
| 388 WebContents::FromRenderFrameHost(render_frame_host)); | |
| 389 if (web_contents) { | |
| 390 web_contents->IncrementBluetoothConnectedDeviceCount(); | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 void BluetoothDispatcherHost::ConnectedDevicesMap:: | |
| 395 DecrementBluetoothConnectedDeviceCount(int frame_routing_id) { | |
| 396 RenderFrameHostImpl* render_frame_host = | |
| 397 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); | |
| 398 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( | |
| 399 WebContents::FromRenderFrameHost(render_frame_host)); | |
| 400 if (web_contents) { | |
| 401 web_contents->DecrementBluetoothConnectedDeviceCount(); | |
| 402 } | |
| 403 } | |
| 404 | |
| 405 void BluetoothDispatcherHost::set_adapter( | 273 void BluetoothDispatcherHost::set_adapter( |
| 406 scoped_refptr<device::BluetoothAdapter> adapter) { | 274 scoped_refptr<device::BluetoothAdapter> adapter) { |
| 407 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 275 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 408 if (adapter_.get()) { | 276 if (adapter_.get()) { |
| 409 adapter_->RemoveObserver(this); | 277 adapter_->RemoveObserver(this); |
| 410 for (device::BluetoothAdapter::Observer* observer : adapter_observers_) { | 278 for (device::BluetoothAdapter::Observer* observer : adapter_observers_) { |
| 411 adapter_->RemoveObserver(observer); | 279 adapter_->RemoveObserver(observer); |
| 412 } | 280 } |
| 413 } | 281 } |
| 414 adapter_ = adapter; | 282 adapter_ = adapter; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 } | 404 } |
| 537 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER); | 405 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER); |
| 538 Send(new BluetoothMsg_RequestDeviceError( | 406 Send(new BluetoothMsg_RequestDeviceError( |
| 539 thread_id, request_id, WebBluetoothError::NO_BLUETOOTH_ADAPTER)); | 407 thread_id, request_id, WebBluetoothError::NO_BLUETOOTH_ADAPTER)); |
| 540 return; | 408 return; |
| 541 } | 409 } |
| 542 OnRequestDeviceImpl(thread_id, request_id, frame_routing_id, filters, | 410 OnRequestDeviceImpl(thread_id, request_id, frame_routing_id, filters, |
| 543 optional_services); | 411 optional_services); |
| 544 } | 412 } |
| 545 | 413 |
| 546 void BluetoothDispatcherHost::OnGATTServerConnect( | |
| 547 int thread_id, | |
| 548 int request_id, | |
| 549 int frame_routing_id, | |
| 550 const std::string& device_id) { | |
| 551 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 552 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); | |
| 553 const base::TimeTicks start_time = base::TimeTicks::Now(); | |
| 554 | |
| 555 const CacheQueryResult query_result = | |
| 556 QueryCacheForDevice(GetOrigin(frame_routing_id), device_id); | |
| 557 | |
| 558 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | |
| 559 RecordConnectGATTOutcome(query_result.outcome); | |
| 560 Send(new BluetoothMsg_GATTServerConnectError(thread_id, request_id, | |
| 561 query_result.GetWebError())); | |
| 562 return; | |
| 563 } | |
| 564 | |
| 565 // If we are already connected no need to connect again. | |
| 566 if (connected_devices_map_->HasActiveConnection(device_id)) { | |
| 567 VLOG(1) << "Already connected."; | |
| 568 Send(new BluetoothMsg_GATTServerConnectSuccess(thread_id, request_id)); | |
| 569 return; | |
| 570 } | |
| 571 | |
| 572 query_result.device->CreateGattConnection( | |
| 573 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | |
| 574 weak_ptr_on_ui_thread_, thread_id, request_id, | |
| 575 frame_routing_id, device_id, start_time), | |
| 576 base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, | |
| 577 weak_ptr_on_ui_thread_, thread_id, request_id, device_id, | |
| 578 start_time)); | |
| 579 } | |
| 580 | |
| 581 void BluetoothDispatcherHost::OnGATTServerDisconnect( | |
| 582 int thread_id, | |
| 583 int frame_routing_id, | |
| 584 const std::string& device_id) { | |
| 585 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 586 RecordWebBluetoothFunctionCall( | |
| 587 UMAWebBluetoothFunction::REMOTE_GATT_SERVER_DISCONNECT); | |
| 588 | |
| 589 // Frames can send a disconnect request after they've started navigating, | |
| 590 // making calls to GetLastCommitted origin invalid. Because we still need | |
| 591 // to disconnect the device, otherwise we would leave users with no other | |
| 592 // option to disconnect than closing the tab, we purposefully don't | |
| 593 // check if the frame has permission to interact with the device. | |
| 594 | |
| 595 // The last BluetoothGattConnection for a device closes the connection when | |
| 596 // it's destroyed. | |
| 597 | |
| 598 // This only catches disconnections from the renderer. If the device | |
| 599 // disconnects by itself, or the renderer frame has been deleted | |
| 600 // due to navigation, we will not hide the indicator. | |
| 601 // TODO(ortuno): Once we move to Frame and Mojo we will be able | |
| 602 // to observe the frame's lifetime and hide the indicator when necessary. | |
| 603 // http://crbug.com/508771 | |
| 604 connected_devices_map_->Remove(frame_routing_id, device_id); | |
| 605 } | |
| 606 | |
| 607 void BluetoothDispatcherHost::OnGetAdapter( | 414 void BluetoothDispatcherHost::OnGetAdapter( |
| 608 base::Closure continuation, | 415 base::Closure continuation, |
| 609 scoped_refptr<device::BluetoothAdapter> adapter) { | 416 scoped_refptr<device::BluetoothAdapter> adapter) { |
| 610 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 417 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 611 set_adapter(adapter); | 418 set_adapter(adapter); |
| 612 continuation.Run(); | 419 continuation.Run(); |
| 613 } | 420 } |
| 614 | 421 |
| 615 void BluetoothDispatcherHost::OnRequestDeviceImpl( | 422 void BluetoothDispatcherHost::OnRequestDeviceImpl( |
| 616 int thread_id, | 423 int thread_id, |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 925 content::BluetoothDevice::ValidatePower( | 732 content::BluetoothDevice::ValidatePower( |
| 926 device->GetInquiryRSSI()), // rssi | 733 device->GetInquiryRSSI()), // rssi |
| 927 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( | 734 content::BluetoothDevice::UUIDsFromBluetoothUUIDs( |
| 928 filtered_uuids)); // uuids | 735 filtered_uuids)); // uuids |
| 929 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS); | 736 RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS); |
| 930 Send(new BluetoothMsg_RequestDeviceSuccess(session->thread_id, | 737 Send(new BluetoothMsg_RequestDeviceSuccess(session->thread_id, |
| 931 session->request_id, device_ipc)); | 738 session->request_id, device_ipc)); |
| 932 request_device_sessions_.Remove(chooser_id); | 739 request_device_sessions_.Remove(chooser_id); |
| 933 } | 740 } |
| 934 | 741 |
| 935 void BluetoothDispatcherHost::OnGATTConnectionCreated( | |
| 936 int thread_id, | |
| 937 int request_id, | |
| 938 int frame_routing_id, | |
| 939 const std::string& device_id, | |
| 940 base::TimeTicks start_time, | |
| 941 std::unique_ptr<device::BluetoothGattConnection> connection) { | |
| 942 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 943 RecordConnectGATTTimeSuccess(base::TimeTicks::Now() - start_time); | |
| 944 RecordConnectGATTOutcome(UMAConnectGATTOutcome::SUCCESS); | |
| 945 connected_devices_map_->InsertOrReplace(frame_routing_id, device_id, | |
| 946 std::move(connection)); | |
| 947 Send(new BluetoothMsg_GATTServerConnectSuccess(thread_id, request_id)); | |
| 948 } | |
| 949 | |
| 950 void BluetoothDispatcherHost::OnCreateGATTConnectionError( | |
| 951 int thread_id, | |
| 952 int request_id, | |
| 953 const std::string& device_id, | |
| 954 base::TimeTicks start_time, | |
| 955 device::BluetoothDevice::ConnectErrorCode error_code) { | |
| 956 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 957 // There was an error creating the ATT Bearer so we reject with | |
| 958 // NetworkError. | |
| 959 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-con
nectgatt | |
| 960 RecordConnectGATTTimeFailed(base::TimeTicks::Now() - start_time); | |
| 961 // RecordConnectGATTOutcome is called by TranslateConnectError. | |
| 962 Send(new BluetoothMsg_GATTServerConnectError( | |
| 963 thread_id, request_id, TranslateConnectError(error_code))); | |
| 964 } | |
| 965 | |
| 966 CacheQueryResult BluetoothDispatcherHost::QueryCacheForDevice( | 742 CacheQueryResult BluetoothDispatcherHost::QueryCacheForDevice( |
| 967 const url::Origin& origin, | 743 const url::Origin& origin, |
| 968 const std::string& device_id) { | 744 const std::string& device_id) { |
| 969 const std::string& device_address = | 745 const std::string& device_address = |
| 970 allowed_devices_map_.GetDeviceAddress(origin, device_id); | 746 allowed_devices_map_.GetDeviceAddress(origin, device_id); |
| 971 if (device_address.empty()) { | 747 if (device_address.empty()) { |
| 972 bad_message::ReceivedBadMessage( | 748 bad_message::ReceivedBadMessage( |
| 973 this, bad_message::BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN); | 749 this, bad_message::BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN); |
| 974 return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER); | 750 return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER); |
| 975 } | 751 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 996 } | 772 } |
| 997 | 773 |
| 998 void BluetoothDispatcherHost::RemoveAdapterObserver( | 774 void BluetoothDispatcherHost::RemoveAdapterObserver( |
| 999 device::BluetoothAdapter::Observer* observer) { | 775 device::BluetoothAdapter::Observer* observer) { |
| 1000 DCHECK(adapter_observers_.erase(observer)); | 776 DCHECK(adapter_observers_.erase(observer)); |
| 1001 if (adapter_) { | 777 if (adapter_) { |
| 1002 adapter_->RemoveObserver(observer); | 778 adapter_->RemoveObserver(observer); |
| 1003 } | 779 } |
| 1004 } | 780 } |
| 1005 | 781 |
| 1006 url::Origin BluetoothDispatcherHost::GetOrigin(int frame_routing_id) { | |
| 1007 return RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id) | |
| 1008 ->GetLastCommittedOrigin(); | |
| 1009 } | |
| 1010 | |
| 1011 } // namespace content | 782 } // namespace content |
| OLD | NEW |