Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(257)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/permissions/AndroidPermissionRequester.java

Issue 2496473003: Allow modal permission prompts on Android to request system permissions. (Closed)
Patch Set: Switch to Tab Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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.infobar; 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.graphics.Bitmap;
11 import android.support.v7.app.AlertDialog; 10 import android.support.v7.app.AlertDialog;
12 import android.support.v7.widget.SwitchCompat;
13 import android.util.SparseArray; 11 import android.util.SparseArray;
14 import android.view.View; 12 import android.view.View;
15 import android.widget.TextView; 13 import android.widget.TextView;
16 14
17 import org.chromium.base.annotations.CalledByNative;
18 import org.chromium.chrome.R; 15 import org.chromium.chrome.R;
19 import org.chromium.chrome.browser.ContentSettingsType; 16 import org.chromium.chrome.browser.ContentSettingsType;
20 import org.chromium.chrome.browser.ResourceId;
21 import org.chromium.chrome.browser.preferences.PrefServiceBridge; 17 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
22 import org.chromium.chrome.browser.tab.Tab;
23 import org.chromium.ui.base.WindowAndroid; 18 import org.chromium.ui.base.WindowAndroid;
24 import org.chromium.ui.base.WindowAndroid.PermissionCallback; 19 import org.chromium.ui.base.WindowAndroid.PermissionCallback;
25 20
26 /** 21 /**
27 * An infobar used for prompting the user to grant a web API permission. 22 * An object to handle requesting native permissions from Android when the user grants a website
28 * 23 * a permission.
29 */ 24 */
30 public class PermissionInfoBar extends ConfirmInfoBar { 25 public class AndroidPermissionRequester {
31
32 /** Whether or not to show a toggle for opting out of persisting the decisio n. */
33 private boolean mShowPersistenceToggle;
34 26
35 private WindowAndroid mWindowAndroid; 27 private WindowAndroid mWindowAndroid;
gone 2016/11/10 23:05:47 There a way around storing this WindowAndroid?
dominickn 2016/11/10 23:55:13 It'll require a bunch more refactoring which I'm h
28 private RequestDelegate mDelegate;
36 29
37 /** 30 /**
38 * Mapping between the required {@link ContentSettingsType}s and their assoc iated Android 31 * Mapping between the required {@link ContentSettingsType}s and their assoc iated Android
39 * runtime permissions. Only {@link ContentSettingsType}s that are associat ed with runtime 32 * runtime permissions. Only {@link ContentSettingsType}s that are associat ed with runtime
40 * permissions will be included in this list while all others will be exclud ed. 33 * permissions will be included in this list while all others will be exclud ed.
41 */ 34 */
42 private SparseArray<String> mContentSettingsToPermissionsMap; 35 private SparseArray<String> mContentSettingsToPermissionsMap;
43 36
44 protected PermissionInfoBar(int iconDrawableId, Bitmap iconBitmap, String me ssage, 37 /**
45 String linkText, String primaryButtonText, String secondaryButtonTex t, 38 * An interface for classes which need to be informed of the outcome of askin g a user to grant an
46 boolean showPersistenceToggle) { 39 * Android permission.
47 super(iconDrawableId, iconBitmap, message, linkText, primaryButtonText, 40 */
48 secondaryButtonText); 41 public interface RequestDelegate {
49 mShowPersistenceToggle = showPersistenceToggle; 42 void onAndroidPermissionAccepted();
43 void onAndroidPermissionCanceled();
gone 2016/11/10 23:05:47 Welp, this is one of those words no one agrees on
dominickn 2016/11/10 23:55:13 I've been told both spellings on reviews before
50 } 44 }
51 45
52 @Override 46 public AndroidPermissionRequester(WindowAndroid windowAndroid,
53 public void createContent(InfoBarLayout layout) { 47 RequestDelegate delegate, int[] contentSettings) {
54 super.createContent(layout);
55
56 if (mShowPersistenceToggle) {
57 InfoBarControlLayout controlLayout = layout.addControlLayout();
58 String description =
59 layout.getContext().getString(R.string.permission_prompt_per sist_text);
60 controlLayout.addSwitch(
61 0, 0, description, R.id.permission_infobar_persist_toggle, t rue);
62 }
63 }
64
65 @Override
66 public void onTabReparented(Tab tab) {
67 mWindowAndroid = tab.getWindowAndroid();
68 }
69
70 /**
71 * Specifies the {@link ContentSettingsType}s that are controlled by this In foBar.
72 *
73 * @param windowAndroid The WindowAndroid that will be used to check for the necessary
74 * permissions.
75 * @param contentSettings The list of {@link ContentSettingsType}s whose acc ess is guarded
76 * by this InfoBar.
77 */
78 protected void setContentSettings(
79 WindowAndroid windowAndroid, int[] contentSettings) {
80 mWindowAndroid = windowAndroid; 48 mWindowAndroid = windowAndroid;
81 assert windowAndroid != null 49 mDelegate = delegate;
82 : "A WindowAndroid must be specified to request access to conten t settings";
83
84 mContentSettingsToPermissionsMap = generatePermissionsMapping(contentSet tings); 50 mContentSettingsToPermissionsMap = generatePermissionsMapping(contentSet tings);
85 } 51 }
86 52
53 public void setWindowAndroid(WindowAndroid windowAndroid) {
54 mWindowAndroid = windowAndroid;
55 }
56
87 private SparseArray<String> generatePermissionsMapping(int[] contentSettings ) { 57 private SparseArray<String> generatePermissionsMapping(int[] contentSettings ) {
88 SparseArray<String> permissionsToRequest = new SparseArray<String>(); 58 SparseArray<String> permissionsToRequest = new SparseArray<String>();
89 for (int i = 0; i < contentSettings.length; i++) { 59 for (int i = 0; i < contentSettings.length; i++) {
90 String permission = PrefServiceBridge.getAndroidPermissionForContent Setting( 60 String permission = PrefServiceBridge.getAndroidPermissionForContent Setting(
91 contentSettings[i]); 61 contentSettings[i]);
92 if (permission != null && !mWindowAndroid.hasPermission(permission)) { 62 if (permission != null && !mWindowAndroid.hasPermission(permission)) {
93 permissionsToRequest.append(contentSettings[i], permission); 63 permissionsToRequest.append(contentSettings[i], permission);
94 } 64 }
95 } 65 }
96 return permissionsToRequest; 66 return permissionsToRequest;
(...skipping 15 matching lines...) Expand all
112 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_MED IASTREAM_MIC) { 82 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_MED IASTREAM_MIC) {
113 return R.string.infobar_missing_microphone_permission_text; 83 return R.string.infobar_missing_microphone_permission_text;
114 } 84 }
115 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_MED IASTREAM_CAMERA) { 85 if (contentSettingsType == ContentSettingsType.CONTENT_SETTINGS_TYPE_MED IASTREAM_CAMERA) {
116 return R.string.infobar_missing_camera_permission_text; 86 return R.string.infobar_missing_camera_permission_text;
117 } 87 }
118 assert false : "Unexpected content setting type received: " + contentSet tingsType; 88 assert false : "Unexpected content setting type received: " + contentSet tingsType;
119 return R.string.infobar_missing_multiple_permissions_text; 89 return R.string.infobar_missing_multiple_permissions_text;
120 } 90 }
121 91
122 @Override 92 public boolean shouldSkipPermissionRequest() {
123 public void onButtonClicked(final boolean isPrimaryButton) { 93 return (mWindowAndroid == null || mContentSettingsToPermissionsMap == nu ll
124 if (mWindowAndroid == null || !isPrimaryButton || getContext() == null 94 || mContentSettingsToPermissionsMap.size() == 0);
125 || mContentSettingsToPermissionsMap == null
126 || mContentSettingsToPermissionsMap.size() == 0) {
127 onButtonClickedInternal(isPrimaryButton);
128 return;
129 }
130
131 requestAndroidPermissions();
132 } 95 }
133 96
134 private void requestAndroidPermissions() { 97 public void requestAndroidPermissions() {
135 PermissionCallback callback = new PermissionCallback() { 98 PermissionCallback callback = new PermissionCallback() {
136 @Override 99 @Override
137 public void onRequestPermissionsResult( 100 public void onRequestPermissionsResult(
138 String[] permissions, int[] grantResults) { 101 String[] permissions, int[] grantResults) {
139 int deniedCount = 0; 102 int deniedCount = 0;
140 int requestableCount = 0; 103 int requestableCount = 0;
141 int deniedStringId = R.string.infobar_missing_multiple_permissio ns_text; 104 int deniedStringId = R.string.infobar_missing_multiple_permissio ns_text;
142 for (int i = 0; i < grantResults.length; i++) { 105 for (int i = 0; i < grantResults.length; i++) {
143 if (grantResults[i] == PackageManager.PERMISSION_DENIED) { 106 if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
144 deniedCount++; 107 deniedCount++;
(...skipping 22 matching lines...) Expand all
167 .setPositiveButton(R.string.infobar_update_permissio ns_button_text, 130 .setPositiveButton(R.string.infobar_update_permissio ns_button_text,
168 new DialogInterface.OnClickListener() { 131 new DialogInterface.OnClickListener() {
169 @Override 132 @Override
170 public void onClick(DialogInterface dial og, int id) { 133 public void onClick(DialogInterface dial og, int id) {
171 requestAndroidPermissions(); 134 requestAndroidPermissions();
172 } 135 }
173 }) 136 })
174 .setOnCancelListener(new DialogInterface.OnCancelLi stener() { 137 .setOnCancelListener(new DialogInterface.OnCancelLi stener() {
175 @Override 138 @Override
176 public void onCancel(DialogInterface dialog ) { 139 public void onCancel(DialogInterface dialog ) {
177 onCloseButtonClicked(); 140 mDelegate.onAndroidPermissionCanceled() ;
178 } 141 }
179 }); 142 });
180 builder.create().show(); 143 builder.create().show();
181 } else if (deniedCount > 0) { 144 } else if (deniedCount > 0) {
182 onCloseButtonClicked(); 145 mDelegate.onAndroidPermissionCanceled();
183 } else { 146 } else {
184 onButtonClickedInternal(true); 147 mDelegate.onAndroidPermissionAccepted();
185 } 148 }
186 } 149 }
187 }; 150 };
188 151
189 String[] permissionsToRequest = new String[mContentSettingsToPermissions Map.size()]; 152 String[] permissionsToRequest = new String[mContentSettingsToPermissions Map.size()];
190 for (int i = 0; i < mContentSettingsToPermissionsMap.size(); i++) { 153 for (int i = 0; i < mContentSettingsToPermissionsMap.size(); i++) {
191 permissionsToRequest[i] = mContentSettingsToPermissionsMap.valueAt(i ); 154 permissionsToRequest[i] = mContentSettingsToPermissionsMap.valueAt(i );
192 } 155 }
193 mWindowAndroid.requestPermissions(permissionsToRequest, callback); 156 mWindowAndroid.requestPermissions(permissionsToRequest, callback);
194 } 157 }
195 158
196 private void onButtonClickedInternal(boolean isPrimaryButton) {
197 super.onButtonClicked(isPrimaryButton);
198 }
199
200 /**
201 * Returns true if the persist switch exists and is toggled on.
202 */
203 @CalledByNative
204 protected boolean isPersistSwitchOn() {
205 SwitchCompat persistSwitch = (SwitchCompat) getView().findViewById(
206 R.id.permission_infobar_persist_toggle);
207 if (mShowPersistenceToggle && persistSwitch != null) {
208 return persistSwitch.isChecked();
209 }
210 return false;
211 }
212
213 /**
214 * Creates and begins the process for showing a PermissionInfoBar.
215 * @param windowAndroid The owning window for the infobar.
216 * @param enumeratedIconId ID corresponding to the icon that will be shown f or the infobar.
217 * The ID must have been mapped using the ResourceMa pper class before
218 * passing it to this function.
219 * @param iconBitmap Bitmap to use if there is no equivalent Java resource f or
220 * enumeratedIconId.
221 * @param message Message to display to the user indicating what the infobar is for.
222 * @param linkText Link text to display in addition to the message.
223 * @param buttonOk String to display on the OK button.
224 * @param buttonCancel String to display on the Cancel button.
225 * @param contentSettings The list of ContentSettingTypes being requested by this infobar.
226 * @param showPersistenceToggle Whether or not a toggle to opt-out of persis ting a decision
227 * should be displayed.
228 */
229 @CalledByNative
230 private static PermissionInfoBar create(WindowAndroid windowAndroid, int enu meratedIconId,
231 Bitmap iconBitmap, String message, String linkText, String buttonOk,
232 String buttonCancel, int[] contentSettings, boolean showPersistenceT oggle) {
233 int drawableId = ResourceId.mapToDrawableId(enumeratedIconId);
234
235 PermissionInfoBar infoBar = new PermissionInfoBar(drawableId, iconBitmap , message, linkText,
236 buttonOk, buttonCancel, showPersistenceToggle);
237 infoBar.setContentSettings(windowAndroid, contentSettings);
238
239 return infoBar;
240 }
241 } 159 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698