| Index: third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp
|
| diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ddbfe71ee31d80a608ed0632631d41b08d412d70
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp
|
| @@ -0,0 +1,201 @@
|
| +// 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 "modules/bluetooth/BluetoothRemoteGATTDescriptor.h"
|
| +
|
| +#include "bindings/core/v8/CallbackPromiseAdapter.h"
|
| +#include "bindings/core/v8/ScriptPromise.h"
|
| +#include "bindings/core/v8/ScriptPromiseResolver.h"
|
| +#include "core/dom/DOMDataView.h"
|
| +#include "core/dom/DOMException.h"
|
| +#include "core/dom/ExceptionCode.h"
|
| +#include "core/events/Event.h"
|
| +#include "core/inspector/ConsoleMessage.h"
|
| +#include "modules/bluetooth/BluetoothError.h"
|
| +#include "modules/bluetooth/BluetoothRemoteGATTService.h"
|
| +#include "modules/bluetooth/BluetoothSupplement.h"
|
| +#include "public/platform/modules/bluetooth/WebBluetooth.h"
|
| +#include <memory>
|
| +
|
| +namespace blink {
|
| +
|
| +namespace {
|
| +const char kGATTServerDisconnected[] =
|
| + "GATT Server disconnected while performing a GATT operation.";
|
| +const char kGATTServerNotConnected[] =
|
| + "GATT Server is disconnected. Cannot perform GATT operations.";
|
| +
|
| +DOMDataView* ConvertWebVectorToDataView(const WebVector<uint8_t>& webVector) {
|
| + static_assert(sizeof(*webVector.data()) == 1,
|
| + "uint8_t should be a single byte");
|
| + DOMArrayBuffer* domBuffer =
|
| + DOMArrayBuffer::create(webVector.data(), webVector.size());
|
| + return DOMDataView::create(domBuffer, 0, webVector.size());
|
| +}
|
| +
|
| +} // anonymous namespace
|
| +
|
| +BluetoothRemoteGATTDescriptor::BluetoothRemoteGATTDescriptor(
|
| + std::unique_ptr<WebBluetoothRemoteGATTDescriptorInit> webDescriptor,
|
| + BluetoothRemoteGATTCharacteristic* characteristic)
|
| + : m_webDescriptor(std::move(webDescriptor)),
|
| + m_characteristic(characteristic) {}
|
| +
|
| +BluetoothRemoteGATTDescriptor* BluetoothRemoteGATTDescriptor::take(
|
| + std::unique_ptr<WebBluetoothRemoteGATTDescriptorInit> webDescriptor,
|
| + BluetoothRemoteGATTCharacteristic* characteristic) {
|
| + if (!webDescriptor) {
|
| + return nullptr;
|
| + }
|
| + BluetoothRemoteGATTDescriptor* descriptor = new BluetoothRemoteGATTDescriptor(
|
| + std::move(webDescriptor), characteristic);
|
| + return descriptor;
|
| +}
|
| +
|
| +void BluetoothRemoteGATTDescriptor::setValue(DOMDataView* domDataView) {
|
| + m_value = domDataView;
|
| +}
|
| +
|
| +class DescriptorReadValueCallback : public WebBluetoothReadValueCallbacks {
|
| + public:
|
| + DescriptorReadValueCallback(BluetoothRemoteGATTDescriptor* descriptor,
|
| + ScriptPromiseResolver* resolver)
|
| + : m_descriptor(descriptor), m_resolver(resolver) {
|
| + // We always check that the device is connected before constructing this
|
| + // object.
|
| + CHECK(m_descriptor->getGatt()->connected());
|
| + m_descriptor->getGatt()->AddToActiveAlgorithms(m_resolver.get());
|
| + }
|
| +
|
| + void onSuccess(const WebVector<uint8_t>& value) override {
|
| + if (!m_resolver->getExecutionContext() ||
|
| + m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
|
| + return;
|
| +
|
| + if (!m_descriptor->getGatt()->RemoveFromActiveAlgorithms(
|
| + m_resolver.get())) {
|
| + m_resolver->reject(
|
| + DOMException::create(NetworkError, kGATTServerDisconnected));
|
| + return;
|
| + }
|
| +
|
| + DOMDataView* domDataView = ConvertWebVectorToDataView(value);
|
| + if (m_descriptor)
|
| + m_descriptor->setValue(domDataView);
|
| +
|
| + m_resolver->resolve(domDataView);
|
| + }
|
| +
|
| + void onError(
|
| + int32_t
|
| + error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */)
|
| + override {
|
| + if (!m_resolver->getExecutionContext() ||
|
| + m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
|
| + return;
|
| +
|
| + if (!m_descriptor->getGatt()->RemoveFromActiveAlgorithms(
|
| + m_resolver.get())) {
|
| + m_resolver->reject(
|
| + DOMException::create(NetworkError, kGATTServerDisconnected));
|
| + return;
|
| + }
|
| +
|
| + m_resolver->reject(BluetoothError::take(m_resolver, error));
|
| + }
|
| +
|
| + private:
|
| + WeakPersistent<BluetoothRemoteGATTDescriptor> m_descriptor;
|
| + Persistent<ScriptPromiseResolver> m_resolver;
|
| +};
|
| +
|
| +ScriptPromise BluetoothRemoteGATTDescriptor::readValue(
|
| + ScriptState* scriptState) {
|
| + if (!getGatt()->connected()) {
|
| + return ScriptPromise::rejectWithDOMException(
|
| + scriptState,
|
| + DOMException::create(NetworkError, kGATTServerNotConnected));
|
| + }
|
| +
|
| + WebBluetooth* webbluetooth =
|
| + BluetoothSupplement::fromScriptState(scriptState);
|
| +
|
| + ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
|
| + ScriptPromise promise = resolver->promise();
|
| +
|
| + webbluetooth->descriptorReadValue(
|
| + m_webDescriptor->descriptorInstanceID,
|
| + new DescriptorReadValueCallback(this, resolver));
|
| + return promise;
|
| +}
|
| +
|
| +class DescriptorWriteValueCallback : public WebBluetoothWriteValueCallbacks {
|
| + public:
|
| + DescriptorWriteValueCallback(BluetoothRemoteGATTDescriptor* descriptor,
|
| + ScriptPromiseResolver* resolver)
|
| + : m_webDescriptor(descriptor), m_resolver(resolver) {}
|
| +
|
| + void onSuccess(const WebVector<uint8_t>& value) override {
|
| + if (!m_resolver->getExecutionContext() ||
|
| + m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
|
| + return;
|
| +
|
| + if (m_webDescriptor) {
|
| + m_webDescriptor->setValue(ConvertWebVectorToDataView(value));
|
| + }
|
| + m_resolver->resolve();
|
| + }
|
| +
|
| + void onError(
|
| + int32_t
|
| + error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */)
|
| + override {
|
| + if (!m_resolver->getExecutionContext() ||
|
| + m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
|
| + return;
|
| + m_resolver->reject(BluetoothError::take(m_resolver, error));
|
| + }
|
| +
|
| + private:
|
| + WeakPersistent<BluetoothRemoteGATTDescriptor> m_webDescriptor;
|
| + Persistent<ScriptPromiseResolver> m_resolver;
|
| +};
|
| +
|
| +ScriptPromise BluetoothRemoteGATTDescriptor::writeValue(
|
| + ScriptState* scriptState,
|
| + const DOMArrayPiece& value) {
|
| + WebBluetooth* webbluetooth =
|
| + BluetoothSupplement::fromScriptState(scriptState);
|
| +
|
| + // Partial implementation of writeValue algorithm:
|
| + // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattdescriptor-writevalue
|
| +
|
| + // If bytes is more than 512 bytes long (the maximum length of an attribute
|
| + // value, per Long Attribute Values) return a promise rejected with an
|
| + // InvalidModificationError and abort.
|
| + if (value.byteLength() > 512) {
|
| + return ScriptPromise::rejectWithDOMException(
|
| + scriptState, DOMException::create(InvalidModificationError,
|
| + "Value can't exceed 512 bytes."));
|
| + }
|
| +
|
| + // Let valueVector be a copy of the bytes held by value.
|
| + WebVector<uint8_t> valueVector(value.bytes(), value.byteLength());
|
| +
|
| + ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
|
| +
|
| + ScriptPromise promise = resolver->promise();
|
| + webbluetooth->descriptorWriteValue(
|
| + m_webDescriptor->descriptorInstanceID, valueVector,
|
| + new DescriptorWriteValueCallback(this, resolver));
|
| +
|
| + return promise;
|
| +}
|
| +
|
| +DEFINE_TRACE(BluetoothRemoteGATTDescriptor) {
|
| + visitor->trace(m_characteristic);
|
| + visitor->trace(m_value);
|
| +}
|
| +
|
| +} // namespace blink
|
|
|