Index: content/browser/bluetooth/bluetooth_dispatcher_host.cc |
diff --git a/content/browser/bluetooth/bluetooth_dispatcher_host.cc b/content/browser/bluetooth/bluetooth_dispatcher_host.cc |
index 85bf81e00038f5b12484100403ac1c7e100a936e..deb626df075cda1a08b08e8fc27ee6164cdd1dbf 100644 |
--- a/content/browser/bluetooth/bluetooth_dispatcher_host.cc |
+++ b/content/browser/bluetooth/bluetooth_dispatcher_host.cc |
@@ -279,6 +279,7 @@ bool BluetoothDispatcherHost::OnMessageReceived(const IPC::Message& message) { |
IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcherHost, message) |
IPC_MESSAGE_HANDLER(BluetoothHostMsg_RequestDevice, OnRequestDevice) |
IPC_MESSAGE_HANDLER(BluetoothHostMsg_ConnectGATT, OnConnectGATT) |
+ IPC_MESSAGE_HANDLER(BluetoothHostMsg_Disconnect, OnDisconnect) |
IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetPrimaryService, OnGetPrimaryService) |
IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetCharacteristic, OnGetCharacteristic) |
IPC_MESSAGE_HANDLER(BluetoothHostMsg_ReadValue, OnReadValue) |
@@ -321,7 +322,7 @@ void BluetoothDispatcherHost::SetBluetoothAdapterForTesting( |
characteristic_to_service_.clear(); |
characteristic_id_to_notify_session_.clear(); |
active_characteristic_threads_.clear(); |
- connections_.clear(); |
+ device_id_to_connection_map_.clear(); |
} |
set_adapter(std::move(mock_adapter)); |
@@ -434,7 +435,6 @@ struct BluetoothDispatcherHost::PrimaryServicesRequest { |
void BluetoothDispatcherHost::set_adapter( |
scoped_refptr<device::BluetoothAdapter> adapter) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- connections_.clear(); |
if (adapter_.get()) |
adapter_->RemoveObserver(this); |
adapter_ = adapter; |
@@ -732,6 +732,17 @@ void BluetoothDispatcherHost::OnConnectGATT(int thread_id, |
return; |
} |
+ // If we are already connected no need to connect again. |
+ auto connection_iter = device_id_to_connection_map_.find(device_id); |
+ if (connection_iter != device_id_to_connection_map_.end()) { |
+ if (connection_iter->second->IsConnected()) { |
+ VLOG(1) << "Already connected."; |
+ Send(new BluetoothMsg_ConnectGATTSuccess(thread_id, request_id, |
+ device_id)); |
+ return; |
+ } |
+ } |
+ |
query_result.device->CreateGattConnection( |
base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, |
weak_ptr_on_ui_thread_, thread_id, request_id, device_id, |
@@ -741,6 +752,31 @@ void BluetoothDispatcherHost::OnConnectGATT(int thread_id, |
start_time)); |
} |
+void BluetoothDispatcherHost::OnDisconnect(int thread_id, |
+ int frame_routing_id, |
+ const std::string& device_id) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ RecordWebBluetoothFunctionCall( |
+ UMAWebBluetoothFunction::REMOTE_GATT_SERVER_DISCONNECT); |
+ |
+ // Make sure the origin is allowed to access the device. We perform this check |
+ // in case a hostile renderer is trying to disconnect a device that the |
+ // renderer is not allowed to access. |
+ if (allowed_devices_map_.GetDeviceAddress(GetOrigin(frame_routing_id), |
+ device_id) |
+ .empty()) { |
+ bad_message::ReceivedBadMessage( |
+ this, bad_message::BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN); |
+ return; |
+ } |
+ |
+ // The last BluetoothGattConnection for a device closes the connection when |
+ // it's destroyed. |
+ if (device_id_to_connection_map_.erase(device_id)) { |
+ VLOG(1) << "Disconnecting device: " << device_id; |
+ } |
+} |
+ |
void BluetoothDispatcherHost::OnGetPrimaryService( |
int thread_id, |
int request_id, |
@@ -1188,7 +1224,7 @@ void BluetoothDispatcherHost::OnGATTConnectionCreated( |
base::TimeTicks start_time, |
scoped_ptr<device::BluetoothGattConnection> connection) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- connections_.push_back(std::move(connection)); |
+ device_id_to_connection_map_[device_id] = std::move(connection); |
RecordConnectGATTTimeSuccess(base::TimeTicks::Now() - start_time); |
RecordConnectGATTOutcome(UMAConnectGATTOutcome::SUCCESS); |
Send(new BluetoothMsg_ConnectGATTSuccess(thread_id, request_id, device_id)); |