[Bluetooth] Add callbacks registering to GATTServer::registerService 48/244548/7
authorRafal Walczyna <r.walczyna@samsung.com>
Mon, 21 Sep 2020 09:44:22 +0000 (11:44 +0200)
committerRafal Walczyna <r.walczyna@samsung.com>
Wed, 23 Sep 2020 08:56:48 +0000 (10:56 +0200)
Register BluetoothGATT{Characteristic, Descriptor}::{read, write}ValueRequestCallbacks
in BluetoothGATTServer::registerService()

[ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-263
[TASK] https://code.sec.samsung.net/jira/browse/XWALK-2166

[Verification] Tested in Chrome developer console

Change-Id: Iee9a9b03627c5fb3d2b3c7941b128c4483953535
Signed-off-by: Rafal Walczyna <r.walczyna@samsung.com>
src/bluetooth/bluetooth_api.js

index 6f506e8..26ad947 100755 (executable)
@@ -2048,6 +2048,150 @@ BluetoothGATTServerService.prototype.unregister = function() {
     }
 };
 
+function _setReadWriteValueRequestCallbacksIfPresent(
+    object,
+    readValueRequestCallback,
+    readValueSendResponseSuccessCallback,
+    readValueSendResponseErrorCallback,
+    writeValueRequestCallback,
+    writeValueSendResponseSuccessCallback,
+    writeValueSendResponseErrorCallback,
+    successCallback,
+    errorCallback
+) {
+    if (
+        object instanceof BluetoothGATTServerCharacteristic ||
+        object instanceof BluetoothGATTServerDescriptor
+    ) {
+        if (readValueRequestCallback) {
+            object.setReadValueRequestCallback(
+                readValueRequestCallback,
+                successCallback,
+                errorCallback,
+                readValueSendResponseSuccessCallback,
+                readValueSendResponseErrorCallback
+            );
+        }
+        if (writeValueRequestCallback) {
+            object.setWriteValueRequestCallback(
+                writeValueRequestCallback,
+                successCallback,
+                errorCallback,
+                writeValueSendResponseSuccessCallback,
+                writeValueSendResponseErrorCallback
+            );
+        }
+    }
+}
+
+function _countCallbackToRegisterInService(service) {
+    var count = 0;
+    for (var serviceIndex = 0; serviceIndex < service.services.length; ++serviceIndex) {
+        count = count + _countCallbackToRegisterInService(service.services[serviceIndex]);
+    }
+
+    for (
+        var characteristicIndex = 0;
+        characteristicIndex < service.characteristics.length;
+        ++characteristicIndex
+    ) {
+        var characteristic = service.characteristics[characteristicIndex];
+        if (characteristic['_readValueRequestCallback']) {
+            count++;
+        }
+        if (characteristic['_writeValueRequestCallback']) {
+            count++;
+        }
+        for (
+            var descriptorIndex = 0;
+            descriptorIndex < characteristic.descriptors.length;
+            ++descriptorIndex
+        ) {
+            var descriptor = characteristic.descriptors[descriptorIndex];
+            if (descriptor['_readValueRequestCallback']) {
+                count++;
+            }
+            if (descriptor['_writeValueRequestCallback']) {
+                count++;
+            }
+        }
+    }
+    return count;
+}
+
+function _registerReadWriteValueRequestCallbacksInGATTServiceRecursively(
+    service,
+    callbacksAggregator
+) {
+    for (var serviceIndex = 0; serviceIndex < service.services.length; ++serviceIndex) {
+        _registerReadWriteValueRequestCallbacksInGATTServiceRecursively(
+            service.services[serviceIndex],
+            callbacksAggregator
+        );
+    }
+
+    for (
+        var characteristicIndex = 0;
+        characteristicIndex < service.characteristics.length;
+        ++characteristicIndex
+    ) {
+        var characteristic = service.characteristics[characteristicIndex];
+        // Callbacks for characteristics
+        _setReadWriteValueRequestCallbacksIfPresent(
+            characteristic,
+            characteristic['_readValueRequestCallback'],
+            characteristic['_readValueSendResponseSuccessCallback'],
+            characteristic['_readValueSendResponseErrorCallback'],
+            characteristic['_writeValueRequestCallback'],
+            characteristic['_writeValueSendResponseSuccessCallback'],
+            characteristic['_writeValueSendResponseErrorCallback'],
+            callbacksAggregator.successCallback,
+            callbacksAggregator.errorCallback
+        );
+        for (
+            var descriptorIndex = 0;
+            descriptorIndex < characteristic.descriptors.length;
+            ++descriptorIndex
+        ) {
+            // Callbacks for descriptors
+            var descriptor = characteristic.descriptors[descriptorIndex];
+            _setReadWriteValueRequestCallbacksIfPresent(
+                descriptor,
+                descriptor['_readValueRequestCallback'],
+                descriptor['_readValueSendResponseSuccessCallback'],
+                descriptor['_readValueSendResponseErrorCallback'],
+                descriptor['_writeValueRequestCallback'],
+                descriptor['_writeValueSendResponseSuccessCallback'],
+                descriptor['_writeValueSendResponseErrorCallback'],
+                callbacksAggregator.successCallback,
+                callbacksAggregator.errorCallback
+            );
+        }
+    }
+}
+
+function _registerReadWriteValueRequestCallbacksInGATTService(
+    service,
+    successCallback,
+    errorCallback
+) {
+    var count = _countCallbackToRegisterInService(service);
+    var callbacksAggregator = new ResultCallbacksAggregator(
+        count,
+        function onAllSucceeded() {
+            successCallback();
+        },
+        function onFailure(error) {
+            errorCallback(error);
+        }
+    );
+
+    _registerReadWriteValueRequestCallbacksInGATTServiceRecursively(
+        service,
+        callbacksAggregator
+    );
+}
+
 var numberArrayToByteArray = function(array) {
     var d = [];
 
@@ -2309,7 +2453,11 @@ var ValidateBluetoothGATTServerCharacteristicInit = function(initData) {
             initData['encryptedSignedReadPermission'] || false,
             initData['encryptedSignedWritePermission'] || false,
             initData['readValueRequestCallback'] || null,
-            initData['writeValueRequestCallback'] || null
+            initData['readValueSendResponseSuccessCallback'] || null,
+            initData['readValueSendResponseErrorCallback'] || null,
+            initData['writeValueRequestCallback'] || null,
+            initData['writeValueSendResponseSuccessCallback'] || null,
+            initData['writeValueSendResponseErrorCallback'] || null
         ],
         [
             {
@@ -2383,9 +2531,29 @@ var ValidateBluetoothGATTServerCharacteristicInit = function(initData) {
                 nullable: true
             },
             {
+                name: 'readValueSendResponseSuccessCallback',
+                type: AV.Types.FUNCTION,
+                nullable: true
+            },
+            {
+                name: 'readValueSendResponseErrorCallback',
+                type: AV.Types.FUNCTION,
+                nullable: true
+            },
+            {
                 name: 'writeValueRequestCallback',
                 type: AV.Types.FUNCTION,
                 nullable: true
+            },
+            {
+                name: 'writeValueSendResponseErrorCallback',
+                type: AV.Types.FUNCTION,
+                nullable: true
+            },
+            {
+                name: 'writeValueSendResponseSuccessCallback',
+                type: AV.Types.FUNCTION,
+                nullable: true
             }
         ]
     );
@@ -2451,7 +2619,49 @@ var BluetoothGATTServerCharacteristic = function(data) {
             },
             set: function() {}
         },
