| 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" | 22 #include "content/browser/bad_message.h" |
| 23 #include "content/browser/bluetooth/bluetooth_blacklist.h" | 23 #include "content/browser/bluetooth/bluetooth_blacklist.h" |
| 24 #include "content/browser/bluetooth/first_device_bluetooth_chooser.h" | 24 #include "content/browser/bluetooth/first_device_bluetooth_chooser.h" |
| 25 #include "content/browser/frame_host/render_frame_host_impl.h" | 25 #include "content/browser/frame_host/render_frame_host_impl.h" |
| 26 #include "content/browser/web_contents/web_contents_impl.h" |
| 26 #include "content/public/browser/content_browser_client.h" | 27 #include "content/public/browser/content_browser_client.h" |
| 27 #include "content/public/browser/web_contents.h" | 28 #include "content/public/browser/web_contents.h" |
| 28 #include "content/public/browser/web_contents_delegate.h" | 29 #include "content/public/browser/web_contents_delegate.h" |
| 29 #include "device/bluetooth/bluetooth_adapter.h" | 30 #include "device/bluetooth/bluetooth_adapter.h" |
| 30 #include "device/bluetooth/bluetooth_adapter_factory.h" | 31 #include "device/bluetooth/bluetooth_adapter_factory.h" |
| 31 #include "device/bluetooth/bluetooth_device.h" | 32 #include "device/bluetooth/bluetooth_device.h" |
| 32 #include "device/bluetooth/bluetooth_discovery_session.h" | 33 #include "device/bluetooth/bluetooth_discovery_session.h" |
| 33 #include "device/bluetooth/bluetooth_gatt_characteristic.h" | 34 #include "device/bluetooth/bluetooth_gatt_characteristic.h" |
| 34 #include "device/bluetooth/bluetooth_gatt_service.h" | 35 #include "device/bluetooth/bluetooth_gatt_service.h" |
| 35 | 36 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 // directly, and change this to a reasonable discovery timeout. | 273 // directly, and change this to a reasonable discovery timeout. |
| 273 base::TimeDelta::FromSecondsD(current_delay_time_), | 274 base::TimeDelta::FromSecondsD(current_delay_time_), |
| 274 base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery, | 275 base::Bind(&BluetoothDispatcherHost::StopDeviceDiscovery, |
| 275 // base::Timer guarantees it won't call back after its | 276 // base::Timer guarantees it won't call back after its |
| 276 // destructor starts. | 277 // destructor starts. |
| 277 base::Unretained(this)), | 278 base::Unretained(this)), |
| 278 /*is_repeating=*/false), | 279 /*is_repeating=*/false), |
| 279 weak_ptr_factory_(this) { | 280 weak_ptr_factory_(this) { |
| 280 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 281 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 281 | 282 |
| 283 connected_devices_map_.reset(new ConnectedDevicesMap(render_process_id)); |
| 284 |
| 282 // Bind all future weak pointers to the UI thread. | 285 // Bind all future weak pointers to the UI thread. |
| 283 weak_ptr_on_ui_thread_ = weak_ptr_factory_.GetWeakPtr(); | 286 weak_ptr_on_ui_thread_ = weak_ptr_factory_.GetWeakPtr(); |
| 284 weak_ptr_on_ui_thread_.get(); // Associates with UI thread. | 287 weak_ptr_on_ui_thread_.get(); // Associates with UI thread. |
| 285 } | 288 } |
| 286 | 289 |
| 287 void BluetoothDispatcherHost::OnDestruct() const { | 290 void BluetoothDispatcherHost::OnDestruct() const { |
| 288 // See class comment: UI Thread Note. | 291 // See class comment: UI Thread Note. |
| 289 BrowserThread::DeleteOnUIThread::Destruct(this); | 292 BrowserThread::DeleteOnUIThread::Destruct(this); |
| 290 } | 293 } |
| 291 | 294 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 DCHECK(pending_primary_services_requests_.empty()); | 342 DCHECK(pending_primary_services_requests_.empty()); |
| 340 | 343 |
| 341 // The following data structures are cleaned up when a | 344 // The following data structures are cleaned up when a |
| 342 // device/service/characteristic is removed. | 345 // device/service/characteristic is removed. |
| 343 // Since this can happen after the test is done and the cleanup function is | 346 // Since this can happen after the test is done and the cleanup function is |
| 344 // called, we clean them here. | 347 // called, we clean them here. |
| 345 service_to_device_.clear(); | 348 service_to_device_.clear(); |
| 346 characteristic_to_service_.clear(); | 349 characteristic_to_service_.clear(); |
| 347 characteristic_id_to_notify_session_.clear(); | 350 characteristic_id_to_notify_session_.clear(); |
| 348 active_characteristic_threads_.clear(); | 351 active_characteristic_threads_.clear(); |
| 349 device_id_to_connection_map_.clear(); | 352 connected_devices_map_.reset(new ConnectedDevicesMap(render_process_id_)); |
| 350 allowed_devices_map_ = BluetoothAllowedDevicesMap(); | 353 allowed_devices_map_ = BluetoothAllowedDevicesMap(); |
| 351 } | 354 } |
| 352 | 355 |
| 353 set_adapter(std::move(mock_adapter)); | 356 set_adapter(std::move(mock_adapter)); |
| 354 } | 357 } |
| 355 | 358 |
| 356 BluetoothDispatcherHost::~BluetoothDispatcherHost() { | 359 BluetoothDispatcherHost::~BluetoothDispatcherHost() { |
| 357 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 360 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 358 // Clear adapter, releasing observer references. | 361 // Clear adapter, releasing observer references. |
| 359 set_adapter(scoped_refptr<device::BluetoothAdapter>()); | 362 set_adapter(scoped_refptr<device::BluetoothAdapter>()); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 service_uuid(service_uuid), | 447 service_uuid(service_uuid), |
| 445 func(func) {} | 448 func(func) {} |
| 446 ~PrimaryServicesRequest() {} | 449 ~PrimaryServicesRequest() {} |
| 447 | 450 |
| 448 int thread_id; | 451 int thread_id; |
| 449 int request_id; | 452 int request_id; |
| 450 std::string service_uuid; | 453 std::string service_uuid; |
| 451 CallingFunction func; | 454 CallingFunction func; |
| 452 }; | 455 }; |
| 453 | 456 |
| 457 BluetoothDispatcherHost::ConnectedDevicesMap::ConnectedDevicesMap( |
| 458 int render_process_id) |
| 459 : render_process_id_(render_process_id) {} |
| 460 |
| 461 BluetoothDispatcherHost::ConnectedDevicesMap::~ConnectedDevicesMap() { |
| 462 for (auto frame_id_device_id : frame_ids_device_ids_) { |
| 463 DecrementBluetoothConnectedDeviceCount(frame_id_device_id.first); |
| 464 } |
| 465 } |
| 466 |
| 467 bool BluetoothDispatcherHost::ConnectedDevicesMap::HasActiveConnection( |
| 468 const std::string& device_id) { |
| 469 auto connection_iter = device_id_to_connection_map_.find(device_id); |
| 470 if (connection_iter != device_id_to_connection_map_.end()) { |
| 471 return connection_iter->second->IsConnected(); |
| 472 } |
| 473 return false; |
| 474 } |
| 475 |
| 476 void BluetoothDispatcherHost::ConnectedDevicesMap::InsertOrReplace( |
| 477 int frame_routing_id, |
| 478 const std::string& device_id, |
| 479 scoped_ptr<device::BluetoothGattConnection> connection) { |
| 480 auto connection_iter = device_id_to_connection_map_.find(device_id); |
| 481 if (connection_iter == device_id_to_connection_map_.end()) { |
| 482 IncrementBluetoothConnectedDeviceCount(frame_routing_id); |
| 483 frame_ids_device_ids_.insert(std::make_pair(frame_routing_id, device_id)); |
| 484 } else { |
| 485 device_id_to_connection_map_.erase(connection_iter); |
| 486 } |
| 487 device_id_to_connection_map_[device_id] = std::move(connection); |
| 488 } |
| 489 |
| 490 void BluetoothDispatcherHost::ConnectedDevicesMap::Remove( |
| 491 int frame_routing_id, |
| 492 const std::string& device_id) { |
| 493 if (device_id_to_connection_map_.erase(device_id)) { |
| 494 VLOG(1) << "Disconnecting device: " << device_id; |
| 495 DecrementBluetoothConnectedDeviceCount(frame_routing_id); |
| 496 frame_ids_device_ids_.erase(std::make_pair(frame_routing_id, device_id)); |
| 497 } |
| 498 } |
| 499 |
| 500 void BluetoothDispatcherHost::ConnectedDevicesMap:: |
| 501 IncrementBluetoothConnectedDeviceCount(int frame_routing_id) { |
| 502 RenderFrameHostImpl* render_frame_host = |
| 503 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); |
| 504 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( |
| 505 WebContents::FromRenderFrameHost(render_frame_host)); |
| 506 if (web_contents) { |
| 507 web_contents->IncrementBluetoothConnectedDeviceCount(); |
| 508 } |
| 509 } |
| 510 |
| 511 void BluetoothDispatcherHost::ConnectedDevicesMap:: |
| 512 DecrementBluetoothConnectedDeviceCount(int frame_routing_id) { |
| 513 RenderFrameHostImpl* render_frame_host = |
| 514 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); |
| 515 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( |
| 516 WebContents::FromRenderFrameHost(render_frame_host)); |
| 517 if (web_contents) { |
| 518 web_contents->DecrementBluetoothConnectedDeviceCount(); |
| 519 } |
| 520 } |
| 521 |
| 454 void BluetoothDispatcherHost::set_adapter( | 522 void BluetoothDispatcherHost::set_adapter( |
| 455 scoped_refptr<device::BluetoothAdapter> adapter) { | 523 scoped_refptr<device::BluetoothAdapter> adapter) { |
| 456 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 524 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 457 if (adapter_.get()) | 525 if (adapter_.get()) |
| 458 adapter_->RemoveObserver(this); | 526 adapter_->RemoveObserver(this); |
| 459 adapter_ = adapter; | 527 adapter_ = adapter; |
| 460 if (adapter_.get()) | 528 if (adapter_.get()) |
| 461 adapter_->AddObserver(this); | 529 adapter_->AddObserver(this); |
| 462 } | 530 } |
| 463 | 531 |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 QueryCacheForDevice(GetOrigin(frame_routing_id), device_id); | 736 QueryCacheForDevice(GetOrigin(frame_routing_id), device_id); |
| 669 | 737 |
| 670 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { | 738 if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
| 671 RecordConnectGATTOutcome(query_result.outcome); | 739 RecordConnectGATTOutcome(query_result.outcome); |
| 672 Send(new BluetoothMsg_GATTServerConnectError(thread_id, request_id, | 740 Send(new BluetoothMsg_GATTServerConnectError(thread_id, request_id, |
| 673 query_result.GetWebError())); | 741 query_result.GetWebError())); |
| 674 return; | 742 return; |
| 675 } | 743 } |
| 676 | 744 |
| 677 // If we are already connected no need to connect again. | 745 // If we are already connected no need to connect again. |
| 678 auto connection_iter = device_id_to_connection_map_.find(device_id); | 746 if (connected_devices_map_->HasActiveConnection(device_id)) { |
| 679 if (connection_iter != device_id_to_connection_map_.end()) { | 747 VLOG(1) << "Already connected."; |
| 680 if (connection_iter->second->IsConnected()) { | 748 Send(new BluetoothMsg_GATTServerConnectSuccess(thread_id, request_id)); |
| 681 VLOG(1) << "Already connected."; | 749 return; |
| 682 Send(new BluetoothMsg_GATTServerConnectSuccess(thread_id, request_id)); | |
| 683 return; | |
| 684 } | |
| 685 } | 750 } |
| 686 | 751 |
| 687 query_result.device->CreateGattConnection( | 752 query_result.device->CreateGattConnection( |
| 688 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | 753 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, |
| 689 weak_ptr_on_ui_thread_, thread_id, request_id, | 754 weak_ptr_on_ui_thread_, thread_id, request_id, |
| 690 frame_routing_id, device_id, start_time), | 755 frame_routing_id, device_id, start_time), |
| 691 base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, | 756 base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, |
| 692 weak_ptr_on_ui_thread_, thread_id, request_id, device_id, | 757 weak_ptr_on_ui_thread_, thread_id, request_id, device_id, |
| 693 start_time)); | 758 start_time)); |
| 694 } | 759 } |
| 695 | 760 |
| 696 void BluetoothDispatcherHost::OnGATTServerDisconnect( | 761 void BluetoothDispatcherHost::OnGATTServerDisconnect( |
| 697 int thread_id, | 762 int thread_id, |
| 698 int frame_routing_id, | 763 int frame_routing_id, |
| 699 const std::string& device_id) { | 764 const std::string& device_id) { |
| 700 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 765 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 701 RecordWebBluetoothFunctionCall( | 766 RecordWebBluetoothFunctionCall( |
| 702 UMAWebBluetoothFunction::REMOTE_GATT_SERVER_DISCONNECT); | 767 UMAWebBluetoothFunction::REMOTE_GATT_SERVER_DISCONNECT); |
| 703 | 768 |
| 704 // Frames can send a disconnect request after they've started navigating, | 769 // Frames can send a disconnect request after they've started navigating, |
| 705 // making calls to GetLastCommitted origin invalid. Because we still need | 770 // making calls to GetLastCommitted origin invalid. Because we still need |
| 706 // to disconnect the device, otherwise we would leave users with no other | 771 // to disconnect the device, otherwise we would leave users with no other |
| 707 // option to disconnect than closing the tab, we purposefully don't | 772 // option to disconnect than closing the tab, we purposefully don't |
| 708 // check if the frame has permission to interact with the device. | 773 // check if the frame has permission to interact with the device. |
| 709 | 774 |
| 710 RenderFrameHostImpl* render_frame_host = | |
| 711 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); | |
| 712 WebContents* web_contents = | |
| 713 WebContents::FromRenderFrameHost(render_frame_host); | |
| 714 if (web_contents) { | |
| 715 web_contents->SetBluetoothDeviceConnected(false); | |
| 716 } | |
| 717 | |
| 718 // The last BluetoothGattConnection for a device closes the connection when | 775 // The last BluetoothGattConnection for a device closes the connection when |
| 719 // it's destroyed. | 776 // it's destroyed. |
| 720 if (device_id_to_connection_map_.erase(device_id)) { | 777 |
| 721 VLOG(1) << "Disconnecting device: " << device_id; | 778 // This only catches disconnections from the renderer. If the device |
| 722 } | 779 // disconnects by itself, or the renderer frame has been deleted |
| 780 // due to navigation, we will not hide the indicator. |
| 781 // TODO(ortuno): Once we move to Frame and Mojo we will be able |
| 782 // to observe the frame's lifetime and hide the indicator when necessary. |
| 783 // http://crbug.com/508771 |
| 784 connected_devices_map_->Remove(frame_routing_id, device_id); |
| 723 } | 785 } |
| 724 | 786 |
| 725 void BluetoothDispatcherHost::OnGetPrimaryService( | 787 void BluetoothDispatcherHost::OnGetPrimaryService( |
| 726 int thread_id, | 788 int thread_id, |
| 727 int request_id, | 789 int request_id, |
| 728 int frame_routing_id, | 790 int frame_routing_id, |
| 729 const std::string& device_id, | 791 const std::string& device_id, |
| 730 const std::string& service_uuid) { | 792 const std::string& service_uuid) { |
| 731 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 793 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 732 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_PRIMARY_SERVICE); | 794 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_PRIMARY_SERVICE); |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 } | 1462 } |
| 1401 | 1463 |
| 1402 void BluetoothDispatcherHost::OnGATTConnectionCreated( | 1464 void BluetoothDispatcherHost::OnGATTConnectionCreated( |
| 1403 int thread_id, | 1465 int thread_id, |
| 1404 int request_id, | 1466 int request_id, |
| 1405 int frame_routing_id, | 1467 int frame_routing_id, |
| 1406 const std::string& device_id, | 1468 const std::string& device_id, |
| 1407 base::TimeTicks start_time, | 1469 base::TimeTicks start_time, |
| 1408 scoped_ptr<device::BluetoothGattConnection> connection) { | 1470 scoped_ptr<device::BluetoothGattConnection> connection) { |
| 1409 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1471 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1410 device_id_to_connection_map_[device_id] = std::move(connection); | |
| 1411 RecordConnectGATTTimeSuccess(base::TimeTicks::Now() - start_time); | 1472 RecordConnectGATTTimeSuccess(base::TimeTicks::Now() - start_time); |
| 1412 RecordConnectGATTOutcome(UMAConnectGATTOutcome::SUCCESS); | 1473 RecordConnectGATTOutcome(UMAConnectGATTOutcome::SUCCESS); |
| 1413 RenderFrameHostImpl* render_frame_host = | 1474 connected_devices_map_->InsertOrReplace(frame_routing_id, device_id, |
| 1414 RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id); | 1475 std::move(connection)); |
| 1415 WebContents* web_contents = | |
| 1416 WebContents::FromRenderFrameHost(render_frame_host); | |
| 1417 if (web_contents) { | |
| 1418 web_contents->SetBluetoothDeviceConnected(true); | |
| 1419 } | |
| 1420 Send(new BluetoothMsg_GATTServerConnectSuccess(thread_id, request_id)); | 1476 Send(new BluetoothMsg_GATTServerConnectSuccess(thread_id, request_id)); |
| 1421 } | 1477 } |
| 1422 | 1478 |
| 1423 void BluetoothDispatcherHost::OnCreateGATTConnectionError( | 1479 void BluetoothDispatcherHost::OnCreateGATTConnectionError( |
| 1424 int thread_id, | 1480 int thread_id, |
| 1425 int request_id, | 1481 int request_id, |
| 1426 const std::string& device_id, | 1482 const std::string& device_id, |
| 1427 base::TimeTicks start_time, | 1483 base::TimeTicks start_time, |
| 1428 device::BluetoothDevice::ConnectErrorCode error_code) { | 1484 device::BluetoothDevice::ConnectErrorCode error_code) { |
| 1429 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1485 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1616 | 1672 |
| 1617 bool BluetoothDispatcherHost::CanFrameAccessCharacteristicInstance( | 1673 bool BluetoothDispatcherHost::CanFrameAccessCharacteristicInstance( |
| 1618 int frame_routing_id, | 1674 int frame_routing_id, |
| 1619 const std::string& characteristic_instance_id) { | 1675 const std::string& characteristic_instance_id) { |
| 1620 return QueryCacheForCharacteristic(GetOrigin(frame_routing_id), | 1676 return QueryCacheForCharacteristic(GetOrigin(frame_routing_id), |
| 1621 characteristic_instance_id) | 1677 characteristic_instance_id) |
| 1622 .outcome != CacheQueryOutcome::BAD_RENDERER; | 1678 .outcome != CacheQueryOutcome::BAD_RENDERER; |
| 1623 } | 1679 } |
| 1624 | 1680 |
| 1625 } // namespace content | 1681 } // namespace content |
| OLD | NEW |