| 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 05f1ebad273044b90192b6a67022ee333025ba56..71dfa5b2634cc336e95a02d9a31d90138754c8af 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/threading/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_chooser_controller.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);
|
| + ClearState();
|
| }
|
|
|
| void WebBluetoothServiceImpl::SetClientConnectionErrorHandler(
|
| @@ -193,11 +195,22 @@ void WebBluetoothServiceImpl::DidFinishNavigation(
|
| }
|
| }
|
|
|
| -void WebBluetoothServiceImpl::AdapterPresentChanged(
|
| +void WebBluetoothServiceImpl::AdapterPoweredChanged(
|
| device::BluetoothAdapter* adapter,
|
| - bool present) {
|
| - if (!present) {
|
| - ClearState();
|
| + bool powered) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + if (device_chooser_controller_.get()) {
|
| + device_chooser_controller_->AdapterPoweredChanged(powered);
|
| + }
|
| +}
|
| +
|
| +void WebBluetoothServiceImpl::DeviceAdded(device::BluetoothAdapter* adapter,
|
| + device::BluetoothDevice* device) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + if (device_chooser_controller_.get()) {
|
| + VLOG(1) << "Adding device to device chooser controller: "
|
| + << device->GetAddress();
|
| + device_chooser_controller_->AddFilteredDevice(*device);
|
| }
|
| }
|
|
|
| @@ -276,14 +289,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 (!GetAdapter()) {
|
| + 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, GetAdapter());
|
| +}
|
| +
|
| 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);
|
| @@ -336,16 +370,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();
|
| @@ -614,6 +646,27 @@ void WebBluetoothServiceImpl::RemoteCharacteristicStopNotifications(
|
| weak_ptr_factory_.GetWeakPtr(), characteristic_instance_id, callback));
|
| }
|
|
|
| +void WebBluetoothServiceImpl::RequestDeviceImpl(
|
| + blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
|
| + const RequestDeviceCallback& callback,
|
| + device::BluetoothAdapter* adapter) {
|
| + // 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_chooser_controller_.get());
|
| +
|
| + device_chooser_controller_.reset(new BluetoothDeviceChooserController(
|
| + this, render_frame_host_, adapter,
|
| + GetBluetoothAdapterFactoryWrapper().GetScanDuration()));
|
| +
|
| + device_chooser_controller_->GetDevice(
|
| + std::move(options),
|
| + base::Bind(&WebBluetoothServiceImpl::OnGetDeviceSuccess,
|
| + weak_ptr_factory_.GetWeakPtr(), callback),
|
| + base::Bind(&WebBluetoothServiceImpl::OnGetDeviceFailed,
|
| + weak_ptr_factory_.GetWeakPtr(), callback));
|
| +}
|
| +
|
| void WebBluetoothServiceImpl::RemoteServerGetPrimaryServiceImpl(
|
| const std::string& service_uuid,
|
| const RemoteServerGetPrimaryServiceCallback& callback,
|
| @@ -649,6 +702,57 @@ void WebBluetoothServiceImpl::RemoteServerGetPrimaryServiceImpl(
|
| std::move(service_ptr));
|
| }
|
|
|
| +void WebBluetoothServiceImpl::OnGetDeviceSuccess(
|
| + const RequestDeviceCallback& callback,
|
| + blink::mojom::WebBluetoothRequestDeviceOptionsPtr options,
|
| + const std::string& device_address) {
|
| + device_chooser_controller_.reset();
|
| +
|
| + const device::BluetoothDevice* const device =
|
| + GetAdapter()->GetDevice(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 */);
|
| + 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();
|
| + }
|
| + }
|
| +
|
| + blink::mojom::WebBluetoothDevicePtr device_ptr =
|
| + blink::mojom::WebBluetoothDevice::New();
|
| + 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));
|
| +}
|
| +
|
| +void WebBluetoothServiceImpl::OnGetDeviceFailed(
|
| + const RequestDeviceCallback& callback,
|
| + blink::mojom::WebBluetoothError error) {
|
| + // Errors are recorded by the *device_chooser_controller_.
|
| + callback.Run(error, nullptr /* device */);
|
| + device_chooser_controller_.reset();
|
| +}
|
| +
|
| void WebBluetoothServiceImpl::OnCreateGATTConnectionSuccess(
|
| const std::string& device_id,
|
| base::TimeTicks start_time,
|
| @@ -734,6 +838,27 @@ 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 = GetAdapter()->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);
|
| @@ -745,23 +870,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;
|
| }
|
| @@ -769,10 +885,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);
|
| }
|
| @@ -810,10 +925,15 @@ 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();
|
| +}
|
| +
|
| +device::BluetoothAdapter* WebBluetoothServiceImpl::GetAdapter() {
|
| + return GetBluetoothAdapterFactoryWrapper().GetAdapter(this);
|
| }
|
|
|
| void WebBluetoothServiceImpl::CrashRendererAndClosePipe(
|
| @@ -833,6 +953,9 @@ void WebBluetoothServiceImpl::ClearState() {
|
| service_id_to_device_address_.clear();
|
| connected_devices_.reset(
|
| new FrameConnectedBluetoothDevices(render_frame_host_));
|
| + allowed_devices_map_ = BluetoothAllowedDevicesMap();
|
| + device_chooser_controller_.reset();
|
| + GetBluetoothAdapterFactoryWrapper().ReleaseAdapter(this);
|
| }
|
|
|
| } // namespace content
|
|
|