OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/bluetooth/BluetoothRemoteGATTCharacteristic.h" | 5 #include "modules/bluetooth/BluetoothRemoteGATTCharacteristic.h" |
6 | 6 |
7 #include "bindings/core/v8/ScriptPromise.h" | 7 #include "bindings/core/v8/ScriptPromise.h" |
8 #include "bindings/core/v8/ScriptPromiseResolver.h" | 8 #include "bindings/core/v8/ScriptPromiseResolver.h" |
9 #include "core/dom/DOMDataView.h" | 9 #include "core/dom/DOMDataView.h" |
10 #include "core/dom/DOMException.h" | 10 #include "core/dom/DOMException.h" |
11 #include "core/dom/ExceptionCode.h" | 11 #include "core/dom/ExceptionCode.h" |
12 #include "core/events/Event.h" | 12 #include "core/events/Event.h" |
13 #include "core/inspector/ConsoleMessage.h" | 13 #include "core/inspector/ConsoleMessage.h" |
14 #include "modules/bluetooth/BluetoothCharacteristicProperties.h" | 14 #include "modules/bluetooth/BluetoothCharacteristicProperties.h" |
15 #include "modules/bluetooth/BluetoothError.h" | 15 #include "modules/bluetooth/BluetoothError.h" |
| 16 #include "modules/bluetooth/BluetoothRemoteGATTDescriptor.h" |
16 #include "modules/bluetooth/BluetoothRemoteGATTService.h" | 17 #include "modules/bluetooth/BluetoothRemoteGATTService.h" |
17 #include "modules/bluetooth/BluetoothSupplement.h" | 18 #include "modules/bluetooth/BluetoothSupplement.h" |
| 19 #include "modules/bluetooth/BluetoothUUID.h" |
18 #include "public/platform/modules/bluetooth/WebBluetooth.h" | 20 #include "public/platform/modules/bluetooth/WebBluetooth.h" |
19 #include <memory> | 21 #include <memory> |
20 | 22 |
21 namespace blink { | 23 namespace blink { |
22 | 24 |
23 namespace { | 25 namespace { |
24 | 26 |
25 const char kGATTServerDisconnected[] = | 27 const char kGATTServerDisconnected[] = |
26 "GATT Server disconnected while performing a GATT operation."; | 28 "GATT Server disconnected while performing a GATT operation."; |
27 const char kGATTServerNotConnected[] = | 29 const char kGATTServerNotConnected[] = |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 // We will also need to unregister a characteristic once all the event | 115 // We will also need to unregister a characteristic once all the event |
114 // listeners have been removed. See http://crbug.com/541390 | 116 // listeners have been removed. See http://crbug.com/541390 |
115 if (eventType == EventTypeNames::characteristicvaluechanged) { | 117 if (eventType == EventTypeNames::characteristicvaluechanged) { |
116 WebBluetooth* webbluetooth = | 118 WebBluetooth* webbluetooth = |
117 BluetoothSupplement::fromExecutionContext(getExecutionContext()); | 119 BluetoothSupplement::fromExecutionContext(getExecutionContext()); |
118 webbluetooth->registerCharacteristicObject( | 120 webbluetooth->registerCharacteristicObject( |
119 m_webCharacteristic->characteristicInstanceID, this); | 121 m_webCharacteristic->characteristicInstanceID, this); |
120 } | 122 } |
121 } | 123 } |
122 | 124 |
123 class ReadValueCallback : public WebBluetoothReadValueCallbacks { | 125 class GetDescriptorsCallback : public WebBluetoothGetDescriptorsCallbacks { |
124 public: | 126 public: |
125 ReadValueCallback(BluetoothRemoteGATTCharacteristic* characteristic, | 127 GetDescriptorsCallback(BluetoothRemoteGATTCharacteristic* characteristic, |
126 ScriptPromiseResolver* resolver) | 128 mojom::blink::WebBluetoothGATTQueryQuantity quantity, |
| 129 ScriptPromiseResolver* resolver) |
| 130 : m_characteristic(characteristic), |
| 131 m_quantity(quantity), |
| 132 m_resolver(resolver) { |
| 133 // We always check that the device is connected before constructing this |
| 134 // object. |
| 135 CHECK(m_characteristic->gatt()->connected()); |
| 136 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); |
| 137 } |
| 138 |
| 139 void onSuccess(const WebVector<WebBluetoothRemoteGATTDescriptorInit*>& |
| 140 webDescriptors) override { |
| 141 if (!m_resolver->getExecutionContext() || |
| 142 m_resolver->getExecutionContext()->isContextDestroyed()) |
| 143 return; |
| 144 |
| 145 // If the resolver is not in the set of ActiveAlgorithms then the frame |
| 146 // disconnected so we reject. |
| 147 if (!m_characteristic->gatt()->RemoveFromActiveAlgorithms( |
| 148 m_resolver.get())) { |
| 149 m_resolver->reject( |
| 150 DOMException::create(NetworkError, kGATTServerDisconnected)); |
| 151 return; |
| 152 } |
| 153 |
| 154 if (m_quantity == mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE) { |
| 155 DCHECK_EQ(1u, webDescriptors.size()); |
| 156 m_resolver->resolve( |
| 157 m_characteristic->gatt() |
| 158 ->device() |
| 159 ->getOrCreateBluetoothRemoteGATTDescriptor( |
| 160 wrapUnique(webDescriptors[0]), m_characteristic)); |
| 161 return; |
| 162 } |
| 163 |
| 164 HeapVector<Member<BluetoothRemoteGATTDescriptor>> descriptors; |
| 165 descriptors.reserveInitialCapacity(webDescriptors.size()); |
| 166 for (WebBluetoothRemoteGATTDescriptorInit* webDescriptor : webDescriptors) { |
| 167 descriptors.append(m_characteristic->gatt() |
| 168 ->device() |
| 169 ->getOrCreateBluetoothRemoteGATTDescriptor( |
| 170 wrapUnique(webDescriptor), m_characteristic)); |
| 171 } |
| 172 m_resolver->resolve(descriptors); |
| 173 } |
| 174 |
| 175 void onError( |
| 176 int32_t |
| 177 error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */) |
| 178 override { |
| 179 if (!m_resolver->getExecutionContext() || |
| 180 m_resolver->getExecutionContext()->isContextDestroyed()) |
| 181 return; |
| 182 |
| 183 // If the resolver is not in the set of ActiveAlgorithms then the frame |
| 184 // disconnected so we reject. |
| 185 if (!m_characteristic->gatt()->RemoveFromActiveAlgorithms( |
| 186 m_resolver.get())) { |
| 187 m_resolver->reject( |
| 188 DOMException::create(NetworkError, kGATTServerDisconnected)); |
| 189 return; |
| 190 } |
| 191 |
| 192 m_resolver->reject(BluetoothError::take(m_resolver, error)); |
| 193 } |
| 194 |
| 195 private: |
| 196 Persistent<BluetoothRemoteGATTCharacteristic> m_characteristic; |
| 197 mojom::blink::WebBluetoothGATTQueryQuantity m_quantity; |
| 198 const Persistent<ScriptPromiseResolver> m_resolver; |
| 199 }; |
| 200 |
| 201 ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptor( |
| 202 ScriptState* scriptState, |
| 203 const StringOrUnsignedLong& descriptorUUID, |
| 204 ExceptionState& exceptionState) { |
| 205 String descriptor = |
| 206 BluetoothUUID::getDescriptor(descriptorUUID, exceptionState); |
| 207 if (exceptionState.hadException()) |
| 208 return exceptionState.reject(scriptState); |
| 209 |
| 210 return getDescriptorsImpl(scriptState, |
| 211 mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE, |
| 212 descriptor); |
| 213 } |
| 214 |
| 215 ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptors( |
| 216 ScriptState* scriptState, |
| 217 ExceptionState&) { |
| 218 return getDescriptorsImpl( |
| 219 scriptState, mojom::blink::WebBluetoothGATTQueryQuantity::MULTIPLE); |
| 220 } |
| 221 |
| 222 ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptors( |
| 223 ScriptState* scriptState, |
| 224 const StringOrUnsignedLong& descriptorUUID, |
| 225 ExceptionState& exceptionState) { |
| 226 String descriptor = |
| 227 BluetoothUUID::getDescriptor(descriptorUUID, exceptionState); |
| 228 if (exceptionState.hadException()) |
| 229 return exceptionState.reject(scriptState); |
| 230 |
| 231 return getDescriptorsImpl( |
| 232 scriptState, mojom::blink::WebBluetoothGATTQueryQuantity::MULTIPLE, |
| 233 descriptor); |
| 234 } |
| 235 |
| 236 class CharacteristicReadValueCallback : public WebBluetoothReadValueCallbacks { |
| 237 public: |
| 238 CharacteristicReadValueCallback( |
| 239 BluetoothRemoteGATTCharacteristic* characteristic, |
| 240 ScriptPromiseResolver* resolver) |
127 : m_characteristic(characteristic), m_resolver(resolver) { | 241 : m_characteristic(characteristic), m_resolver(resolver) { |
128 // We always check that the device is connected before constructing this | 242 // We always check that the device is connected before constructing this |
129 // object. | 243 // object. |
130 CHECK(m_characteristic->gatt()->connected()); | 244 CHECK(m_characteristic->gatt()->connected()); |
131 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); | 245 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); |
132 } | 246 } |
133 | 247 |
134 void onSuccess(const WebVector<uint8_t>& value) override { | 248 void onSuccess(const WebVector<uint8_t>& value) override { |
135 if (!m_resolver->getExecutionContext() || | 249 if (!m_resolver->getExecutionContext() || |
136 m_resolver->getExecutionContext()->isContextDestroyed()) | 250 m_resolver->getExecutionContext()->isContextDestroyed()) |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 return ScriptPromise::rejectWithDOMException( | 300 return ScriptPromise::rejectWithDOMException( |
187 scriptState, | 301 scriptState, |
188 DOMException::create(InvalidStateError, kInvalidCharacteristic)); | 302 DOMException::create(InvalidStateError, kInvalidCharacteristic)); |
189 } | 303 } |
190 | 304 |
191 WebBluetooth* webbluetooth = | 305 WebBluetooth* webbluetooth = |
192 BluetoothSupplement::fromScriptState(scriptState); | 306 BluetoothSupplement::fromScriptState(scriptState); |
193 | 307 |
194 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 308 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
195 ScriptPromise promise = resolver->promise(); | 309 ScriptPromise promise = resolver->promise(); |
196 webbluetooth->readValue(m_webCharacteristic->characteristicInstanceID, | 310 webbluetooth->characteristicReadValue( |
197 new ReadValueCallback(this, resolver)); | 311 m_webCharacteristic->characteristicInstanceID, |
| 312 new CharacteristicReadValueCallback(this, resolver)); |
198 | 313 |
199 return promise; | 314 return promise; |
200 } | 315 } |
201 | 316 |
202 class WriteValueCallback : public WebBluetoothWriteValueCallbacks { | 317 class CharacteristicWriteValueCallback |
| 318 : public WebBluetoothWriteValueCallbacks { |
203 public: | 319 public: |
204 WriteValueCallback(BluetoothRemoteGATTCharacteristic* characteristic, | 320 CharacteristicWriteValueCallback( |
205 ScriptPromiseResolver* resolver) | 321 BluetoothRemoteGATTCharacteristic* characteristic, |
| 322 ScriptPromiseResolver* resolver) |
206 : m_characteristic(characteristic), m_resolver(resolver) { | 323 : m_characteristic(characteristic), m_resolver(resolver) { |
207 // We always check that the device is connected before constructing this | 324 // We always check that the device is connected before constructing this |
208 // object. | 325 // object. |
209 CHECK(m_characteristic->gatt()->connected()); | 326 CHECK(m_characteristic->gatt()->connected()); |
210 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); | 327 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); |
211 } | 328 } |
212 | 329 |
213 void onSuccess(const WebVector<uint8_t>& value) override { | 330 void onSuccess(const WebVector<uint8_t>& value) override { |
214 if (!m_resolver->getExecutionContext() || | 331 if (!m_resolver->getExecutionContext() || |
215 m_resolver->getExecutionContext()->isContextDestroyed()) | 332 m_resolver->getExecutionContext()->isContextDestroyed()) |
(...skipping 12 matching lines...) Expand all Loading... |
228 m_resolver->resolve(); | 345 m_resolver->resolve(); |
229 } | 346 } |
230 | 347 |
231 void onError( | 348 void onError( |
232 int32_t | 349 int32_t |
233 error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */) | 350 error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */) |
234 override { | 351 override { |
235 if (!m_resolver->getExecutionContext() || | 352 if (!m_resolver->getExecutionContext() || |
236 m_resolver->getExecutionContext()->isContextDestroyed()) | 353 m_resolver->getExecutionContext()->isContextDestroyed()) |
237 return; | 354 return; |
238 | |
239 if (!m_characteristic->gatt()->RemoveFromActiveAlgorithms( | 355 if (!m_characteristic->gatt()->RemoveFromActiveAlgorithms( |
240 m_resolver.get())) { | 356 m_resolver.get())) { |
241 m_resolver->reject( | 357 m_resolver->reject( |
242 DOMException::create(NetworkError, kGATTServerDisconnected)); | 358 DOMException::create(NetworkError, kGATTServerDisconnected)); |
243 return; | 359 return; |
244 } | 360 } |
245 | 361 |
246 m_resolver->reject(BluetoothError::take(m_resolver, error)); | 362 m_resolver->reject(BluetoothError::take(m_resolver, error)); |
247 } | 363 } |
248 | 364 |
(...skipping 30 matching lines...) Expand all Loading... |
279 return ScriptPromise::rejectWithDOMException( | 395 return ScriptPromise::rejectWithDOMException( |
280 scriptState, DOMException::create(InvalidModificationError, | 396 scriptState, DOMException::create(InvalidModificationError, |
281 "Value can't exceed 512 bytes.")); | 397 "Value can't exceed 512 bytes.")); |
282 | 398 |
283 // Let valueVector be a copy of the bytes held by value. | 399 // Let valueVector be a copy of the bytes held by value. |
284 WebVector<uint8_t> valueVector(value.bytes(), value.byteLength()); | 400 WebVector<uint8_t> valueVector(value.bytes(), value.byteLength()); |
285 | 401 |
286 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 402 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
287 | 403 |
288 ScriptPromise promise = resolver->promise(); | 404 ScriptPromise promise = resolver->promise(); |
289 webbluetooth->writeValue(m_webCharacteristic->characteristicInstanceID, | 405 webbluetooth->characteristicWriteValue( |
290 valueVector, new WriteValueCallback(this, resolver)); | 406 m_webCharacteristic->characteristicInstanceID, valueVector, |
| 407 new CharacteristicWriteValueCallback(this, resolver)); |
291 | 408 |
292 return promise; | 409 return promise; |
293 } | 410 } |
294 | 411 |
295 class NotificationsCallback : public WebBluetoothNotificationsCallbacks { | 412 class NotificationsCallback : public WebBluetoothNotificationsCallbacks { |
296 public: | 413 public: |
297 NotificationsCallback(BluetoothRemoteGATTCharacteristic* characteristic, | 414 NotificationsCallback(BluetoothRemoteGATTCharacteristic* characteristic, |
298 ScriptPromiseResolver* resolver) | 415 ScriptPromiseResolver* resolver) |
299 : m_characteristic(characteristic), m_resolver(resolver) { | 416 : m_characteristic(characteristic), m_resolver(resolver) { |
300 // We always check that the device is connected before constructing this | 417 // We always check that the device is connected before constructing this |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 | 508 |
392 WebBluetooth* webbluetooth = | 509 WebBluetooth* webbluetooth = |
393 BluetoothSupplement::fromScriptState(scriptState); | 510 BluetoothSupplement::fromScriptState(scriptState); |
394 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 511 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
395 ScriptPromise promise = resolver->promise(); | 512 ScriptPromise promise = resolver->promise(); |
396 webbluetooth->stopNotifications(m_webCharacteristic->characteristicInstanceID, | 513 webbluetooth->stopNotifications(m_webCharacteristic->characteristicInstanceID, |
397 new NotificationsCallback(this, resolver)); | 514 new NotificationsCallback(this, resolver)); |
398 return promise; | 515 return promise; |
399 } | 516 } |
400 | 517 |
| 518 ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptorsImpl( |
| 519 ScriptState* scriptState, |
| 520 mojom::blink::WebBluetoothGATTQueryQuantity quantity, |
| 521 const String& descriptor) { |
| 522 #if OS(MACOSX) |
| 523 // TODO(crbug.com/624017): Remove when descriptors are implemented on MacOS. |
| 524 return ScriptPromise::rejectWithDOMException( |
| 525 scriptState, DOMException::create(NotSupportedError, |
| 526 "getDescriptor[s] is not implemented " |
| 527 "yet. See https://goo.gl/J6ASzs")); |
| 528 #endif // OS(MACOSX) |
| 529 WebBluetooth* webbluetooth = |
| 530 BluetoothSupplement::fromScriptState(scriptState); |
| 531 |
| 532 if (!gatt()->connected()) { |
| 533 return ScriptPromise::rejectWithDOMException( |
| 534 scriptState, |
| 535 DOMException::create(NetworkError, kGATTServerNotConnected)); |
| 536 } |
| 537 |
| 538 if (!gatt()->device()->isValidCharacteristic( |
| 539 m_webCharacteristic->characteristicInstanceID)) { |
| 540 return ScriptPromise::rejectWithDOMException( |
| 541 scriptState, |
| 542 DOMException::create(InvalidStateError, kInvalidCharacteristic)); |
| 543 } |
| 544 |
| 545 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 546 ScriptPromise promise = resolver->promise(); |
| 547 |
| 548 webbluetooth->getDescriptors( |
| 549 m_webCharacteristic->characteristicInstanceID, |
| 550 static_cast<int32_t>(quantity), descriptor, |
| 551 new GetDescriptorsCallback(this, quantity, resolver)); |
| 552 |
| 553 return promise; |
| 554 } |
| 555 |
401 DEFINE_TRACE(BluetoothRemoteGATTCharacteristic) { | 556 DEFINE_TRACE(BluetoothRemoteGATTCharacteristic) { |
402 visitor->trace(m_service); | 557 visitor->trace(m_service); |
403 visitor->trace(m_properties); | 558 visitor->trace(m_properties); |
404 visitor->trace(m_value); | 559 visitor->trace(m_value); |
405 EventTargetWithInlineData::trace(visitor); | 560 EventTargetWithInlineData::trace(visitor); |
406 ActiveDOMObject::trace(visitor); | 561 ActiveDOMObject::trace(visitor); |
407 } | 562 } |
408 | 563 |
409 } // namespace blink | 564 } // namespace blink |
OLD | NEW |