OLD | NEW |
---|---|
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 } |
OLD | NEW |