-        // This property is "private" and meant not to be used by users
+        // This properties are "private" and meant not to be used by users
+        _readValueRequestCallback: {
+            enumerable: true,
+            get: function() {
+                return data.readValueRequestCallback;
+            },
+            set: function() {}
+        },
+        _readValueSendResponseSuccessCallback: {
+            enumerable: false,
+            get: function() {
+                return data.readValueSendResponseSuccessCallback;
+            },
+            set: function() {}
+        },
+        _readValueSendResponseErrorCallback: {
+            enumerable: false,
+            get: function() {
+                return data.readValueSendResponseErrorCallback;
+            },
+            set: function() {}
+        },
+        _writeValueRequestCallback: {
+            enumerable: false,
+            get: function() {
+                return data.writeValueRequestCallback;
+            },
+            set: function() {}
+        },
+        _writeValueSendResponseSuccessCallback: {
+            enumerable: false,
+            get: function() {
+                return data.writeValueSendResponseSuccessCallback;
+            },
+            set: function() {}
+        },
+        _writeValueSendResponseErrorCallback: {
+            enumerable: false,
+            get: function() {
+                return data.writeValueSendResponseErrorCallback;
+            },
+            set: function() {}
+        },
         _id: {
             // It has to be enumerable, to be serialized with JSON.stringify()
             enumerable: true,
@@ -3110,7 +3320,11 @@ var ValidateBluetoothGATTServerDescriptorInit = function(initData) {
             initData['encryptedSignedReadPermission'] || false,
             initData['encryptedSignedWritePermission'] || false,
             initData['readValueRequestCallback'] || null,
-            initData['writeValueRequestCallback'] || null
+            initData['readValueSendResponseSuccessCallback'] || null,
+            initData['readValueSendResponseErrorCallback'] || null,
+            initData['writeValueRequestCallback'] || null,
+            initData['writeValueSendResponseSuccessCallback'] || null,
+            initData['writeValueSendResponseErrorCallback'] || null
         ],
         [
             {
@@ -3148,9 +3362,29 @@ var ValidateBluetoothGATTServerDescriptorInit = function(initData) {
                 nullable: true
             },
             {
+                name: 'readValueSendResponseSuccessCallback',
+                type: AV.Types.FUNCTION,
+                nullable: true
+            },
+            {
+                name: 'readValueSendResponseErrorCallback',
+                type: AV.Types.FUNCTION,
+                nullable: true
+            },
+            {
                 name: 'writeValueRequestCallback',
                 type: AV.Types.FUNCTION,
                 nullable: true
+            },
+            {
+                name: 'writeValueSendResponseErrorCallback',
+                type: AV.Types.FUNCTION,
+                nullable: true
+            },
+            {
+                name: 'writeValueSendResponseSuccessCallback',
+                type: AV.Types.FUNCTION,
+                nullable: true
             }
         ]
     );
@@ -3204,7 +3438,49 @@ var BluetoothGATTServerDescriptor = function(data, address) {
             },
             set: function() {}
         },
