Index: content/browser/bluetooth/web_bluetooth_service_impl.cc |
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc |
index 0a8728f10d54b3c631d23bbbcc2d1a65819dc5a5..b50f2320ce3bd14da021a7dda48f2e433f53c46f 100644 |
--- a/content/browser/bluetooth/web_bluetooth_service_impl.cc |
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc |
@@ -4,7 +4,7 @@ |
// ID Not In Map Note: |
// A service, characteristic, or descriptor ID not in the corresponding |
-// BluetoothDispatcherHost map [service_id_to_device_address_, |
+// WebBluetoothServiceImpl map [service_id_to_device_address_, |
// characteristic_id_to_service_id_, descriptor_to_characteristic_] implies a |
// hostile renderer because a renderer obtains the corresponding ID from this |
// class and it will be added to the map at that time. |
@@ -13,11 +13,15 @@ |
#include <algorithm> |
+#include "base/strings/utf_string_conversions.h" |
#include "base/thread_task_runner_handle.h" |
+#include "content/browser/bluetooth/bluetooth_adapter_factory_wrapper.h" |
#include "content/browser/bluetooth/bluetooth_blacklist.h" |
-#include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
+#include "content/browser/bluetooth/bluetooth_device_provider.h" |
+#include "content/browser/bluetooth/bluetooth_metrics.h" |
#include "content/browser/bluetooth/frame_connected_bluetooth_devices.h" |
#include "content/browser/renderer_host/render_process_host_impl.h" |
+#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/navigation_handle.h" |
#include "content/public/browser/render_frame_host.h" |
#include "content/public/browser/web_contents.h" |
@@ -170,13 +174,11 @@ WebBluetoothServiceImpl::WebBluetoothServiceImpl( |
weak_ptr_factory_(this) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
CHECK(web_contents()); |
- |
- GetBluetoothDispatcherHost()->AddAdapterObserver(this); |
} |
WebBluetoothServiceImpl::~WebBluetoothServiceImpl() { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- GetBluetoothDispatcherHost()->RemoveAdapterObserver(this); |
+ GetBluetoothAdapterFactoryWrapper()->ReleaseAdapter(this); |
} |
void WebBluetoothServiceImpl::SetClientConnectionErrorHandler( |
@@ -193,11 +195,21 @@ void WebBluetoothServiceImpl::DidFinishNavigation( |
} |
} |
-void WebBluetoothServiceImpl::AdapterPresentChanged( |
+void WebBluetoothServiceImpl::AdapterPoweredChanged( |
device::BluetoothAdapter* adapter, |
- bool present) { |
- if (!present) { |
- ClearState(); |
Jeffrey Yasskin
2016/05/13 04:41:59
Is removing this going to bring https://crbug.com/
ortuno
2016/05/13 20:11:18
Noup! That bug happened because the adapter in Blu
|
+ bool powered) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ if (device_provider_.get()) { |
+ device_provider_->AdapterPoweredChanged(powered); |
+ } |
+} |
+ |
+void WebBluetoothServiceImpl::DeviceAdded(device::BluetoothAdapter* adapter, |
+ device::BluetoothDevice* device) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ if (device_provider_.get()) { |
+ VLOG(1) << "Adding device to device provider: " << device->GetAddress(); |
+ device_provider_->AddFilteredDevice(*device); |
} |
} |
@@ -275,14 +287,35 @@ void WebBluetoothServiceImpl::SetClient( |
client_.Bind(std::move(client)); |
} |
+void WebBluetoothServiceImpl::RequestDevice( |
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options, |
+ const RequestDeviceCallback& callback) { |
+ RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::REQUEST_DEVICE); |
+ RecordRequestDeviceOptions(options); |
+ |
+ if (!GetBluetoothAdapterFactoryWrapper()->GetAdapter(this)) { |
+ if (GetBluetoothAdapterFactoryWrapper()->IsBluetoothAdapterAvailable()) { |
+ GetBluetoothAdapterFactoryWrapper()->AcquireAdapter( |
+ this, base::Bind(&WebBluetoothServiceImpl::RequestDeviceImpl, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ base::Passed(std::move(options)), callback)); |
+ return; |
+ } |
+ RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER); |
+ callback.Run(blink::mojom::WebBluetoothError::NO_BLUETOOTH_ADAPTER, |
+ nullptr /* device */); |
+ return; |
+ } |
+ RequestDeviceImpl(std::move(options), callback); |
+} |
+ |
void WebBluetoothServiceImpl::RemoteServerConnect( |
const mojo::String& device_id, |
const RemoteServerConnectCallback& callback) { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); |
- const CacheQueryResult query_result = |
- GetBluetoothDispatcherHost()->QueryCacheForDevice(GetOrigin(), device_id); |
+ const CacheQueryResult query_result = QueryCacheForDevice(device_id); |
if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
RecordConnectGATTOutcome(query_result.outcome); |
@@ -335,16 +368,14 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryService( |
RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_PRIMARY_SERVICE); |
RecordGetPrimaryServiceService(device::BluetoothUUID(service_uuid)); |
- if (!GetBluetoothDispatcherHost() |
- ->allowed_devices_map_.IsOriginAllowedToAccessService( |
- GetOrigin(), device_id, service_uuid)) { |
+ if (!allowed_devices_map_.IsOriginAllowedToAccessService( |
+ GetOrigin(), device_id, service_uuid)) { |
callback.Run(blink::mojom::WebBluetoothError::NOT_ALLOWED_TO_ACCESS_SERVICE, |
nullptr /* service */); |
return; |
} |
- const CacheQueryResult query_result = |
- GetBluetoothDispatcherHost()->QueryCacheForDevice(GetOrigin(), device_id); |
+ const CacheQueryResult query_result = QueryCacheForDevice(device_id); |
if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
binding_.Close(); |
@@ -613,6 +644,26 @@ void WebBluetoothServiceImpl::RemoteCharacteristicStopNotifications( |
weak_ptr_factory_.GetWeakPtr(), characteristic_instance_id, callback)); |
} |
+void WebBluetoothServiceImpl::RequestDeviceImpl( |
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options, |
+ const RequestDeviceCallback& callback) { |
+ // requestDevice() can only be called when processing a user-gesture and |
+ // any user gesture outside of a chooser should close the chooser so we should |
+ // never get a request with an open chooser. |
+ CHECK(!device_provider_.get()); |
+ |
+ device_provider_.reset(new BluetoothDeviceProvider( |
+ render_frame_host_, GetBluetoothAdapterFactoryWrapper()->GetAdapter(this), |
+ GetBluetoothAdapterFactoryWrapper()->GetScanDuration())); |
+ |
+ device_provider_->GetDevice( |
+ options->Clone(), base::Bind(&WebBluetoothServiceImpl::OnGetDeviceSuccess, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ base::Passed(options->Clone()), callback), |
Jeffrey Yasskin
2016/05/13 04:41:59
Instead of cloning the options, would it make sens
ortuno
2016/05/13 20:11:18
Done.
|
+ base::Bind(&WebBluetoothServiceImpl::OnGetDeviceFailed, |
+ weak_ptr_factory_.GetWeakPtr(), callback)); |
+} |
+ |
void WebBluetoothServiceImpl::RemoteServerGetPrimaryServiceImpl( |
const std::string& service_uuid, |
const RemoteServerGetPrimaryServiceCallback& callback, |
@@ -648,6 +699,60 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryServiceImpl( |
std::move(service_ptr)); |
} |
+void WebBluetoothServiceImpl::OnGetDeviceSuccess( |
+ blink::mojom::WebBluetoothRequestDeviceOptionsPtr options, |
+ const RequestDeviceCallback& callback, |
+ const std::string& device_address) { |
+ blink::mojom::WebBluetoothDevicePtr device_ptr = |
Jeffrey Yasskin
2016/05/13 04:41:59
I'd probably create this just before it's used for
ortuno
2016/05/13 20:11:18
Done.
|
+ blink::mojom::WebBluetoothDevice::New(); |
+ |
+ const device::BluetoothDevice* const device = |
+ GetBluetoothAdapterFactoryWrapper()->GetAdapter(this)->GetDevice( |
Jeffrey Yasskin
2016/05/13 04:41:59
Consider wrapping the "GetBluetoothAdapterFactoryW
ortuno
2016/05/13 20:11:18
Done.
|
+ device_address); |
+ if (device == nullptr) { |
+ VLOG(1) << "Device " << device_address << " no longer in adapter"; |
+ RecordRequestDeviceOutcome(UMARequestDeviceOutcome::CHOSEN_DEVICE_VANISHED); |
+ callback.Run(blink::mojom::WebBluetoothError::CHOSEN_DEVICE_VANISHED, |
+ nullptr /* device */); |
+ device_provider_.reset(); |
Jeffrey Yasskin
2016/05/13 04:41:59
Can you reset this at the beginning of the functio
ortuno
2016/05/13 20:11:18
Done.
|
+ return; |
+ } |
+ |
+ const std::string device_id_for_origin = |
+ allowed_devices_map_.AddDevice(GetOrigin(), device_address, options); |
+ |
+ VLOG(1) << "Device: " << device->GetName(); |
+ VLOG(1) << "UUIDs: "; |
+ |
+ mojo::Array<mojo::String> filtered_uuids; |
+ for (const device::BluetoothUUID& uuid : device->GetUUIDs()) { |
+ if (allowed_devices_map_.IsOriginAllowedToAccessService( |
+ GetOrigin(), device_id_for_origin, uuid.canonical_value())) { |
+ VLOG(1) << "\t Allowed: " << uuid.canonical_value(); |
+ filtered_uuids.push_back(uuid.canonical_value()); |
+ } else { |
+ VLOG(1) << "\t Not Allowed: " << uuid.canonical_value(); |
+ } |
+ } |
+ |
+ device_ptr->id = device_id_for_origin; |
+ device_ptr->name = base::UTF16ToUTF8(device->GetName()); |
+ device_ptr->uuids = std::move(filtered_uuids); |
+ |
+ RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS); |
+ callback.Run(blink::mojom::WebBluetoothError::SUCCESS, std::move(device_ptr)); |
+ device_provider_.reset(); |
+} |
+ |
+void WebBluetoothServiceImpl::OnGetDeviceFailed( |
+ const RequestDeviceCallback& callback, |
+ blink::mojom::WebBluetoothError error) { |
+ // Errors are recorded by the BluetoothDeviceProvider that called this |
Jeffrey Yasskin
2016/05/13 04:41:59
Or just "by *device_provider_."?
ortuno
2016/05/13 20:11:18
Done.
|
+ // function. |
+ callback.Run(error, nullptr /* device */); |
+ device_provider_.reset(); |
+} |
+ |
void WebBluetoothServiceImpl::OnCreateGATTConnectionSuccess( |
const std::string& device_id, |
base::TimeTicks start_time, |
@@ -733,6 +838,29 @@ void WebBluetoothServiceImpl::OnStopNotifySessionComplete( |
callback.Run(); |
} |
+CacheQueryResult WebBluetoothServiceImpl::QueryCacheForDevice( |
+ const std::string& device_id) { |
+ const std::string& device_address = |
+ allowed_devices_map_.GetDeviceAddress(GetOrigin(), device_id); |
+ if (device_address.empty()) { |
+ CrashRendererAndClosePipe(bad_message::BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN); |
+ return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER); |
+ } |
+ |
+ CacheQueryResult result; |
+ result.device = |
+ GetBluetoothAdapterFactoryWrapper()->GetAdapter(this)->GetDevice( |
+ device_address); |
+ |
+ // When a device can't be found in the BluetoothAdapter, that generally |
+ // indicates that it's gone out of range. We reject with a NetworkError in |
+ // that case. |
+ if (result.device == nullptr) { |
+ result.outcome = CacheQueryOutcome::NO_DEVICE; |
+ } |
+ return result; |
+} |
+ |
CacheQueryResult WebBluetoothServiceImpl::QueryCacheForService( |
const std::string& service_instance_id) { |
auto device_iter = service_id_to_device_address_.find(service_instance_id); |
@@ -744,23 +872,14 @@ CacheQueryResult WebBluetoothServiceImpl::QueryCacheForService( |
} |
const std::string& device_id = |
- GetBluetoothDispatcherHost()->allowed_devices_map_.GetDeviceId( |
- GetOrigin(), device_iter->second); |
+ allowed_devices_map_.GetDeviceId(GetOrigin(), device_iter->second); |
// Kill the renderer if origin is not allowed to access the device. |
if (device_id.empty()) { |
CrashRendererAndClosePipe(bad_message::BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN); |
return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER); |
} |
- CacheQueryResult result = |
- GetBluetoothDispatcherHost()->QueryCacheForDevice(GetOrigin(), device_id); |
- |
- // TODO(ortuno): Remove once QueryCacheForDevice closes binding_. |
- // http://crbug.com/508771 |
- if (result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
- binding_.Close(); |
- } |
- |
+ CacheQueryResult result = QueryCacheForDevice(device_id); |
if (result.outcome != CacheQueryOutcome::SUCCESS) { |
return result; |
} |
@@ -768,10 +887,9 @@ CacheQueryResult WebBluetoothServiceImpl::QueryCacheForService( |
result.service = result.device->GetGattService(service_instance_id); |
if (result.service == nullptr) { |
result.outcome = CacheQueryOutcome::NO_SERVICE; |
- } else if (!GetBluetoothDispatcherHost() |
- ->allowed_devices_map_.IsOriginAllowedToAccessService( |
- GetOrigin(), device_id, |
- result.service->GetUUID().canonical_value())) { |
+ } else if (!allowed_devices_map_.IsOriginAllowedToAccessService( |
+ GetOrigin(), device_id, |
+ result.service->GetUUID().canonical_value())) { |
CrashRendererAndClosePipe(bad_message::BDH_SERVICE_NOT_ALLOWED_FOR_ORIGIN); |
return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER); |
} |
@@ -809,10 +927,11 @@ RenderProcessHost* WebBluetoothServiceImpl::GetRenderProcessHost() { |
return render_frame_host_->GetProcess(); |
} |
-BluetoothDispatcherHost* WebBluetoothServiceImpl::GetBluetoothDispatcherHost() { |
+BluetoothAdapterFactoryWrapper* |
+WebBluetoothServiceImpl::GetBluetoothAdapterFactoryWrapper() { |
RenderProcessHostImpl* render_process_host_impl = |
static_cast<RenderProcessHostImpl*>(GetRenderProcessHost()); |
- return render_process_host_impl->GetBluetoothDispatcherHost(); |
+ return render_process_host_impl->GetBluetoothAdapterFactoryWrapper(); |
} |
void WebBluetoothServiceImpl::CrashRendererAndClosePipe( |
@@ -832,6 +951,9 @@ void WebBluetoothServiceImpl::ClearState() { |
service_id_to_device_address_.clear(); |
connected_devices_.reset( |
new FrameConnectedBluetoothDevices(render_frame_host_)); |
+ allowed_devices_map_ = BluetoothAllowedDevicesMap(); |
+ device_provider_.reset(); |
+ GetBluetoothAdapterFactoryWrapper()->ReleaseAdapter(this); |
} |
} // namespace content |