Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,14 @@ public void onProgressChanged(WebView webView, int newProgress) {
@Override
public void onPermissionRequest(final PermissionRequest request) {

// Reset state to handle new request
grantedPermissions = new ArrayList<>();
permissionRequest = null;

ArrayList<String> requestedAndroidPermissions = new ArrayList<>();
ArrayList<String> permissionsNeedingDialog = new ArrayList<>();
ArrayList<String> permissionLabels = new ArrayList<>();

for (String requestedResource : request.getResources()) {
String androidPermission = null;
String requestPermissionIdentifier = null;
Expand All @@ -179,37 +184,83 @@ public void onPermissionRequest(final PermissionRequest request) {
*/
androidPermission = PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID;
} }
Uri originUri = request.getOrigin();
String host = originUri.getHost();
// TODO: RESOURCE_MIDI_SYSEX, RESOURCE_PROTECTED_MEDIA_ID.
String alertMessage = String.format("Allow " + host + " to use your " + requestPermissionIdentifier + "?");

if (androidPermission != null) {
if (ContextCompat.checkSelfPermission(this.mWebView.getThemedReactContext(), androidPermission) == PackageManager.PERMISSION_GRANTED) {
AlertDialog.Builder builder = new AlertDialog.Builder(this.mWebView.getContext());
builder.setMessage(alertMessage);
builder.setCancelable(false);
String finalAndroidPermission = androidPermission;
builder.setPositiveButton("Allow", (dialog, which) -> {
permissionRequest = request;
grantedPermissions.add(finalAndroidPermission);
requestPermissions(grantedPermissions);
});
builder.setNegativeButton("Don't allow", (dialog, which) -> {
request.deny();
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
//Delay making `allow` clickable for 500ms to avoid unwanted presses.
Button posButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
posButton.setEnabled(false);
this.runDelayed(() -> posButton.setEnabled(true), 500);
// Permission already granted at OS level, but still need user confirmation
permissionsNeedingDialog.add(androidPermission);
permissionLabels.add(requestPermissionIdentifier);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Null Permission Label in Protected Media Dialog

When RESOURCE_PROTECTED_MEDIA_ID permission is requested with mAllowsProtectedMedia=false, the variable requestPermissionIdentifier is never set (remains null). If this permission ends up in the permissionsNeedingDialog path (line 191-192), null is added to permissionLabels. This causes the permission dialog to display "Allow [host] to use your null?" to the user, or "camera and null" if combined with other permissions. The fix should set requestPermissionIdentifier = "protected media" or similar for the RESOURCE_PROTECTED_MEDIA_ID case at line 174-186.

Fix in Cursor Fix in Web

} else {
// Permission not granted at OS level, need to request it
requestedAndroidPermissions.add(androidPermission);
}
}
}

// If all the permissions are already granted, send the response to the WebView synchronously
// Show a SINGLE dialog for all permissions that are already granted at OS level
if (!permissionsNeedingDialog.isEmpty()) {
Uri originUri = request.getOrigin();
String host = originUri.getHost();

// Build message for all requested permissions
String permissionList = String.join(" and ", permissionLabels);
String alertMessage = String.format("Allow %s to use your %s?", host, permissionList);

AlertDialog.Builder builder = new AlertDialog.Builder(this.mWebView.getContext());
builder.setMessage(alertMessage);
builder.setCancelable(false);

builder.setPositiveButton("Allow", (dialog, which) -> {
// Add all permissions to granted list
for (String permission : permissionsNeedingDialog) {
if (permission.equals(Manifest.permission.CAMERA)) {
grantedPermissions.add(PermissionRequest.RESOURCE_VIDEO_CAPTURE);
} else if (permission.equals(Manifest.permission.RECORD_AUDIO)) {
grantedPermissions.add(PermissionRequest.RESOURCE_AUDIO_CAPTURE);
} else if (permission.equals(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID)) {
grantedPermissions.add(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID);
}
}

// If no additional system permissions needed, grant immediately
if (requestedAndroidPermissions.isEmpty()) {
if (!grantedPermissions.isEmpty()) {
try {
request.grant(grantedPermissions.toArray(new String[0]));
} catch (IllegalStateException e) {
// Request was already granted or denied, ignore
} finally {
grantedPermissions = null;
permissionRequest = null;
}
}
// DO NOT set permissionRequest since we're handling it entirely here
} else {
// Still need to request system permissions - set permissionRequest for listener callback
permissionRequest = request;
requestPermissions(requestedAndroidPermissions);
}
});

builder.setNegativeButton("Don't allow", (dialog, which) -> {
request.deny();
// Clean up state
grantedPermissions = null;
permissionRequest = null;
});

AlertDialog alertDialog = builder.create();
alertDialog.show();

//Delay making `allow` clickable for 500ms to avoid unwanted presses.
Button posButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
posButton.setEnabled(false);
this.runDelayed(() -> posButton.setEnabled(true), 500);

return;
}

// If all the permissions are already granted (no dialog needed), send the response to the WebView synchronously
if (requestedAndroidPermissions.isEmpty()) {
if (!grantedPermissions.isEmpty()) {
request.grant(grantedPermissions.toArray(new String[0]));
Expand All @@ -219,9 +270,7 @@ public void onPermissionRequest(final PermissionRequest request) {
}

// Otherwise, ask to Android System for native permissions asynchronously

this.permissionRequest = request;

requestPermissions(requestedAndroidPermissions);
}

Expand Down Expand Up @@ -356,9 +405,14 @@ private synchronized void requestPermissions(List<String> permissions) {
if (shouldAnswerToPermissionRequest
&& permissionRequest != null
&& grantedPermissions != null) {
permissionRequest.grant(grantedPermissions.toArray(new String[0]));
permissionRequest = null;
grantedPermissions = null;
try {
permissionRequest.grant(grantedPermissions.toArray(new String[0]));
} catch (IllegalStateException e) {
// Request was already granted or denied, ignore
} finally {
permissionRequest = null;
grantedPermissions = null;
}
}

if (!pendingPermissions.isEmpty()) {
Expand Down
Loading