-        // This property is "private" and meant not to be used by users
+        // This properties are "private" and meant not to be used by users
+        _readValueRequestCallback: {
+            enumerable: false,
+            get: function() {
+                return data.readValueRequestCallback;
+            },
+            set: function() {}
+        },
+        _readValueSendResponseSuccessCallback: {
+            enumerable: false,
+            get: function() {
+                return data.readValueSendResponseSuccessCallback;
+            },
+            set: function() {}
+        },
+        _readValueSendResponseErrorCallback: {
+            enumerable: false,
+            get: function() {
+                return data.readValueSendResponseErrorCallback;
+            },
+            set: function() {}
+        },
+        _writeValueRequestCallback: {
+            enumerable: false,
+            get: function() {
+                return data.writeValueRequestCallback;
+            },
+            set: function() {}
+        },
+        _writeValueSendResponseSuccessCallback: {
+            enumerable: false,
+            get: function() {
+                return data.writeValueSendResponseSuccessCallback;
+            },
+            set: function() {}
+        },
+        _writeValueSendResponseErrorCallback: {
+            enumerable: false,
+            get: function() {
+                return data.writeValueSendResponseErrorCallback;
+            },
+            set: function() {}
+        },
         _id: {
             // It has to be enumerable, to be serialized with JSON.stringify()
             enumerable: true,
@@ -3953,6 +4229,34 @@ BluetoothGATTServer.prototype.registerService = function() {
 
     var service = new BluetoothGATTServerService(args.service);
 
+    // Callback when registering characteristics and descriptors callbacks is successful
+    var successCallback = function() {
+        _BluetoothGATTServerServicesRegisteredInNativeLayer[service._id] = true;
+        _BluetoothGATTServerServices.push(service);
+        native.callIfPossible(args.successCallback);
+    };
+
+    // Callback when registering characteristics and descriptors callbacks fails,
+    // unregister service
+    var errorCallback = function() {
+        var unregisterServiceCallback = function() {
+            native.callIfPossible(args.errorCallback, AbortError);
+        };
+
+        var callArgs = {
+            _id: service._id,
+            idsToRemoveFromNativeLayer: _getIncludedServicesAndItsComponentsIdsRecursively(
+                service
+            )
+        };
+
+        native.call(
+            'BluetoothGATTServerUnregisterService',
+            callArgs,
+            unregisterServiceCallback
+        );
+    };
+
     var callback = function(result) {
         if (native.isFailure(result)) {
             native.callIfPossible(
@@ -3964,9 +4268,11 @@ BluetoothGATTServer.prototype.registerService = function() {
                 )
             );
         } else {
-            _BluetoothGATTServerServicesRegisteredInNativeLayer[service._id] = true;
-            _BluetoothGATTServerServices.push(service);
-            native.callIfPossible(args.successCallback);
+            _registerReadWriteValueRequestCallbacksInGATTService(
+                service,
+                successCallback,
+                errorCallback
+            );
         }
     };