@@ -158,14 +158,11 @@ public void onPermissionRequest(final PermissionRequest request) {
158158 ArrayList <String > requestedAndroidPermissions = new ArrayList <>();
159159 for (String requestedResource : request .getResources ()) {
160160 String androidPermission = null ;
161- String requestPermissionIdentifier = null ;
162161
163162 if (requestedResource .equals (PermissionRequest .RESOURCE_AUDIO_CAPTURE )) {
164163 androidPermission = Manifest .permission .RECORD_AUDIO ;
165- requestPermissionIdentifier = "microphone" ;
166164 } else if (requestedResource .equals (PermissionRequest .RESOURCE_VIDEO_CAPTURE )) {
167165 androidPermission = Manifest .permission .CAMERA ;
168- requestPermissionIdentifier = "camera" ;
169166 } else if (requestedResource .equals (PermissionRequest .RESOURCE_PROTECTED_MEDIA_ID )) {
170167 if (mAllowsProtectedMedia ) {
171168 grantedPermissions .add (requestedResource );
@@ -180,36 +177,43 @@ public void onPermissionRequest(final PermissionRequest request) {
180177 androidPermission = PermissionRequest .RESOURCE_PROTECTED_MEDIA_ID ;
181178 }
182179 }
183- Uri originUri = request .getOrigin ();
184- String host = originUri .getHost ();
180+
185181 // TODO: RESOURCE_MIDI_SYSEX, RESOURCE_PROTECTED_MEDIA_ID.
186- String alertMessage = String .format ("Allow " + host + " to use your " + requestPermissionIdentifier + "?" );
187182 if (androidPermission != null ) {
188183 if (ContextCompat .checkSelfPermission (this .mWebView .getThemedReactContext (), androidPermission ) == PackageManager .PERMISSION_GRANTED ) {
189- AlertDialog .Builder builder = new AlertDialog .Builder (this .mWebView .getContext ());
190- builder .setMessage (alertMessage );
191- builder .setCancelable (false );
192- String finalAndroidPermission = androidPermission ;
193- builder .setPositiveButton ("Allow" , (dialog , which ) -> {
194- permissionRequest = request ;
195- grantedPermissions .add (finalAndroidPermission );
196- requestPermissions (grantedPermissions );
197- });
198- builder .setNegativeButton ("Don't allow" , (dialog , which ) -> {
199- request .deny ();
200- });
201- AlertDialog alertDialog = builder .create ();
202- alertDialog .show ();
203- //Delay making `allow` clickable for 500ms to avoid unwanted presses.
204- Button posButton = alertDialog .getButton (AlertDialog .BUTTON_POSITIVE );
205- posButton .setEnabled (false );
206- this .runDelayed (() -> posButton .setEnabled (true ), 500 );
184+ grantedPermissions .add (requestedResource );
207185 } else {
208186 requestedAndroidPermissions .add (androidPermission );
209187 }
210188 }
211189 }
212190
191+ if (this .shouldShowRequestPermissionDialog (grantedPermissions )) {
192+ String alertMessage = this .getRequestPermissionAlertMessage (request , grantedPermissions );
193+
194+ this .showRequestPermissionDialog (
195+ alertMessage ,
196+ (dialog , which ) -> {
197+ this .grantOrRequestPermission (request , requestedAndroidPermissions );
198+ },
199+ (dialog , which ) -> {
200+ request .deny ();
201+ });
202+ } else {
203+ this .grantOrRequestPermission (request , requestedAndroidPermissions );
204+ }
205+ }
206+
207+ // CW-22083: 如果網頁要求麥克風或攝影機權限,就顯示權限請求對話框。
208+ // 參數只需要傳入已經被授權的權限即可。未授權的權限會由手機系統的權限請求對話框處理。
209+ private boolean shouldShowRequestPermissionDialog (List <String > grantedPermissions ) {
210+ return grantedPermissions .contains (PermissionRequest .RESOURCE_AUDIO_CAPTURE ) ||
211+ grantedPermissions .contains (PermissionRequest .RESOURCE_VIDEO_CAPTURE );
212+ }
213+
214+ // 如果 requestedAndroidPermissions 為空,表示手機系統已經給予所有權限給 app。app 可以直接 grant 權限給 webview。
215+ // 如果 requestedAndroidPermissions 不為空,表示 app 還需要向手機系統請求權限,後續會有 listener 會再 grant 權限給 webview。
216+ private void grantOrRequestPermission (PermissionRequest request , List <String > requestedAndroidPermissions ) {
213217 // If all the permissions are already granted, send the response to the WebView synchronously
214218 if (requestedAndroidPermissions .isEmpty ()) {
215219 if (!grantedPermissions .isEmpty ()) {
@@ -226,6 +230,51 @@ public void onPermissionRequest(final PermissionRequest request) {
226230 requestPermissions (requestedAndroidPermissions );
227231 }
228232
233+ private String getDisplayHostName (PermissionRequest request ) {
234+ try {
235+ Uri originUri = request .getOrigin ();
236+ return originUri .getHost ();
237+ } catch (Exception e ) {
238+ return "" ;
239+ }
240+ }
241+
242+ private String getRequestPermissionAlertMessage (PermissionRequest request , List <String > permissions ) {
243+ List <String > permissionNames = new ArrayList <>();
244+ for (String permission : permissions ) {
245+ switch (permission ) {
246+ case PermissionRequest .RESOURCE_AUDIO_CAPTURE :
247+ permissionNames .add ("microphone" );
248+ break ;
249+ case PermissionRequest .RESOURCE_VIDEO_CAPTURE :
250+ permissionNames .add ("camera" );
251+ break ;
252+ default :
253+ // Skip unknown permissions, just handle audio & video
254+ break ;
255+ }
256+ }
257+
258+ String host = this .getDisplayHostName (request );
259+ String permissionNamesJoined = String .join (" and " , permissionNames );
260+
261+ return String .format ("Allow " + host + " to use your " + permissionNamesJoined + "?" );
262+ }
263+
264+ private void showRequestPermissionDialog (String alertMessage , DialogInterface .OnClickListener onAllow , DialogInterface .OnClickListener onDeny ) {
265+ AlertDialog .Builder builder = new AlertDialog .Builder (this .mWebView .getContext ());
266+ builder .setMessage (alertMessage );
267+ builder .setCancelable (false );
268+ builder .setPositiveButton ("Allow" , onAllow );
269+ builder .setNegativeButton ("Don't allow" , onDeny );
270+ AlertDialog alertDialog = builder .create ();
271+ alertDialog .show ();
272+ //Delay making `allow` clickable for 500ms to avoid unwanted presses.
273+ Button posButton = alertDialog .getButton (AlertDialog .BUTTON_POSITIVE );
274+ posButton .setEnabled (false );
275+ this .runDelayed (() -> posButton .setEnabled (true ), 500 );
276+ }
277+
229278 private void runDelayed (Runnable function , long delayMillis ) {
230279 Handler handler = new Handler ();
231280 handler .postDelayed (function , delayMillis );
0 commit comments