Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp

Issue 2466223002: Implement WebBluetooth getDescriptor[s] (Closed)
Patch Set: Ensure that we throw a kGattServerNotConnected error if getDescriptor[s] is called while not connec… Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "modules/bluetooth/BluetoothRemoteGATTDescriptor.h"
6
7 #include "bindings/core/v8/CallbackPromiseAdapter.h"
8 #include "bindings/core/v8/ScriptPromise.h"
9 #include "bindings/core/v8/ScriptPromiseResolver.h"
10 #include "core/dom/DOMDataView.h"
11 #include "core/dom/DOMException.h"
12 #include "core/dom/ExceptionCode.h"
13 #include "core/events/Event.h"
14 #include "core/inspector/ConsoleMessage.h"
15 #include "modules/bluetooth/BluetoothError.h"
16 #include "modules/bluetooth/BluetoothRemoteGATTService.h"
17 #include "modules/bluetooth/BluetoothSupplement.h"
18 #include "public/platform/modules/bluetooth/WebBluetooth.h"
19 #include <memory>
20
21 namespace blink {
22
23 namespace {
24
25 // TODO dft move to some utility!
26
27 const char kGATTServerDisconnected[] =
28 "GATT Server disconnected while performing a GATT operation.";
29 const char kGATTServerNotConnected[] =
30 "GATT Server is disconnected. Cannot perform GATT operations.";
31
32 DOMDataView* ConvertWebVectorToDataView(const WebVector<uint8_t>& webVector) {
33 static_assert(sizeof(*webVector.data()) == 1,
34 "uint8_t should be a single byte");
35 DOMArrayBuffer* domBuffer =
36 DOMArrayBuffer::create(webVector.data(), webVector.size());
37 return DOMDataView::create(domBuffer, 0, webVector.size());
38 }
39
40 } // anonymous namespace
41
42 BluetoothRemoteGATTDescriptor::BluetoothRemoteGATTDescriptor(
43 ExecutionContext* context,
44 std::unique_ptr<WebBluetoothRemoteGATTDescriptorInit> webDescriptor,
45 BluetoothRemoteGATTService* service)
46 : ActiveDOMObject(context),
47 m_webDescriptor(std::move(webDescriptor)),
48 m_service(service),
49 m_stopped(false) {
50 // See example in Source/platform/heap/ThreadState.h
51 ThreadState::current()->registerPreFinalizer(this);
52 }
53
54 BluetoothRemoteGATTDescriptor* BluetoothRemoteGATTDescriptor::take(
55 ScriptPromiseResolver* resolver,
56 std::unique_ptr<WebBluetoothRemoteGATTDescriptorInit> webDescriptor,
57 BluetoothRemoteGATTService* service) {
58 if (!webDescriptor) {
59 return nullptr;
60 }
61 BluetoothRemoteGATTDescriptor* descriptor = new BluetoothRemoteGATTDescriptor(
62 resolver->getExecutionContext(), std::move(webDescriptor), service);
63 // See note in ActiveDOMObject about suspendIfNeeded.
64 descriptor->suspendIfNeeded();
65 return descriptor;
66 }
67
68 void BluetoothRemoteGATTDescriptor::setValue(DOMDataView* domDataView) {
69 m_value = domDataView;
70 }
71
72 void BluetoothRemoteGATTDescriptor::dispatchDescriptorValueChanged(
73 const WebVector<uint8_t>& value) {
74 this->setValue(ConvertWebVectorToDataView(value));
75 dispatchEvent(Event::create(EventTypeNames::descriptorvaluechanged));
76 }
77
78 void BluetoothRemoteGATTDescriptor::contextDestroyed() {
79 notifyDescriptorObjectRemoved();
80 }
81
82 void BluetoothRemoteGATTDescriptor::dispose() {
83 notifyDescriptorObjectRemoved();
84 }
85
86 void BluetoothRemoteGATTDescriptor::notifyDescriptorObjectRemoved() {
87 if (!m_stopped) {
88 m_stopped = true;
89 WebBluetooth* webbluetooth = BluetoothSupplement::fromExecutionContext(
90 ActiveDOMObject::getExecutionContext());
91 webbluetooth->descriptorObjectRemoved(m_webDescriptor->descriptorInstanceID,
92 this);
93 }
94 }
95
96 const WTF::AtomicString& BluetoothRemoteGATTDescriptor::interfaceName() const {
97 return EventTargetNames::BluetoothRemoteGATTDescriptor;
98 }
99
100 ExecutionContext* BluetoothRemoteGATTDescriptor::getExecutionContext() const {
101 return ActiveDOMObject::getExecutionContext();
102 }
103
104 void BluetoothRemoteGATTDescriptor::addedEventListener(
105 const AtomicString& eventType,
106 RegisteredEventListener& registeredListener) {
107 EventTargetWithInlineData::addedEventListener(eventType, registeredListener);
108 // We will also need to unregister a descriptor once all the event
109 // listeners have been removed. See http://crbug.com/541390
110 if (eventType == EventTypeNames::descriptorvaluechanged) {
111 WebBluetooth* webbluetooth =
112 BluetoothSupplement::fromExecutionContext(getExecutionContext());
113 webbluetooth->registerDescriptorObject(
114 m_webDescriptor->descriptorInstanceID, this);
115 }
116 }
117
118 // TODO dft -- can we move out into a utility
119 class ReadValueCallback : public WebBluetoothReadValueCallbacks {
120 public:
121 ReadValueCallback(BluetoothRemoteGATTDescriptor* descriptor,
122 ScriptPromiseResolver* resolver)
123 : m_descriptor(descriptor), m_resolver(resolver) {
124 // We always check that the device is connected before constructing this
125 // object.
126 CHECK(m_descriptor->gatt()->connected());
127 m_descriptor->gatt()->AddToActiveAlgorithms(m_resolver.get());
128 }
129
130 void onSuccess(const WebVector<uint8_t>& value) override {
131 if (!m_resolver->getExecutionContext() ||
132 m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
133 return;
134
135 if (!m_descriptor->gatt()->RemoveFromActiveAlgorithms(m_resolver.get())) {
136 m_resolver->reject(
137 DOMException::create(NetworkError, kGATTServerDisconnected));
138 return;
139 }
140
141 DOMDataView* domDataView = ConvertWebVectorToDataView(value);
142 if (m_descriptor)
143 m_descriptor->setValue(domDataView);
144
145 m_resolver->resolve(domDataView);
146 }
147
148 void onError(
149 int32_t
150 error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */)
151 override {
152 if (!m_resolver->getExecutionContext() ||
153 m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
154 return;
155
156 if (!m_descriptor->gatt()->RemoveFromActiveAlgorithms(m_resolver.get())) {
157 m_resolver->reject(
158 DOMException::create(NetworkError, kGATTServerDisconnected));
159 return;
160 }
161
162 m_resolver->reject(BluetoothError::take(m_resolver, error));
163 }
164
165 private:
166 WeakPersistent<BluetoothRemoteGATTDescriptor> m_descriptor;
167 Persistent<ScriptPromiseResolver> m_resolver;
168 };
169
170 ScriptPromise BluetoothRemoteGATTDescriptor::readValue(
171 ScriptState* scriptState) {
172 if (!gatt()->connected()) {
173 return ScriptPromise::rejectWithDOMException(
174 scriptState,
175 DOMException::create(NetworkError, kGATTServerNotConnected));
176 }
177
178 WebBluetooth* webbluetooth =
179 BluetoothSupplement::fromScriptState(scriptState);
180
181 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
182 ScriptPromise promise = resolver->promise();
183
184 webbluetooth->descriptorReadValue(m_webDescriptor->descriptorInstanceID,
185 new ReadValueCallback(this, resolver));
186 return promise;
187 }
188
189 class WriteValueCallback : public WebBluetoothWriteValueCallbacks {
190 public:
191 WriteValueCallback(BluetoothRemoteGATTDescriptor* descriptor,
192 ScriptPromiseResolver* resolver)
193 : m_webDescriptor(descriptor), m_resolver(resolver) {}
194
195 void onSuccess(const WebVector<uint8_t>& value) override {
196 if (!m_resolver->getExecutionContext() ||
197 m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
198 return;
199
200 if (m_webDescriptor) {
201 m_webDescriptor->setValue(ConvertWebVectorToDataView(value));
202 }
203 m_resolver->resolve();
204 }
205
206 void onError(
207 int32_t
208 error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */)
209 override {
210 if (!m_resolver->getExecutionContext() ||
211 m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
212 return;
213 m_resolver->reject(BluetoothError::take(m_resolver, error));
214 }
215
216 private:
217 WeakPersistent<BluetoothRemoteGATTDescriptor> m_webDescriptor;
218 Persistent<ScriptPromiseResolver> m_resolver;
219 };
220
221 ScriptPromise BluetoothRemoteGATTDescriptor::writeValue(
222 ScriptState* scriptState,
223 const DOMArrayPiece& value) {
224 WebBluetooth* webbluetooth =
225 BluetoothSupplement::fromScriptState(scriptState);
226
227 // Partial implementation of writeValue algorithm:
228 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattdescri ptor-writevalue
229
230 // If bytes is more than 512 bytes long (the maximum length of an attribute
231 // value, per Long Attribute Values) return a promise rejected with an
232 // InvalidModificationError and abort.
233 if (value.byteLength() > 512) {
234 return ScriptPromise::rejectWithDOMException(
235 scriptState, DOMException::create(InvalidModificationError,
236 "Value can't exceed 512 bytes."));
237 }
238
239 // Let valueVector be a copy of the bytes held by value.
240 WebVector<uint8_t> valueVector(value.bytes(), value.byteLength());
241
242 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
243
244 ScriptPromise promise = resolver->promise();
245 webbluetooth->descriptorWriteValue(m_webDescriptor->descriptorInstanceID,
246 valueVector,
247 new WriteValueCallback(this, resolver));
248
249 return promise;
250 }
251
252 DEFINE_TRACE(BluetoothRemoteGATTDescriptor) {
253 visitor->trace(m_service);
254 visitor->trace(m_characteristic);
255 visitor->trace(m_value);
256 EventTargetWithInlineData::trace(visitor);
257 ActiveDOMObject::trace(visitor);
258 }
259
260 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698