dpa99c / cordova-diagnostic-plugin

Cordova/Phonegap plugin to manage device settings
539 stars 361 forks source link

Requesting camera AND media access permissions together results in ambiguous return value #519

Closed tibbsa closed 1 month ago

tibbsa commented 2 months ago

Bug report

Current behavior:

If an application tries to check the status of camera permissions, or request camera permissions, while also requesting media access permissions at the same time, the return value is ambiguous. The callback accepts only a single 'status' value, but three different permissions are being sought for. It is entirely possible for a user to agree to allowing camera access, but then deny access to media read/write. In that case, the 'status' value in the callback is DENIED, even though the user did in fact grant camera access.

Expected behavior:

If both camera and storage permissions are being requested together, the callback value should delineate the result of each permission request. Since this in and of itself would be a breaking change for existing applications, it may be more sensible to separate this into two separate permissions check/request functions instead of combining camera and media access together.

Steps to reproduce:

More information on how I came to this conclusion is below, but this behaviour is obvious and reproduced in the example project as well. Grant access to the camera but not media, and the status display still shows the camera as being not authorized.

08-28 08:10:11.981  9553  9553 I chromium: [INFO:CONSOLE(401)] "[QRCodeScan] Beginning requestCameraPermissions()", source: https://localhost/js/21.js (401)
...
08-28 08:10:11.983  9553  9708 V Diagnostic: Get authorisation status for android.permission.CAMERA
08-28 08:10:11.984  9553  9708 V Diagnostic: Get authorisation status for android.permission.READ_MEDIA_IMAGES
08-28 08:10:11.985  9553  9708 V Diagnostic: Get authorisation status for android.permission.READ_MEDIA_VIDEO
08-28 08:10:11.986  9553  9708 D Diagnostic: Requesting permission for android.permission.CAMERA
08-28 08:10:11.986  9553  9708 D Diagnostic: Requesting permission for android.permission.READ_MEDIA_IMAGES
08-28 08:10:11.986  9553  9708 D Diagnostic: Requesting permission for android.permission.READ_MEDIA_VIDEO
08-28 08:10:11.986  9553  9708 V Diagnostic: Requesting permissions
...
08-28 08:10:13.805  9553  9553 V Diagnostic: Received result for permissions request id=746214
...
08-28 08:10:13.815  9553  9553 V Diagnostic: Authorisation for CAMERA is GRANTED
08-28 08:10:13.817  9553  9553 V Diagnostic: Authorisation for READ_MEDIA_IMAGES is DENIED_ALWAYS
08-28 08:10:13.818  9553  9553 V Diagnostic: Authorisation for READ_MEDIA_VIDEO is DENIED_ALWAYS
...
08-28 08:10:13.853  9553  9553 I chromium: [INFO:CONSOLE(404)] "[QRCodeScan] Result from requestCameraAuthorization:  DENIED_ALWAYS", source: https://localhost/js/21.js (404)

It seems that Cordova Diagnostics seems that CAMERA permission was GRANTED, and yet when the result is returned to my app it has changed to DENIED_ALWAYS.

Adding some diagnostic logging to the Cordova diagnostics plugin, getCameraAuthorizationStatus is receiving this back from `Diagnostic.instance._getPermissionsAuthorizationStatus()":

Diagnostic_Camera: {"CAMERA":"GRANTED","READ_MEDIA_IMAGES":"DENIED
_ALWAYS","READ_MEDIA_VIDEO":"DENIED_ALWAYS"}

But then somewhere between receiving that and handing off the JSONObject to callbackContext.success(statuses), we lose the fact that there are in fact 3 different permissions being returned, and somehow my callback is only getting DENIED_ALWAYS even though CAMERA was granted.

I traced callbackContext.success() through to a call to Cordova Webview’s sendPluginResult() but I do not know how that is implemented. It seems to be ‘losing’ the additional information there, though.

Environment information

Quasar 2.16.9, Cordova 12.0.0, Cordova-Android 13.0.0, Cordova-IOS 7.1.1, Cordova Plugin Diagnostic 7.1.4.

Runtime issue

Related code:

From the example project:

        cordova.plugins.diagnostic.getCameraAuthorizationStatus({
            successCallback: function (status) {
                $('#state .camera-authorization-status').find('.value').text(status.toUpperCase());
                onGetCameraAuthorizationStatus(status);
            },
            errorCallback: handleError,
            externalStorage: true
        });

        cordova.plugins.diagnostic.requestCameraAuthorization({
            successCallback: function(status){
                log("Successfully requested camera authorization: authorization was " + status);
                checkState();
            },
            errorCallback: handleError,
            externalStorage: true
        });

Console output

n/a

Other information:

n/a

dpa99c commented 1 month ago

This should be resolved in plugin v7.2.0 which was just published. This changes getCameraAuthorizationStatus() to natively derive the single combined status result based upon build SDK version and requested permission statuses. It also adds getCameraAuthorizationStatuses() to return the individual statuses of requested permissions related to camera, so you can interpret and combine the logic of these permission results yourself.