| 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 // We will also need to unregister a characteristic once all the event | 113 // We will also need to unregister a characteristic once all the event |
| 112 // listeners have been removed. See http://crbug.com/541390 | 114 // listeners have been removed. See http://crbug.com/541390 |
| 113 if (eventType == EventTypeNames::characteristicvaluechanged) { | 115 if (eventType == EventTypeNames::characteristicvaluechanged) { |
| 114 WebBluetooth* webbluetooth = | 116 WebBluetooth* webbluetooth = |
| 115 BluetoothSupplement::fromExecutionContext(getExecutionContext()); | 117 BluetoothSupplement::fromExecutionContext(getExecutionContext()); |
| 116 webbluetooth->registerCharacteristicObject( | 118 webbluetooth->registerCharacteristicObject( |
| 117 m_webCharacteristic->characteristicInstanceID, this); | 119 m_webCharacteristic->characteristicInstanceID, this); |
| 118 } | 120 } |
| 119 } | 121 } |
| 120 | 122 |
| 121 class ReadValueCallback : public WebBluetoothReadValueCallbacks { | 123 class GetDescriptorsCallback : public WebBluetoothGetDescriptorsCallbacks { |
| 122 public: | 124 public: |
| 123 ReadValueCallback(BluetoothRemoteGATTCharacteristic* characteristic, | 125 GetDescriptorsCallback(BluetoothRemoteGATTCharacteristic* characteristic, |
| 124 ScriptPromiseResolver* resolver) | 126 mojom::blink::WebBluetoothGATTQueryQuantity quantity, |
| 127 ScriptPromiseResolver* resolver) |
| 128 : m_characteristic(characteristic), |
| 129 m_quantity(quantity), |
| 130 m_resolver(resolver) { |
| 131 // We always check that the device is connected before constructing this |
| 132 // object. |
| 133 CHECK(m_characteristic->gatt()->connected()); |
| 134 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); |
| 135 } |
| 136 |
| 137 void onSuccess(const WebVector<WebBluetoothRemoteGATTDescriptorInit*>& |
| 138 webDescriptors) override { |
| 139 if (!m_resolver->getExecutionContext() || |
| 140 m_resolver->getExecutionContext()->isContextDestroyed()) |
| 141 return; |
| 142 |
| 143 // If the resolver is not in the set of ActiveAlgorithms then the frame |
| 144 // disconnected so we reject. |
| 145 if (!m_characteristic->gatt()->RemoveFromActiveAlgorithms( |
| 146 m_resolver.get())) { |
| 147 m_resolver->reject( |
| 148 DOMException::create(NetworkError, kGATTServerDisconnected)); |
| 149 return; |
| 150 } |
| 151 |
| 152 if (m_quantity == mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE) { |
| 153 DCHECK_EQ(1u, webDescriptors.size()); |
| 154 m_resolver->resolve( |
| 155 m_characteristic->gatt() |
| 156 ->device() |
| 157 ->getOrCreateBluetoothRemoteGATTDescriptor( |
| 158 WTF::wrapUnique(webDescriptors[0]), m_characteristic)); |
| 159 return; |
| 160 } |
| 161 |
| 162 HeapVector<Member<BluetoothRemoteGATTDescriptor>> descriptors; |
| 163 descriptors.reserveInitialCapacity(webDescriptors.size()); |
| 164 for (WebBluetoothRemoteGATTDescriptorInit* webDescriptor : webDescriptors) { |
| 165 descriptors.append(m_characteristic->gatt() |
| 166 ->device() |
| 167 ->getOrCreateBluetoothRemoteGATTDescriptor( |
| 168 WTF::wrapUnique(webDescriptor), m_characteristi
c)); |
| 169 } |
| 170 m_resolver->resolve(descriptors); |
| 171 } |
| 172 |
| 173 void onError( |
| 174 int32_t |
| 175 error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */) |
| 176 override { |
| 177 if (!m_resolver->getExecutionContext() || |
| 178 m_resolver->getExecutionContext()->isContextDestroyed()) |
| 179 return; |
| 180 |
| 181 // If the resolver is not in the set of ActiveAlgorithms then the frame |
| 182 // disconnected so we reject. |
| 183 if (!m_characteristic->gatt()->RemoveFromActiveAlgorithms( |
| 184 m_resolver.get())) { |
| 185 m_resolver->reject( |
| 186 DOMException::create(NetworkError, kGATTServerDisconnected)); |
| 187 return; |
| 188 } |
| 189 |
| 190 m_resolver->reject(BluetoothError::take(m_resolver, error)); |
| 191 } |
| 192 |
| 193 private: |
| 194 Persistent<BluetoothRemoteGATTCharacteristic> m_characteristic; |
| 195 mojom::blink::WebBluetoothGATTQueryQuantity m_quantity; |
| 196 const Persistent<ScriptPromiseResolver> m_resolver; |
| 197 }; |
| 198 |
| 199 ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptor( |
| 200 ScriptState* scriptState, |
| 201 const StringOrUnsignedLong& descriptorUUID, |
| 202 ExceptionState& exceptionState) { |
| 203 String descriptor = |
| 204 BluetoothUUID::getDescriptor(descriptorUUID, exceptionState); |
| 205 if (exceptionState.hadException()) |
| 206 return exceptionState.reject(scriptState); |
| 207 |
| 208 return getDescriptorsImpl(scriptState, |
| 209 mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE, |
| 210 descriptor); |
| 211 } |
| 212 |
| 213 ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptors( |
| 214 ScriptState* scriptState, |
| 215 ExceptionState&) { |
| 216 return getDescriptorsImpl( |
| 217 scriptState, mojom::blink::WebBluetoothGATTQueryQuantity::MULTIPLE); |
| 218 } |
| 219 |
| 220 ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptors( |
| 221 ScriptState* scriptState, |
| 222 const StringOrUnsignedLong& descriptorUUID, |
| 223 ExceptionState& exceptionState) { |
| 224 String descriptor = |
| 225 BluetoothUUID::getDescriptor(descriptorUUID, exceptionState); |
| 226 if (exceptionState.hadException()) |
| 227 return exceptionState.reject(scriptState); |
| 228 |
| 229 return getDescriptorsImpl( |
| 230 scriptState, mojom::blink::WebBluetoothGATTQueryQuantity::MULTIPLE, |
| 231 descriptor); |
| 232 } |
| 233 |
| 234 class CharacteristicReadValueCallback : public WebBluetoothReadValueCallbacks { |
| 235 public: |
| 236 CharacteristicReadValueCallback( |
| 237 BluetoothRemoteGATTCharacteristic* characteristic, |
| 238 ScriptPromiseResolver* resolver) |
| 125 : m_characteristic(characteristic), m_resolver(resolver) { | 239 : m_characteristic(characteristic), m_resolver(resolver) { |
| 126 // We always check that the device is connected before constructing this | 240 // We always check that the device is connected before constructing this |
| 127 // object. | 241 // object. |
| 128 CHECK(m_characteristic->gatt()->connected()); | 242 CHECK(m_characteristic->gatt()->connected()); |
| 129 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); | 243 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); |
| 130 } | 244 } |
| 131 | 245 |
| 132 void onSuccess(const WebVector<uint8_t>& value) override { | 246 void onSuccess(const WebVector<uint8_t>& value) override { |
| 133 if (!m_resolver->getExecutionContext() || | 247 if (!m_resolver->getExecutionContext() || |
| 134 m_resolver->getExecutionContext()->isContextDestroyed()) | 248 m_resolver->getExecutionContext()->isContextDestroyed()) |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 return ScriptPromise::rejectWithDOMException( | 298 return ScriptPromise::rejectWithDOMException( |
| 185 scriptState, | 299 scriptState, |
| 186 DOMException::create(InvalidStateError, kInvalidCharacteristic)); | 300 DOMException::create(InvalidStateError, kInvalidCharacteristic)); |
| 187 } | 301 } |
| 188 | 302 |
| 189 WebBluetooth* webbluetooth = | 303 WebBluetooth* webbluetooth = |
| 190 BluetoothSupplement::fromScriptState(scriptState); | 304 BluetoothSupplement::fromScriptState(scriptState); |
| 191 | 305 |
| 192 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 306 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 193 ScriptPromise promise = resolver->promise(); | 307 ScriptPromise promise = resolver->promise(); |
| 194 webbluetooth->readValue(m_webCharacteristic->characteristicInstanceID, | 308 webbluetooth->characteristicReadValue( |
| 195 new ReadValueCallback(this, resolver)); | 309 m_webCharacteristic->characteristicInstanceID, |
| 310 new CharacteristicReadValueCallback(this, resolver)); |
| 196 | 311 |
| 197 return promise; | 312 return promise; |
| 198 } | 313 } |
| 199 | 314 |
| 200 class WriteValueCallback : public WebBluetoothWriteValueCallbacks { | 315 class CharacteristicWriteValueCallback |
| 316 : public WebBluetoothWriteValueCallbacks { |
| 201 public: | 317 public: |
| 202 WriteValueCallback(BluetoothRemoteGATTCharacteristic* characteristic, | 318 CharacteristicWriteValueCallback( |
| 203 ScriptPromiseResolver* resolver) | 319 BluetoothRemoteGATTCharacteristic* characteristic, |
| 320 ScriptPromiseResolver* resolver) |
| 204 : m_characteristic(characteristic), m_resolver(resolver) { | 321 : m_characteristic(characteristic), m_resolver(resolver) { |
| 205 // We always check that the device is connected before constructing this | 322 // We always check that the device is connected before constructing this |
| 206 // object. | 323 // object. |
| 207 CHECK(m_characteristic->gatt()->connected()); | 324 CHECK(m_characteristic->gatt()->connected()); |
| 208 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); | 325 m_characteristic->gatt()->AddToActiveAlgorithms(m_resolver.get()); |
| 209 } | 326 } |
| 210 | 327 |
| 211 void onSuccess(const WebVector<uint8_t>& value) override { | 328 void onSuccess(const WebVector<uint8_t>& value) override { |
| 212 if (!m_resolver->getExecutionContext() || | 329 if (!m_resolver->getExecutionContext() || |
| 213 m_resolver->getExecutionContext()->isContextDestroyed()) | 330 m_resolver->getExecutionContext()->isContextDestroyed()) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 226 m_resolver->resolve(); | 343 m_resolver->resolve(); |
| 227 } | 344 } |
| 228 | 345 |
| 229 void onError( | 346 void onError( |
| 230 int32_t | 347 int32_t |
| 231 error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */) | 348 error /* Corresponds to WebBluetoothResult in web_bluetooth.mojom */) |
| 232 override { | 349 override { |
| 233 if (!m_resolver->getExecutionContext() || | 350 if (!m_resolver->getExecutionContext() || |
| 234 m_resolver->getExecutionContext()->isContextDestroyed()) | 351 m_resolver->getExecutionContext()->isContextDestroyed()) |
| 235 return; | 352 return; |
| 236 | |
| 237 if (!m_characteristic->gatt()->RemoveFromActiveAlgorithms( | 353 if (!m_characteristic->gatt()->RemoveFromActiveAlgorithms( |
| 238 m_resolver.get())) { | 354 m_resolver.get())) { |
| 239 m_resolver->reject( | 355 m_resolver->reject( |
| 240 DOMException::create(NetworkError, kGATTServerDisconnected)); | 356 DOMException::create(NetworkError, kGATTServerDisconnected)); |
| 241 return; | 357 return; |
| 242 } | 358 } |
| 243 | 359 |
| 244 m_resolver->reject(BluetoothError::take(m_resolver, error)); | 360 m_resolver->reject(BluetoothError::take(m_resolver, error)); |
| 245 } | 361 } |
| 246 | 362 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 277 return ScriptPromise::rejectWithDOMException( | 393 return ScriptPromise::rejectWithDOMException( |
| 278 scriptState, DOMException::create(InvalidModificationError, | 394 scriptState, DOMException::create(InvalidModificationError, |
| 279 "Value can't exceed 512 bytes.")); | 395 "Value can't exceed 512 bytes.")); |
| 280 | 396 |
| 281 // Let valueVector be a copy of the bytes held by value. | 397 // Let valueVector be a copy of the bytes held by value. |
| 282 WebVector<uint8_t> valueVector(value.bytes(), value.byteLength()); | 398 WebVector<uint8_t> valueVector(value.bytes(), value.byteLength()); |
| 283 | 399 |
| 284 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 400 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 285 | 401 |
| 286 ScriptPromise promise = resolver->promise(); | 402 ScriptPromise promise = resolver->promise(); |
| 287 webbluetooth->writeValue(m_webCharacteristic->characteristicInstanceID, | 403 webbluetooth->characteristicWriteValue( |
| 288 valueVector, new WriteValueCallback(this, resolver)); | 404 m_webCharacteristic->characteristicInstanceID, valueVector, |
| 405 new CharacteristicWriteValueCallback(this, resolver)); |
| 289 | 406 |
| 290 return promise; | 407 return promise; |
| 291 } | 408 } |
| 292 | 409 |
| 293 class NotificationsCallback : public WebBluetoothNotificationsCallbacks { | 410 class NotificationsCallback : public WebBluetoothNotificationsCallbacks { |
| 294 public: | 411 public: |
| 295 NotificationsCallback(BluetoothRemoteGATTCharacteristic* characteristic, | 412 NotificationsCallback(BluetoothRemoteGATTCharacteristic* characteristic, |
| 296 ScriptPromiseResolver* resolver) | 413 ScriptPromiseResolver* resolver) |
| 297 : m_characteristic(characteristic), m_resolver(resolver) { | 414 : m_characteristic(characteristic), m_resolver(resolver) { |
| 298 // We always check that the device is connected before constructing this | 415 // We always check that the device is connected before constructing this |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 | 498 |
| 382 WebBluetooth* webbluetooth = | 499 WebBluetooth* webbluetooth = |
| 383 BluetoothSupplement::fromScriptState(scriptState); | 500 BluetoothSupplement::fromScriptState(scriptState); |
| 384 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 501 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 385 ScriptPromise promise = resolver->promise(); | 502 ScriptPromise promise = resolver->promise(); |
| 386 webbluetooth->stopNotifications(m_webCharacteristic->characteristicInstanceID, | 503 webbluetooth->stopNotifications(m_webCharacteristic->characteristicInstanceID, |
| 387 new NotificationsCallback(this, resolver)); | 504 new NotificationsCallback(this, resolver)); |
| 388 return promise; | 505 return promise; |
| 389 } | 506 } |
| 390 | 507 |
| 508 ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptorsImpl( |
| 509 ScriptState* scriptState, |
| 510 mojom::blink::WebBluetoothGATTQueryQuantity quantity, |
| 511 const String& descriptor) { |
| 512 WebBluetooth* webbluetooth = |
| 513 BluetoothSupplement::fromScriptState(scriptState); |
| 514 |
| 515 if (!gatt()->connected()) { |
| 516 return ScriptPromise::rejectWithDOMException( |
| 517 scriptState, |
| 518 DOMException::create(NetworkError, kGATTServerNotConnected)); |
| 519 } |
| 520 |
| 521 if (!gatt()->device()->isValidCharacteristic( |
| 522 m_webCharacteristic->characteristicInstanceID)) { |
| 523 return ScriptPromise::rejectWithDOMException( |
| 524 scriptState, |
| 525 DOMException::create(InvalidStateError, kInvalidCharacteristic)); |
| 526 } |
| 527 |
| 528 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 529 ScriptPromise promise = resolver->promise(); |
| 530 |
| 531 webbluetooth->getDescriptors( |
| 532 m_webCharacteristic->characteristicInstanceID, |
| 533 static_cast<int32_t>(quantity), descriptor, |
| 534 new GetDescriptorsCallback(this, quantity, resolver)); |
| 535 |
| 536 return promise; |
| 537 } |
| 538 |
| 391 DEFINE_TRACE(BluetoothRemoteGATTCharacteristic) { | 539 DEFINE_TRACE(BluetoothRemoteGATTCharacteristic) { |
| 392 visitor->trace(m_service); | 540 visitor->trace(m_service); |
| 393 visitor->trace(m_properties); | 541 visitor->trace(m_properties); |
| 394 visitor->trace(m_value); | 542 visitor->trace(m_value); |
| 395 EventTargetWithInlineData::trace(visitor); | 543 EventTargetWithInlineData::trace(visitor); |
| 396 SuspendableObject::trace(visitor); | 544 SuspendableObject::trace(visitor); |
| 397 } | 545 } |
| 398 | 546 |
| 399 } // namespace blink | 547 } // namespace blink |
| OLD | NEW |