Chromium Code Reviews| 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 |