Chromium Code Reviews| 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 |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..daee7b2d642f94d972dcb6ecf76e188be1ddfe76 |
| --- /dev/null |
| +++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc |
| @@ -0,0 +1,175 @@ |
| +// Copyright 2016 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/web_bluetooth_service_impl.h" |
| + |
| +#include <vector> |
| + |
| +#include "content/browser/bluetooth/bluetooth_blacklist.h" |
| +#include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
| +#include "content/browser/renderer_host/render_process_host_impl.h" |
| +#include "content/public/browser/render_frame_host.h" |
| +#include "device/bluetooth/bluetooth_gatt_characteristic.h" |
| + |
| +using device::BluetoothGattService; |
| + |
| +namespace content { |
| + |
| +namespace { |
| + |
| +blink::mojom::WebBluetoothError GetWebError(CacheQueryOutcome outcome) { |
|
Jeffrey Yasskin
2016/03/25 00:48:23
I think this duplication will also go away if you
ortuno
2016/03/29 17:58:34
Done. \o/
|
| + switch (outcome) { |
| + case CacheQueryOutcome::BAD_RENDERER: |
| + NOTREACHED(); |
| + return blink::mojom::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE; |
| + case CacheQueryOutcome::SUCCESS: |
| + return blink::mojom::WebBluetoothError::SUCCESS; |
| + case CacheQueryOutcome::NO_DEVICE: |
| + return blink::mojom::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE; |
| + case CacheQueryOutcome::NO_SERVICE: |
| + return blink::mojom::WebBluetoothError::SERVICE_NO_LONGER_EXISTS; |
| + case CacheQueryOutcome::NO_CHARACTERISTIC: |
| + return blink::mojom::WebBluetoothError::CHARACTERISTIC_NO_LONGER_EXISTS; |
| + } |
| + NOTREACHED(); |
| + return blink::mojom::WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE; |
| +} |
| + |
| +blink::mojom::WebBluetoothError TranslateGATTErrorAndRecord( |
| + BluetoothGattService::GattErrorCode error_code, |
| + UMAGATTOperation operation) { |
| + switch (error_code) { |
| + case BluetoothGattService::GATT_ERROR_UNKNOWN: |
| + RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::UNKNOWN); |
| + return blink::mojom::WebBluetoothError::GATT_UNKNOWN_ERROR; |
| + case BluetoothGattService::GATT_ERROR_FAILED: |
| + RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::FAILED); |
| + return blink::mojom::WebBluetoothError::GATT_UNKNOWN_FAILURE; |
| + case BluetoothGattService::GATT_ERROR_IN_PROGRESS: |
| + RecordGATTOperationOutcome(operation, |
| + UMAGATTOperationOutcome::IN_PROGRESS); |
| + return blink::mojom::WebBluetoothError::GATT_OPERATION_IN_PROGRESS; |
| + case BluetoothGattService::GATT_ERROR_INVALID_LENGTH: |
| + RecordGATTOperationOutcome(operation, |
| + UMAGATTOperationOutcome::INVALID_LENGTH); |
| + return blink::mojom::WebBluetoothError::GATT_INVALID_ATTRIBUTE_LENGTH; |
| + case BluetoothGattService::GATT_ERROR_NOT_PERMITTED: |
| + RecordGATTOperationOutcome(operation, |
| + UMAGATTOperationOutcome::NOT_PERMITTED); |
| + return blink::mojom::WebBluetoothError::GATT_NOT_PERMITTED; |
| + case BluetoothGattService::GATT_ERROR_NOT_AUTHORIZED: |
| + RecordGATTOperationOutcome(operation, |
| + UMAGATTOperationOutcome::NOT_AUTHORIZED); |
| + return blink::mojom::WebBluetoothError::GATT_NOT_AUTHORIZED; |
| + case BluetoothGattService::GATT_ERROR_NOT_PAIRED: |
| + RecordGATTOperationOutcome(operation, |
| + UMAGATTOperationOutcome::NOT_PAIRED); |
| + return blink::mojom::WebBluetoothError::GATT_NOT_PAIRED; |
| + case BluetoothGattService::GATT_ERROR_NOT_SUPPORTED: |
| + RecordGATTOperationOutcome(operation, |
| + UMAGATTOperationOutcome::NOT_SUPPORTED); |
| + return blink::mojom::WebBluetoothError::GATT_NOT_SUPPORTED; |
| + } |
| + NOTREACHED(); |
| + return blink::mojom::WebBluetoothError::GATT_UNTRANSLATED_ERROR_CODE; |
| +} |
| + |
| +} // namespace |
| + |
| +using CacheQueryResult = BluetoothDispatcherHost::CacheQueryResult; |
| + |
| +WebBluetoothServiceImpl::WebBluetoothServiceImpl( |
| + RenderFrameHost* render_frame_host, |
| + blink::mojom::WebBluetoothServiceRequest request) |
| + : render_frame_host_(render_frame_host), |
| + render_process_host_(render_frame_host->GetProcess()), |
| + binding_(this, std::move(request)), |
| + weak_ptr_factory_(this) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + // Bind all future weak pointers to the UI thread. |
| + weak_ptr_on_ui_thread_ = weak_ptr_factory_.GetWeakPtr(); |
| + weak_ptr_on_ui_thread_.get(); // Associates with UI thread. |
| +} |
| + |
| +WebBluetoothServiceImpl::~WebBluetoothServiceImpl() {} |
| + |
| +void WebBluetoothServiceImpl::RemoteCharacteristicWriteValue( |
| + const mojo::String& characteristic_instance_id, |
| + mojo::Array<uint8_t> value, |
| + const RemoteCharacteristicWriteValueCallback& callback) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + RecordWebBluetoothFunctionCall( |
| + UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE); |
| + |
| + // We perform the length check on the renderer side. So if we |
| + // get a value with length > 512, we can assume it's a hostile |
| + // renderer and kill it. |
| + if (value.size() > 512) { |
| + CrashRendererAndClosePipe(bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); |
| + return; |
| + } |
| + |
| + const CacheQueryResult query_result = |
| + GetBluetoothDispatcherHost()->QueryCacheForCharacteristic( |
| + GetOrigin(), characteristic_instance_id); |
| + |
| + if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { |
| + binding_.Close(); |
| + return; |
| + } |
| + |
| + if (query_result.outcome != CacheQueryOutcome::SUCCESS) { |
| + RecordCharacteristicWriteValueOutcome(query_result.outcome); |
| + callback.Run(GetWebError(query_result.outcome)); |
| + return; |
| + } |
| + |
| + if (BluetoothBlacklist::Get().IsExcludedFromWrites( |
| + query_result.characteristic->GetUUID())) { |
| + RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::BLACKLISTED); |
| + callback.Run(blink::mojom::WebBluetoothError::BLACKLISTED_WRITE); |
| + return; |
| + } |
| + |
| + query_result.characteristic->WriteRemoteCharacteristic( |
| + value.To<std::vector<uint8_t>>(), |
| + base::Bind(&WebBluetoothServiceImpl::OnWriteValueSuccess, |
| + weak_ptr_on_ui_thread_, callback), |
| + base::Bind(&WebBluetoothServiceImpl::OnWriteValueFailed, |
| + weak_ptr_on_ui_thread_, callback)); |
| +} |
| + |
| +void WebBluetoothServiceImpl::OnWriteValueSuccess( |
| + const RemoteCharacteristicWriteValueCallback& callback) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::SUCCESS); |
| + callback.Run(blink::mojom::WebBluetoothError::SUCCESS); |
| +} |
| + |
| +void WebBluetoothServiceImpl::OnWriteValueFailed( |
| + const RemoteCharacteristicWriteValueCallback& callback, |
| + device::BluetoothGattService::GattErrorCode error_code) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + callback.Run(TranslateGATTErrorAndRecord( |
|
Jeffrey Yasskin
2016/03/25 00:48:23
Probably keep the comment that "// TranslateGATTEr
ortuno
2016/03/29 17:58:34
It's now called TranslateGATTErrorAndRecord. Do yo
Jeffrey Yasskin
2016/03/29 20:30:02
Good point, probably not.
|
| + error_code, UMAGATTOperation::CHARACTERISTIC_WRITE)); |
| +} |
| + |
| +BluetoothDispatcherHost* WebBluetoothServiceImpl::GetBluetoothDispatcherHost() { |
| + RenderProcessHostImpl* render_process_host_impl = |
| + static_cast<RenderProcessHostImpl*>(render_process_host_); |
| + return render_process_host_impl->GetBluetoothDispatcherHost(); |
| +} |
| + |
| +void WebBluetoothServiceImpl::CrashRendererAndClosePipe( |
| + bad_message::BadMessageReason reason) { |
| + bad_message::ReceivedBadMessage(render_process_host_, reason); |
| + binding_.Close(); |
| +} |
| + |
| +url::Origin WebBluetoothServiceImpl::GetOrigin() { |
| + return render_frame_host_->GetLastCommittedOrigin(); |
| +} |
| + |
| +} // namespace content |