@@ -116,7 +116,7 @@ public class WebViewAuthorizationFragment extends AuthorizationFragment {
116116
117117 private boolean webViewZoomEnabled ;
118118
119- private PermissionRequest mCameraPermissionRequest ;
119+ private CameraPermissionRequest mCameraPermissionRequest ;
120120
121121 // This is used by LegacyFido2ApiManager to launch a PendingIntent received by the legacy API.
122122 private ActivityResultLauncher <LegacyFido2ApiObject > mFidoLauncher ;
@@ -277,29 +277,29 @@ public void onPermissionRequest(final PermissionRequest request) {
277277 // We can only grant or deny permissions for video capture/camera.
278278 // To avoid unintentionally granting requests for not defined permissions
279279 // we check if the request is for camera.
280- if (!isPermissionRequestForCamera (request )) {
280+ if (!CameraPermissionRequest . isValidRequest (request )) {
281281 Logger .warn (methodTag , "Permission request is not for camera." );
282282 request .deny ();
283283 return ;
284284 }
285285 // There is a issue in ESTS UX where it sends multiple camera permission requests.
286286 // So, if there is already a camera permission request in progress we handle it here.
287287 if (mCameraPermissionRequest != null ) {
288- handleRepeatedRequests (request );
288+ Logger .info (methodTag , "Repeated request, granted? " + mCameraPermissionRequest .isGranted ());
289+ handleRepeatedCameraRequests (request );
289290 return ;
290291 }
291292 Logger .info (methodTag , "New camera request." );
292- mCameraPermissionRequest = request ;
293- if (isCameraPermissionGranted ()) {
293+ mCameraPermissionRequest = new CameraPermissionRequest (request );
294+ // If the OS level permission was granted previously,
295+ // we show the rationale to confirm the consent with the current user.
296+ // Otherwise, show the system prompt.
297+ if (isAppCameraPermissionGranted ()) {
294298 Logger .info (methodTag , "Camera permission already granted." );
295- acceptCameraRequest ();
296- } else if (shouldShowRequestPermissionRationale (Manifest .permission .CAMERA )) {
297- Logger .info (methodTag , "Show camera rationale." );
298299 showCameraRationale ();
299300 } else {
300- requestCameraPermissionFromUser ();
301+ requestCameraPermission ();
301302 }
302-
303303 }
304304
305305 @ Override
@@ -323,47 +323,12 @@ public Bitmap getDefaultVideoPoster() {
323323 *
324324 * @param request The permission request.
325325 */
326- @ RequiresApi (api = Build .VERSION_CODES .LOLLIPOP )
327- private void handleRepeatedRequests (@ NonNull final PermissionRequest request ) {
328- final String methodTag = TAG + ":handleRepeatedRequests" ;
329- if (isCameraPermissionGranted ()) {
330- Logger .info (methodTag , "Repeated request, granting the permission." );
331- final String [] cameraPermission = new String [] {
332- PermissionRequest .RESOURCE_VIDEO_CAPTURE
333- };
334- request .grant (cameraPermission );
326+ private void handleRepeatedCameraRequests (@ NonNull final PermissionRequest request ) {
327+ final CameraPermissionRequest duplicatedRequest = new CameraPermissionRequest (request );
328+ if (mCameraPermissionRequest .isGranted ()) {
329+ duplicatedRequest .grant ();
335330 } else {
336- Logger .info (methodTag , "Repeated request, denying the permission" );
337- request .deny ();
338- }
339- }
340-
341- /**
342- * Call this method to grant the permission to access the camera resource.
343- * The granted permission is only valid for the current WebView.
344- * <p>
345- * Note: This method is only available on API level 21 or higher.
346- */
347- private void acceptCameraRequest () {
348- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
349- final String [] cameraPermission = new String [] {
350- PermissionRequest .RESOURCE_VIDEO_CAPTURE
351- };
352- if (mCameraPermissionRequest != null ) {
353- mCameraPermissionRequest .grant (cameraPermission );
354- }
355- }
356- }
357-
358- /**
359- * Call this method to deny the permission to access the camera resource.
360- * <p>
361- * Note: This method is only available on API level 21 or higher.
362- */
363- private void denyCameraRequest () {
364- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP &&
365- mCameraPermissionRequest != null ) {
366- mCameraPermissionRequest .deny ();
331+ duplicatedRequest .deny ();
367332 }
368333 }
369334
@@ -372,50 +337,32 @@ private void denyCameraRequest() {
372337 *
373338 * @return true if the camera permission has been granted, false otherwise.
374339 */
375- private boolean isCameraPermissionGranted () {
340+ private boolean isAppCameraPermissionGranted () {
376341 return ContextCompat .checkSelfPermission (requireContext (), Manifest .permission .CAMERA )
377342 == PackageManager .PERMISSION_GRANTED ;
378343 }
379344
380- /**
381- * Determines whatever if the given permission request is for the camera resource.
382- * <p>
383- * Note: This method is only available on API level 21 or higher.
384- * Devices running on lower API levels will not be able to grant or deny camera permission requests.
385- * getResources() method is only available on API level 21 or higher.
386- *
387- * @param request The permission request.
388- * @return true if the given permission request is for camera, false otherwise.
389- */
390- private boolean isPermissionRequestForCamera (final PermissionRequest request ) {
391- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
392- return request .getResources ().length == 1 &&
393- PermissionRequest .RESOURCE_VIDEO_CAPTURE .equals (request .getResources ()[0 ]);
394- }
395- Logger .warn (TAG , "PermissionRequest.getResources() method is not available on API:"
396- + Build .VERSION .SDK_INT + ". We cannot determine if the request is for camera." );
397- return false ;
398- }
399-
400345 private final ActivityResultLauncher <String > cameraRequestActivity = registerForActivityResult (
401346 new ActivityResultContracts .RequestPermission (),
402347 permissionGranted -> {
403348 Logger .info (TAG , "Camera permission granted: " + permissionGranted );
404349 if (permissionGranted ) {
405- acceptCameraRequest ();
350+ mCameraPermissionRequest . grant ();
406351 }
407352 else {
408- denyCameraRequest ();
353+ mCameraPermissionRequest . deny ();
409354 }
410355 }
411356 );
412357
413358 /**
414359 * Launches the camera permission request for the app.
360+ * Note: if the permission was already granted or denied,
361+ * the user will not be prompted and it will go directly to the callback.
362+ * Using the current state of the permission.
363+ *
415364 */
416- private void requestCameraPermissionFromUser () {
417- final String methodTAG = TAG + ":requestCameraPermissionFromUser" ;
418- Logger .info (methodTAG , "Requesting camera permission." );
365+ private void requestCameraPermission () {
419366 cameraRequestActivity .launch (Manifest .permission .CAMERA );
420367 }
421368
@@ -429,12 +376,11 @@ private void showCameraRationale() {
429376 builder .setMessage (R .string .qr_code_rationale_message )
430377 .setTitle (R .string .qr_code_rationale_header )
431378 .setCancelable (false )
432- .setPositiveButton (R .string .qr_code_rationale_allow , (dialog , id ) -> requestCameraPermissionFromUser ())
433- .setNegativeButton (R .string .qr_code_rationale_block , (dialog , id ) -> denyCameraRequest ());
379+ .setPositiveButton (R .string .qr_code_rationale_allow , (dialog , id ) -> requestCameraPermission ())
380+ .setNegativeButton (R .string .qr_code_rationale_block , (dialog , id ) -> mCameraPermissionRequest . deny ());
434381 builder .show ();
435382 }
436383
437-
438384 /**
439385 * Loads starting authorization request url into WebView.
440386 */
0 commit comments