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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/infobar/ConfirmInfoBar.java

Issue 1236703002: Show a dialog if a user denies' a android runtime permission. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 months 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
« no previous file with comments | « chrome/android/java/res/layout/update_permissions_dialog.xml ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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.infobar;
6 6
7 import android.app.Activity;
8 import android.app.AlertDialog;
7 import android.content.Context; 9 import android.content.Context;
10 import android.content.DialogInterface;
8 import android.content.pm.PackageManager; 11 import android.content.pm.PackageManager;
9 import android.graphics.Bitmap; 12 import android.graphics.Bitmap;
10 import android.os.Process; 13 import android.os.Process;
14 import android.util.SparseArray;
15 import android.view.View;
16 import android.widget.TextView;
11 17
18 import org.chromium.chrome.R;
12 import org.chromium.chrome.browser.ContentSettingsType; 19 import org.chromium.chrome.browser.ContentSettingsType;
13 import org.chromium.chrome.browser.preferences.PrefServiceBridge; 20 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
14 import org.chromium.ui.base.WindowAndroid; 21 import org.chromium.ui.base.WindowAndroid;
15 import org.chromium.ui.base.WindowAndroid.PermissionCallback; 22 import org.chromium.ui.base.WindowAndroid.PermissionCallback;
16 23
17 import java.util.ArrayList;
18 import java.util.List;
19
20 /** 24 /**
21 * An infobar that presents the user with several buttons. 25 * An infobar that presents the user with several buttons.
22 * 26 *
23 * TODO(newt): merge this into InfoBar.java. 27 * TODO(newt): merge this into InfoBar.java.
24 */ 28 */
25 public class ConfirmInfoBar extends InfoBar { 29 public class ConfirmInfoBar extends InfoBar {
26 /** Text shown on the primary button, e.g. "OK". */ 30 /** Text shown on the primary button, e.g. "OK". */
27 private final String mPrimaryButtonText; 31 private final String mPrimaryButtonText;
28 32
29 /** Text shown on the secondary button, e.g. "Cancel".*/ 33 /** Text shown on the secondary button, e.g. "Cancel".*/
30 private final String mSecondaryButtonText; 34 private final String mSecondaryButtonText;
31 35
32 /** Text shown on the extra button, e.g. "More info". */ 36 /** Text shown on the extra button, e.g. "More info". */
33 private final String mTertiaryButtonText; 37 private final String mTertiaryButtonText;
34 38
35 /** Notified when one of the buttons is clicked. */ 39 /** Notified when one of the buttons is clicked. */
36 private final InfoBarListeners.Confirm mConfirmListener; 40 private final InfoBarListeners.Confirm mConfirmListener;
37 41
38 private WindowAndroid mWindowAndroid; 42 private WindowAndroid mWindowAndroid;
39 43
40 /** 44 /**
41 * The list of {@link ContentSettingsType}s being requested by this infobar. Can be null or 45 * Mapping between the required {@link ContentSettingsType}s and their assoc iated Android
42 * empty if none apply. 46 * runtime permissions. Only {@link ContentSettingsType}s that are associat ed with runtime
47 * permissions will be included in this list while all others will be exclud ed.
43 */ 48 */
44 private int[] mContentSettings; 49 private SparseArray<String> mContentSettingsToPermissionsMap;
45 50
46 public ConfirmInfoBar(InfoBarListeners.Confirm confirmListener, int iconDraw ableId, 51 public ConfirmInfoBar(InfoBarListeners.Confirm confirmListener, int iconDraw ableId,
47 Bitmap iconBitmap, String message, String linkText, String primaryBu ttonText, 52 Bitmap iconBitmap, String message, String linkText, String primaryBu ttonText,
48 String secondaryButtonText) { 53 String secondaryButtonText) {
49 super(confirmListener, iconDrawableId, iconBitmap, message); 54 super(confirmListener, iconDrawableId, iconBitmap, message);
50 mPrimaryButtonText = primaryButtonText; 55 mPrimaryButtonText = primaryButtonText;
51 mSecondaryButtonText = secondaryButtonText; 56 mSecondaryButtonText = secondaryButtonText;
52 mTertiaryButtonText = linkText; 57 mTertiaryButtonText = linkText;
53 mConfirmListener = confirmListener; 58 mConfirmListener = confirmListener;
54 } 59 }
55 60
56 /** 61 /**
57 * Specifies the {@link ContentSettingsType}s that are controlled by this In foBar. 62 * Specifies the {@link ContentSettingsType}s that are controlled by this In foBar.
58 * 63 *
59 * @param windowAndroid The WindowAndroid that will be used to check for the necessary 64 * @param windowAndroid The WindowAndroid that will be used to check for the necessary
60 * permissions. 65 * permissions.
61 * @param contentSettings The list of {@link ContentSettingsType}s whose acc ess is guarded 66 * @param contentSettings The list of {@link ContentSettingsType}s whose acc ess is guarded
62 * by this InfoBar. 67 * by this InfoBar.
63 */ 68 */
64 protected void setContentSettings( 69 protected void setContentSettings(
65 WindowAndroid windowAndroid, int[] contentSettings) { 70 WindowAndroid windowAndroid, int[] contentSettings) {
66 mWindowAndroid = windowAndroid; 71 mWindowAndroid = windowAndroid;
67 mContentSettings = contentSettings;
68
69 assert windowAndroid != null 72 assert windowAndroid != null
70 : "A WindowAndroid must be specified to request access to conten t settings"; 73 : "A WindowAndroid must be specified to request access to conten t settings";
74
75 mContentSettingsToPermissionsMap = generatePermissionsMapping(contentSet tings);
71 } 76 }
72 77
73 @Override 78 @Override
74 public void createContent(InfoBarLayout layout) { 79 public void createContent(InfoBarLayout layout) {
75 layout.setButtons(mPrimaryButtonText, mSecondaryButtonText, mTertiaryBut tonText); 80 layout.setButtons(mPrimaryButtonText, mSecondaryButtonText, mTertiaryBut tonText);
76 } 81 }
77 82
78 private static boolean hasPermission(Context context, String permission) { 83 private static boolean hasPermission(Context context, String permission) {
79 return context.checkPermission(permission, Process.myPid(), Process.myUi d()) 84 return context.checkPermission(permission, Process.myPid(), Process.myUi d())
80 != PackageManager.PERMISSION_DENIED; 85 != PackageManager.PERMISSION_DENIED;
81 } 86 }
82 87
83 private List<String> getPermissionsToRequest() { 88 private SparseArray<String> generatePermissionsMapping(int[] contentSettings ) {
84 Context context = getContext(); 89 Context context = mWindowAndroid.getApplicationContext();
85 List<String> permissionsToRequest = new ArrayList<String>(); 90 SparseArray<String> permissionsToRequest = new SparseArray<String>();
86 for (int i = 0; i < mContentSettings.length; i++) { 91 for (int i = 0; i < contentSettings.length; i++) {
87 String permission = PrefServiceBridge.getAndroidPermissionForContent Setting( 92 String permission = PrefServiceBridge.getAndroidPermissionForContent Setting(
88 mContentSettings[i]); 93 contentSettings[i]);
89 if (permission != null) { 94 if (permission != null) {
90 if (!hasPermission(context, permission)) permissionsToRequest.ad d(permission); 95 if (!hasPermission(context, permission)) {
96 permissionsToRequest.append(contentSettings[i], permission);
97 }
91 } 98 }
92 } 99 }
93 return permissionsToRequest; 100 return permissionsToRequest;
94 } 101 }
95 102
103 private int getDeniedPermissionResourceId(String permission) {
104 int contentSettingsType = 0;
105 // SparseArray#indexOfValue uses == instead of .equals, so we need to ma nually iterate
106 // over the list.
107 for (int i = 0; i < mContentSettingsToPermissionsMap.size(); i++) {
108 if (permission.equals(mContentSettingsToPermissionsMap.valueAt(i))) {
109 contentSettingsType = mContentSettingsToPermissionsMap.keyAt(i);
110 }
111 }
112 switch (contentSettingsType) {
113 case ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION:
114 return R.string.infobar_missing_location_permission_text;
115 case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
116 return R.string.infobar_missing_microphone_permission_text;
117 case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
118 return R.string.infobar_missing_camera_permission_text;
119 default:
120 assert false;
121 return R.string.infobar_missing_multiple_permissions_text;
122
123 }
124 }
125
96 @Override 126 @Override
97 public void onButtonClicked(final boolean isPrimaryButton) { 127 public void onButtonClicked(final boolean isPrimaryButton) {
98 if (mWindowAndroid == null || mContentSettings == null 128 if (mWindowAndroid == null || mContentSettingsToPermissionsMap == null
99 || !isPrimaryButton || getContext() == null) { 129 || !isPrimaryButton || getContext() == null) {
100 onButtonClickedInternal(isPrimaryButton); 130 onButtonClickedInternal(isPrimaryButton);
101 return; 131 return;
102 } 132 }
103 133
104 List<String> permissionsToRequest = getPermissionsToRequest(); 134 if (mContentSettingsToPermissionsMap.size() == 0) {
gone 2015/07/10 23:52:07 can this be combined with the above block?
Ted C 2015/07/10 23:56:53 Done.
105 if (permissionsToRequest.isEmpty()) {
106 onButtonClickedInternal(isPrimaryButton); 135 onButtonClickedInternal(isPrimaryButton);
107 return; 136 return;
108 } 137 }
109 138
139 requestAndroidPermissions();
140 }
141
142 private void requestAndroidPermissions() {
110 PermissionCallback callback = new PermissionCallback() { 143 PermissionCallback callback = new PermissionCallback() {
111 @Override 144 @Override
112 public void onRequestPermissionsResult( 145 public void onRequestPermissionsResult(
113 String[] permissions, int[] grantResults) { 146 String[] permissions, int[] grantResults) {
114 boolean grantedAllPermissions = true; 147 int deniedCount = 0;
148 int requestableCount = 0;
149 int deniedStringId = R.string.infobar_missing_multiple_permissio ns_text;
115 for (int i = 0; i < grantResults.length; i++) { 150 for (int i = 0; i < grantResults.length; i++) {
116 if (grantResults[i] == PackageManager.PERMISSION_DENIED) { 151 if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
117 grantedAllPermissions = false; 152 deniedCount++;
118 break; 153 if (deniedCount > 1) {
154 deniedStringId = R.string.infobar_missing_multiple_p ermissions_text;
155 } else {
156 deniedStringId = getDeniedPermissionResourceId(permi ssions[i]);
157 }
158
159 if (mWindowAndroid.canRequestPermission(permissions[i])) {
160 requestableCount++;
161 }
119 } 162 }
120 } 163 }
121 164
122 if (!grantedAllPermissions) { 165 Activity activity = mWindowAndroid.getActivity().get();
166 if (deniedCount > 0 && requestableCount > 0 && activity != null) {
167 View view = activity.getLayoutInflater().inflate(
168 R.layout.update_permissions_dialog, null);
169 TextView dialogText = (TextView) view.findViewById(R.id.text );
170 dialogText.setText(deniedStringId);
171
172 AlertDialog.Builder builder = new AlertDialog.Builder(getCon text())
173 .setView(view)
174 .setPositiveButton(R.string.infobar_update_permissio ns_button_text,
175 new DialogInterface.OnClickListener() {
176 @Override
177 public void onClick(DialogInterface dial og, int id) {
178 requestAndroidPermissions();
179 }
180 })
181 .setOnCancelListener(new DialogInterface.OnCancelLi stener() {
182 @Override
183 public void onCancel(DialogInterface dialog ) {
184 onCloseButtonClicked();
185 }
186 });
187 builder.create().show();
188 } else if (deniedCount > 0) {
123 onCloseButtonClicked(); 189 onCloseButtonClicked();
124 } else { 190 } else {
125 onButtonClickedInternal(true); 191 onButtonClickedInternal(true);
126 } 192 }
127 } 193 }
128 }; 194 };
129 195
130 mWindowAndroid.requestPermissions( 196 String[] permissionsToRequest = new String[mContentSettingsToPermissions Map.size()];
131 permissionsToRequest.toArray(new String[permissionsToRequest.siz e()]), 197 for (int i = 0; i < mContentSettingsToPermissionsMap.size(); i++) {
132 callback); 198 permissionsToRequest[i] = mContentSettingsToPermissionsMap.valueAt(i );
199 }
200 mWindowAndroid.requestPermissions(permissionsToRequest, callback);
133 } 201 }
134 202
135 private void onButtonClickedInternal(boolean isPrimaryButton) { 203 private void onButtonClickedInternal(boolean isPrimaryButton) {
136 if (mConfirmListener != null) { 204 if (mConfirmListener != null) {
137 mConfirmListener.onConfirmInfoBarButtonClicked(this, isPrimaryButton ); 205 mConfirmListener.onConfirmInfoBarButtonClicked(this, isPrimaryButton );
138 } 206 }
139 207
140 int action = isPrimaryButton ? InfoBar.ACTION_TYPE_OK : InfoBar.ACTION_T YPE_CANCEL; 208 int action = isPrimaryButton ? InfoBar.ACTION_TYPE_OK : InfoBar.ACTION_T YPE_CANCEL;
141 onButtonClicked(action, ""); 209 onButtonClicked(action, "");
142 } 210 }
143 } 211 }
OLDNEW
« no previous file with comments | « chrome/android/java/res/layout/update_permissions_dialog.xml ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698