| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
| |
| #include "base/strings/utf_string_conversions.h" |
| #include "content/common/bluetooth/bluetooth_messages.h" |
| #include "device/bluetooth/bluetooth_adapter.h" |
| #include "device/bluetooth/bluetooth_adapter_factory.h" |
| #include "device/bluetooth/bluetooth_device.h" |
| #include "device/bluetooth/bluetooth_discovery_session.h" |
| |
| using device::BluetoothAdapter; |
| using device::BluetoothAdapterFactory; |
| |
| namespace content { |
| |
| const int kScanTime = 5; // 5 seconds of scan time |
| const int kTestingScanTime = 0; // No need to scan for tests |
| |
| BluetoothDispatcherHost::BluetoothDispatcherHost() |
| : BrowserMessageFilter(BluetoothMsgStart), |
| weak_ptr_factory_(this) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| current_scan_time_ = kScanTime; |
| if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) |
| BluetoothAdapterFactory::GetAdapter( |
| base::Bind(&BluetoothDispatcherHost::set_adapter, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void BluetoothDispatcherHost::OnDestruct() const { |
| // See class comment: UI Thread Note. |
| BrowserThread::DeleteOnUIThread::Destruct(this); |
| } |
| |
| void BluetoothDispatcherHost::OverrideThreadForMessage( |
| const IPC::Message& message, |
| content::BrowserThread::ID* thread) { |
| // See class comment: UI Thread Note. |
| *thread = BrowserThread::UI; |
| } |
| |
| bool BluetoothDispatcherHost::OnMessageReceived(const IPC::Message& message) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcherHost, message) |
| IPC_MESSAGE_HANDLER(BluetoothHostMsg_RequestDevice, OnRequestDevice) |
| IPC_MESSAGE_HANDLER(BluetoothHostMsg_ConnectGATT, OnConnectGATT) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| } |
| |
| void BluetoothDispatcherHost::SetBluetoothAdapterForTesting( |
| scoped_refptr<device::BluetoothAdapter> mock_adapter) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| current_scan_time_ = kTestingScanTime; |
| set_adapter(mock_adapter.Pass()); |
| } |
| |
| BluetoothDispatcherHost::~BluetoothDispatcherHost() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| // Clear adapter, releasing observer references. |
| set_adapter(scoped_refptr<device::BluetoothAdapter>()); |
| } |
| |
| void BluetoothDispatcherHost::set_adapter( |
| scoped_refptr<device::BluetoothAdapter> adapter) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| if (adapter_.get()) |
| adapter_->RemoveObserver(this); |
| adapter_ = adapter; |
| if (adapter_.get()) |
| adapter_->AddObserver(this); |
| } |
| |
| void BluetoothDispatcherHost::OnRequestDevice(int thread_id, int request_id) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| // TODO(scheib): Filter devices by services: crbug.com/440594 |
| // TODO(scheib): Device selection UI: crbug.com/436280 |
| // TODO(scheib): Utilize BluetoothAdapter::Observer::DeviceAdded/Removed. |
| if (adapter_.get()) { |
| adapter_->StartDiscoverySession( |
| base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStarted, |
| weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
| base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStartedError, |
| weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| } else { |
| DLOG(WARNING) << "No BluetoothAdapter. Can't serve requestDevice."; |
| Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| BluetoothError::NOT_FOUND)); |
| } |
| return; |
| } |
| |
| void BluetoothDispatcherHost::OnConnectGATT( |
| int thread_id, |
| int request_id, |
| const std::string& device_instance_id) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| // TODO(ortuno): Add actual implementation of connectGATT. This needs to be |
| // done after the "allowed devices map" is implemented. |
| Send(new BluetoothMsg_ConnectGATTSuccess(thread_id, request_id, |
| device_instance_id)); |
| } |
| |
| void BluetoothDispatcherHost::OnDiscoverySessionStarted( |
| int thread_id, |
| int request_id, |
| scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| BrowserThread::PostDelayedTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&BluetoothDispatcherHost::StopDiscoverySession, |
| weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
| base::Passed(&discovery_session)), |
| base::TimeDelta::FromSeconds(current_scan_time_)); |
| } |
| |
| void BluetoothDispatcherHost::OnDiscoverySessionStartedError(int thread_id, |
| int request_id) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStartedError"; |
| Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| BluetoothError::NOT_FOUND)); |
| } |
| |
| void BluetoothDispatcherHost::StopDiscoverySession( |
| int thread_id, |
| int request_id, |
| scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| discovery_session->Stop( |
| base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStopped, |
| weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
| base::Bind(&BluetoothDispatcherHost::OnDiscoverySessionStoppedError, |
| weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
| } |
| |
| void BluetoothDispatcherHost::OnDiscoverySessionStopped(int thread_id, |
| int request_id) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| if (devices.begin() == devices.end()) { |
| Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| BluetoothError::NOT_FOUND)); |
| } else { |
| device::BluetoothDevice* device = *devices.begin(); |
| content::BluetoothDevice device_ipc( |
| device->GetAddress(), // instance_id |
| device->GetName(), // name |
| device->GetBluetoothClass(), // device_class |
| device->GetVendorIDSource(), // vendor_id_source |
| device->GetVendorID(), // vendor_id |
| device->GetProductID(), // product_id |
| device->GetDeviceID(), // product_version |
| device->IsPaired(), // paired |
| content::BluetoothDevice::UUIDsFromBluetoothUUIDs( |
| device->GetUUIDs())); // uuids |
| Send(new BluetoothMsg_RequestDeviceSuccess(thread_id, request_id, |
| device_ipc)); |
| } |
| } |
| |
| void BluetoothDispatcherHost::OnDiscoverySessionStoppedError(int thread_id, |
| int request_id) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| DLOG(WARNING) << "BluetoothDispatcherHost::OnDiscoverySessionStoppedError"; |
| Send(new BluetoothMsg_RequestDeviceError(thread_id, request_id, |
| BluetoothError::NOT_FOUND)); |
| } |
| |
| } // namespace content |