OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.permissions; | 5 package org.chromium.chrome.browser.permissions; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.content.DialogInterface; | 8 import android.content.DialogInterface; |
9 import android.content.pm.PackageManager; | 9 import android.content.pm.PackageManager; |
10 import android.support.v7.app.AlertDialog; | 10 import android.support.v7.app.AlertDialog; |
11 import android.util.SparseArray; | 11 import android.util.SparseArray; |
12 import android.view.View; | 12 import android.view.View; |
13 import android.widget.TextView; | 13 import android.widget.TextView; |
14 | 14 |
15 import org.chromium.chrome.R; | 15 import org.chromium.chrome.R; |
16 import org.chromium.chrome.browser.ContentSettingsType; | 16 import org.chromium.chrome.browser.ContentSettingsType; |
17 import org.chromium.chrome.browser.preferences.PrefServiceBridge; | 17 import org.chromium.chrome.browser.preferences.PrefServiceBridge; |
18 import org.chromium.chrome.browser.tab.Tab; | 18 import org.chromium.chrome.browser.tab.Tab; |
19 import org.chromium.ui.base.WindowAndroid; | 19 import org.chromium.ui.base.WindowAndroid; |
20 import org.chromium.ui.base.WindowAndroid.PermissionCallback; | 20 import org.chromium.ui.base.WindowAndroid.PermissionCallback; |
21 | 21 |
| 22 import java.util.ArrayList; |
| 23 import java.util.Collections; |
| 24 import java.util.HashSet; |
| 25 import java.util.List; |
| 26 import java.util.Set; |
| 27 |
22 /** | 28 /** |
23 * Methods to handle requesting native permissions from Android when the user gr
ants a website a | 29 * Methods to handle requesting native permissions from Android when the user gr
ants a website a |
24 * permission. | 30 * permission. |
25 */ | 31 */ |
26 public class AndroidPermissionRequester { | 32 public class AndroidPermissionRequester { |
27 /** | 33 /** |
28 * An interface for classes which need to be informed of the outcome of askin
g a user to grant an | 34 * An interface for classes which need to be informed of the outcome of askin
g a user to grant an |
29 * Android permission. | 35 * Android permission. |
30 */ | 36 */ |
31 public interface RequestDelegate { | 37 public interface RequestDelegate { |
32 void onAndroidPermissionAccepted(); | 38 void onAndroidPermissionAccepted(); |
33 void onAndroidPermissionCanceled(); | 39 void onAndroidPermissionCanceled(); |
34 } | 40 } |
35 | 41 |
36 private static SparseArray<String> generatePermissionsMapping( | 42 private static SparseArray<String[]> generatePermissionsMapping( |
37 WindowAndroid windowAndroid, int[] contentSettingsTypes) { | 43 WindowAndroid windowAndroid, int[] contentSettingsTypes) { |
38 SparseArray<String> permissionsToRequest = new SparseArray<String>(); | 44 SparseArray<String[]> permissionsToRequest = new SparseArray<>(); |
39 for (int i = 0; i < contentSettingsTypes.length; i++) { | 45 for (int i = 0; i < contentSettingsTypes.length; i++) { |
40 String permission = PrefServiceBridge.getAndroidPermissionForContent
Setting( | 46 String[] permissions = PrefServiceBridge.getAndroidPermissionsForCon
tentSetting( |
41 contentSettingsTypes[i]); | 47 contentSettingsTypes[i]); |
42 if (permission != null && !windowAndroid.hasPermission(permission))
{ | 48 if (permissions == null) continue; |
43 permissionsToRequest.append(contentSettingsTypes[i], permission)
; | 49 List<String> missingPermissions = new ArrayList<>(); |
| 50 for (int j = 0; j < permissions.length; j++) { |
| 51 String permission = permissions[j]; |
| 52 if (!windowAndroid.hasPermission(permission)) missingPermissions
.add(permission); |
| 53 } |
| 54 if (!missingPermissions.isEmpty()) { |
| 55 permissionsToRequest.append(contentSettingsTypes[i], |
| 56 missingPermissions.toArray(new String[missingPermissions
.size()])); |
44 } | 57 } |
45 } | 58 } |
46 return permissionsToRequest; | 59 return permissionsToRequest; |
47 } | 60 } |
48 | 61 |
49 private static int getDeniedPermissionResourceId( | 62 private static int getDeniedPermissionResourceId( |
50 SparseArray<String> contentSettingsTypesToPermissionsMap, String per
mission) { | 63 SparseArray<String[]> contentSettingsTypesToPermissionsMap, String p
ermission) { |
51 int contentSettingsType = 0; | 64 int contentSettingsType = 0; |
52 // SparseArray#indexOfValue uses == instead of .equals, so we need to ma
nually iterate | 65 // SparseArray#indexOfValue uses == instead of .equals, so we need to ma
nually iterate |
53 // over the list. | 66 // over the list. |
54 for (int i = 0; i < contentSettingsTypesToPermissionsMap.size(); i++) { | 67 for (int i = 0; i < contentSettingsTypesToPermissionsMap.size(); i++) { |
55 if (permission.equals(contentSettingsTypesToPermissionsMap.valueAt(i
))) { | 68 String[] contentSettingPermissions = contentSettingsTypesToPermissio
nsMap.valueAt(i); |
56 contentSettingsType = contentSettingsTypesToPermissionsMap.keyAt
(i); | 69 for (int j = 0; j < contentSettingPermissions.length; j++) { |
| 70 if (permission.equals(contentSettingPermissions[j])) { |
| 71 contentSettingsType = contentSettingsTypesToPermissionsMap.k
eyAt(i); |
| 72 break; |
| 73 } |
57 } | 74 } |
58 } | 75 } |
59 | 76 |
60 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_GEO
LOCATION) { | 77 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_GEO
LOCATION) { |
61 return R.string.infobar_missing_location_permission_text; | 78 return R.string.infobar_missing_location_permission_text; |
62 } | 79 } |
63 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_MED
IASTREAM_MIC) { | 80 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_MED
IASTREAM_MIC) { |
64 return R.string.infobar_missing_microphone_permission_text; | 81 return R.string.infobar_missing_microphone_permission_text; |
65 } | 82 } |
66 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_MED
IASTREAM_CAMERA) { | 83 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_MED
IASTREAM_CAMERA) { |
67 return R.string.infobar_missing_camera_permission_text; | 84 return R.string.infobar_missing_camera_permission_text; |
68 } | 85 } |
69 assert false : "Unexpected content setting type received: " + contentSet
tingsType; | 86 assert false : "Unexpected content setting type received: " + contentSet
tingsType; |
70 return R.string.infobar_missing_multiple_permissions_text; | 87 return R.string.infobar_missing_multiple_permissions_text; |
71 } | 88 } |
72 | 89 |
73 /** | 90 /** |
74 * Returns true if any of the permissions in contentSettingsTypes must be re
quested from the | 91 * Returns true if any of the permissions in contentSettingsTypes must be re
quested from the |
75 * system. Otherwise returns false. | 92 * system. Otherwise returns false. |
76 * | 93 * |
77 * If true is returned, this method will asynchronously request the necessar
y permissions using | 94 * If true is returned, this method will asynchronously request the necessar
y permissions using |
78 * a dialog, running methods on the RequestDelegate when the user has made a
decision. | 95 * a dialog, running methods on the RequestDelegate when the user has made a
decision. |
79 */ | 96 */ |
80 public static boolean requestAndroidPermissions( | 97 public static boolean requestAndroidPermissions( |
81 final Tab tab, final int[] contentSettingsTypes, final RequestDelega
te delegate) { | 98 final Tab tab, final int[] contentSettingsTypes, final RequestDelega
te delegate) { |
82 final WindowAndroid windowAndroid = tab.getWindowAndroid(); | 99 final WindowAndroid windowAndroid = tab.getWindowAndroid(); |
83 if (windowAndroid == null) return false; | 100 if (windowAndroid == null) return false; |
84 | 101 |
85 final SparseArray<String> contentSettingsTypesToPermissionsMap = | 102 final SparseArray<String[]> contentSettingsTypesToPermissionsMap = |
86 generatePermissionsMapping(windowAndroid, contentSettingsTypes); | 103 generatePermissionsMapping(windowAndroid, contentSettingsTypes); |
87 | 104 |
88 if (contentSettingsTypesToPermissionsMap.size() == 0) return false; | 105 if (contentSettingsTypesToPermissionsMap.size() == 0) return false; |
89 | 106 |
90 PermissionCallback callback = new PermissionCallback() { | 107 PermissionCallback callback = new PermissionCallback() { |
91 @Override | 108 @Override |
92 public void onRequestPermissionsResult( | 109 public void onRequestPermissionsResult( |
93 String[] permissions, int[] grantResults) { | 110 String[] permissions, int[] grantResults) { |
94 int deniedCount = 0; | 111 int deniedCount = 0; |
95 int requestableCount = 0; | 112 int requestableCount = 0; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 }); | 152 }); |
136 builder.create().show(); | 153 builder.create().show(); |
137 } else if (deniedCount > 0) { | 154 } else if (deniedCount > 0) { |
138 delegate.onAndroidPermissionCanceled(); | 155 delegate.onAndroidPermissionCanceled(); |
139 } else { | 156 } else { |
140 delegate.onAndroidPermissionAccepted(); | 157 delegate.onAndroidPermissionAccepted(); |
141 } | 158 } |
142 } | 159 } |
143 }; | 160 }; |
144 | 161 |
145 String[] permissionsToRequest = new String[contentSettingsTypesToPermiss
ionsMap.size()]; | 162 Set<String> permissionsToRequest = new HashSet<>(); |
146 for (int i = 0; i < contentSettingsTypesToPermissionsMap.size(); i++) { | 163 for (int i = 0; i < contentSettingsTypesToPermissionsMap.size(); i++) { |
147 permissionsToRequest[i] = contentSettingsTypesToPermissionsMap.value
At(i); | 164 Collections.addAll( |
| 165 permissionsToRequest, contentSettingsTypesToPermissionsMap.v
alueAt(i)); |
148 } | 166 } |
149 windowAndroid.requestPermissions(permissionsToRequest, callback); | 167 windowAndroid.requestPermissions( |
| 168 permissionsToRequest.toArray(new String[permissionsToRequest.siz
e()]), callback); |
150 return true; | 169 return true; |
151 } | 170 } |
152 } | 171 } |
OLD | NEW |