| 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.ui.base; | 5 package org.chromium.ui.base; |
| 6 | 6 |
| 7 import android.app.Activity; | 7 import android.app.Activity; |
| 8 import android.app.PendingIntent; | 8 import android.app.PendingIntent; |
| 9 import android.content.ActivityNotFoundException; | 9 import android.content.ActivityNotFoundException; |
| 10 import android.content.Context; |
| 10 import android.content.Intent; | 11 import android.content.Intent; |
| 11 import android.content.IntentSender.SendIntentException; | 12 import android.content.IntentSender.SendIntentException; |
| 12 import android.content.SharedPreferences; | 13 import android.content.SharedPreferences; |
| 13 import android.content.pm.PackageManager; | 14 import android.content.pm.PackageManager; |
| 14 import android.content.pm.PackageManager.NameNotFoundException; | 15 import android.content.pm.PackageManager.NameNotFoundException; |
| 15 import android.content.pm.PermissionInfo; | 16 import android.content.pm.PermissionInfo; |
| 16 import android.os.Build; | 17 import android.os.Build; |
| 17 import android.os.Handler; | 18 import android.os.Handler; |
| 18 import android.os.Process; | 19 import android.os.Process; |
| 19 import android.preference.PreferenceManager; | 20 import android.preference.PreferenceManager; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 34 */ | 35 */ |
| 35 public class ActivityWindowAndroid | 36 public class ActivityWindowAndroid |
| 36 extends WindowAndroid | 37 extends WindowAndroid |
| 37 implements ApplicationStatus.ActivityStateListener, View.OnLayoutChangeL
istener { | 38 implements ApplicationStatus.ActivityStateListener, View.OnLayoutChangeL
istener { |
| 38 // Constants used for intent request code bounding. | 39 // Constants used for intent request code bounding. |
| 39 private static final int REQUEST_CODE_PREFIX = 1000; | 40 private static final int REQUEST_CODE_PREFIX = 1000; |
| 40 private static final int REQUEST_CODE_RANGE_SIZE = 100; | 41 private static final int REQUEST_CODE_RANGE_SIZE = 100; |
| 41 | 42 |
| 42 private static final String PERMISSION_QUERIED_KEY_PREFIX = "HasRequestedAnd
roidPermission::"; | 43 private static final String PERMISSION_QUERIED_KEY_PREFIX = "HasRequestedAnd
roidPermission::"; |
| 43 | 44 |
| 44 private final WeakReference<Activity> mActivityRef; | |
| 45 private final Handler mHandler; | 45 private final Handler mHandler; |
| 46 private final SparseArray<PermissionCallback> mOutstandingPermissionRequests
; | 46 private final SparseArray<PermissionCallback> mOutstandingPermissionRequests
; |
| 47 | 47 |
| 48 private int mNextRequestCode = 0; | 48 private int mNextRequestCode = 0; |
| 49 | 49 |
| 50 /** | 50 /** |
| 51 * Creates an Activity-specific WindowAndroid with associated intent functio
nality. | 51 * Creates an Activity-specific WindowAndroid with associated intent functio
nality. |
| 52 * TODO(jdduke): Remove this overload when all callsites have been updated t
o | 52 * TODO(jdduke): Remove this overload when all callsites have been updated t
o |
| 53 * indicate their activity state listening preference. | 53 * indicate their activity state listening preference. |
| 54 * @param activity The activity associated with the WindowAndroid. | 54 * @param context Context wrapping an activity associated with the WindowAnd
roid. |
| 55 */ | 55 */ |
| 56 public ActivityWindowAndroid(Activity activity) { | 56 public ActivityWindowAndroid(Context context) { |
| 57 this(activity, true); | 57 this(context, true); |
| 58 } | 58 } |
| 59 | 59 |
| 60 /** | 60 /** |
| 61 * Creates an Activity-specific WindowAndroid with associated intent functio
nality. | 61 * Creates an Activity-specific WindowAndroid with associated intent functio
nality. |
| 62 * @param activity The activity associated with the WindowAndroid. | 62 * @param context Context wrapping an activity associated with the WindowAnd
roid. |
| 63 * @param listenToActivityState Whether to listen to activity state changes. | 63 * @param listenToActivityState Whether to listen to activity state changes. |
| 64 */ | 64 */ |
| 65 public ActivityWindowAndroid(Activity activity, boolean listenToActivityStat
e) { | 65 public ActivityWindowAndroid(Context context, boolean listenToActivityState)
{ |
| 66 super(activity.getApplicationContext()); | 66 super(context); |
| 67 mActivityRef = new WeakReference<Activity>(activity); | 67 Activity activity = activityFromContext(context); |
| 68 if (activity == null) { |
| 69 throw new IllegalArgumentException("Context is not and does not wrap
an Activity"); |
| 70 } |
| 68 mHandler = new Handler(); | 71 mHandler = new Handler(); |
| 69 mOutstandingPermissionRequests = new SparseArray<PermissionCallback>(); | 72 mOutstandingPermissionRequests = new SparseArray<PermissionCallback>(); |
| 70 if (listenToActivityState) { | 73 if (listenToActivityState) { |
| 71 ApplicationStatus.registerStateListenerForActivity(this, activity); | 74 ApplicationStatus.registerStateListenerForActivity(this, activity); |
| 72 } | 75 } |
| 73 | 76 |
| 74 setAndroidPermissionDelegate(new ActivityAndroidPermissionDelegate()); | 77 setAndroidPermissionDelegate(new ActivityAndroidPermissionDelegate()); |
| 75 } | 78 } |
| 76 | 79 |
| 77 @Override | 80 @Override |
| 78 protected void registerKeyboardVisibilityCallbacks() { | 81 protected void registerKeyboardVisibilityCallbacks() { |
| 79 Activity activity = mActivityRef.get(); | 82 Activity activity = getActivity().get(); |
| 80 if (activity == null) return; | 83 if (activity == null) return; |
| 81 View content = activity.findViewById(android.R.id.content); | 84 View content = activity.findViewById(android.R.id.content); |
| 82 mIsKeyboardShowing = UiUtils.isKeyboardShowing(mActivityRef.get(), conte
nt); | 85 mIsKeyboardShowing = UiUtils.isKeyboardShowing(getActivity().get(), cont
ent); |
| 83 content.addOnLayoutChangeListener(this); | 86 content.addOnLayoutChangeListener(this); |
| 84 } | 87 } |
| 85 | 88 |
| 86 @Override | 89 @Override |
| 87 protected void unregisterKeyboardVisibilityCallbacks() { | 90 protected void unregisterKeyboardVisibilityCallbacks() { |
| 88 Activity activity = mActivityRef.get(); | 91 Activity activity = getActivity().get(); |
| 89 if (activity == null) return; | 92 if (activity == null) return; |
| 90 activity.findViewById(android.R.id.content).removeOnLayoutChangeListener
(this); | 93 activity.findViewById(android.R.id.content).removeOnLayoutChangeListener
(this); |
| 91 } | 94 } |
| 92 | 95 |
| 93 @Override | 96 @Override |
| 94 public int showCancelableIntent( | 97 public int showCancelableIntent( |
| 95 PendingIntent intent, IntentCallback callback, Integer errorId) { | 98 PendingIntent intent, IntentCallback callback, Integer errorId) { |
| 96 Activity activity = mActivityRef.get(); | 99 Activity activity = getActivity().get(); |
| 97 if (activity == null) return START_INTENT_FAILURE; | 100 if (activity == null) return START_INTENT_FAILURE; |
| 98 | 101 |
| 99 int requestCode = generateNextRequestCode(); | 102 int requestCode = generateNextRequestCode(); |
| 100 | 103 |
| 101 try { | 104 try { |
| 102 activity.startIntentSenderForResult( | 105 activity.startIntentSenderForResult( |
| 103 intent.getIntentSender(), requestCode, new Intent(), 0, 0, 0
); | 106 intent.getIntentSender(), requestCode, new Intent(), 0, 0, 0
); |
| 104 } catch (SendIntentException e) { | 107 } catch (SendIntentException e) { |
| 105 return START_INTENT_FAILURE; | 108 return START_INTENT_FAILURE; |
| 106 } | 109 } |
| 107 | 110 |
| 108 storeCallbackData(requestCode, callback, errorId); | 111 storeCallbackData(requestCode, callback, errorId); |
| 109 return requestCode; | 112 return requestCode; |
| 110 } | 113 } |
| 111 | 114 |
| 112 @Override | 115 @Override |
| 113 public int showCancelableIntent(Intent intent, IntentCallback callback, Inte
ger errorId) { | 116 public int showCancelableIntent(Intent intent, IntentCallback callback, Inte
ger errorId) { |
| 114 Activity activity = mActivityRef.get(); | 117 Activity activity = getActivity().get(); |
| 115 if (activity == null) return START_INTENT_FAILURE; | 118 if (activity == null) return START_INTENT_FAILURE; |
| 116 | 119 |
| 117 int requestCode = generateNextRequestCode(); | 120 int requestCode = generateNextRequestCode(); |
| 118 | 121 |
| 119 try { | 122 try { |
| 120 activity.startActivityForResult(intent, requestCode); | 123 activity.startActivityForResult(intent, requestCode); |
| 121 } catch (ActivityNotFoundException e) { | 124 } catch (ActivityNotFoundException e) { |
| 122 return START_INTENT_FAILURE; | 125 return START_INTENT_FAILURE; |
| 123 } | 126 } |
| 124 | 127 |
| 125 storeCallbackData(requestCode, callback, errorId); | 128 storeCallbackData(requestCode, callback, errorId); |
| 126 return requestCode; | 129 return requestCode; |
| 127 } | 130 } |
| 128 | 131 |
| 129 @Override | 132 @Override |
| 130 public void cancelIntent(int requestCode) { | 133 public void cancelIntent(int requestCode) { |
| 131 Activity activity = mActivityRef.get(); | 134 Activity activity = getActivity().get(); |
| 132 if (activity == null) return; | 135 if (activity == null) return; |
| 133 activity.finishActivity(requestCode); | 136 activity.finishActivity(requestCode); |
| 134 } | 137 } |
| 135 | 138 |
| 136 /** | 139 /** |
| 137 * Responds to the intent result if the intent was created by the native win
dow. | 140 * Responds to the intent result if the intent was created by the native win
dow. |
| 138 * @param requestCode Request code of the requested intent. | 141 * @param requestCode Request code of the requested intent. |
| 139 * @param resultCode Result code of the requested intent. | 142 * @param resultCode Result code of the requested intent. |
| 140 * @param data The data returned by the intent. | 143 * @param data The data returned by the intent. |
| 141 * @return Boolean value of whether the intent was started by the native win
dow. | 144 * @return Boolean value of whether the intent was started by the native win
dow. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 | 186 |
| 184 /** | 187 /** |
| 185 * Responds to a pending permission result. | 188 * Responds to a pending permission result. |
| 186 * @param requestCode The unique code for the permission request. | 189 * @param requestCode The unique code for the permission request. |
| 187 * @param permissions The list of permissions in the result. | 190 * @param permissions The list of permissions in the result. |
| 188 * @param grantResults Whether the permissions were granted. | 191 * @param grantResults Whether the permissions were granted. |
| 189 * @return Whether the permission request corresponding to a pending permiss
ion request. | 192 * @return Whether the permission request corresponding to a pending permiss
ion request. |
| 190 */ | 193 */ |
| 191 public boolean onRequestPermissionsResult(int requestCode, String[] permissi
ons, | 194 public boolean onRequestPermissionsResult(int requestCode, String[] permissi
ons, |
| 192 int[] grantResults) { | 195 int[] grantResults) { |
| 193 Activity activity = mActivityRef.get(); | 196 Activity activity = getActivity().get(); |
| 194 assert activity != null; | 197 assert activity != null; |
| 195 | 198 |
| 196 SharedPreferences.Editor editor = | 199 SharedPreferences.Editor editor = |
| 197 PreferenceManager.getDefaultSharedPreferences(activity).edit(); | 200 PreferenceManager.getDefaultSharedPreferences(activity).edit(); |
| 198 for (int i = 0; i < permissions.length; i++) { | 201 for (int i = 0; i < permissions.length; i++) { |
| 199 editor.putBoolean(getHasRequestedPermissionKey(permissions[i]), true
); | 202 editor.putBoolean(getHasRequestedPermissionKey(permissions[i]), true
); |
| 200 } | 203 } |
| 201 editor.apply(); | 204 editor.apply(); |
| 202 | 205 |
| 203 PermissionCallback callback = mOutstandingPermissionRequests.get(request
Code); | 206 PermissionCallback callback = mOutstandingPermissionRequests.get(request
Code); |
| 204 mOutstandingPermissionRequests.delete(requestCode); | 207 mOutstandingPermissionRequests.delete(requestCode); |
| 205 if (callback == null) return false; | 208 if (callback == null) return false; |
| 206 callback.onRequestPermissionsResult(permissions, grantResults); | 209 callback.onRequestPermissionsResult(permissions, grantResults); |
| 207 return true; | 210 return true; |
| 208 } | 211 } |
| 209 | 212 |
| 210 @Override | 213 @Override |
| 211 public WeakReference<Activity> getActivity() { | 214 public WeakReference<Activity> getActivity() { |
| 212 // Return a new WeakReference to prevent clients from releasing our inte
rnal WeakReference. | 215 return new WeakReference<Activity>(activityFromContext(getContext().get(
))); |
| 213 return new WeakReference<Activity>(mActivityRef.get()); | |
| 214 } | 216 } |
| 215 | 217 |
| 216 @Override | 218 @Override |
| 217 public void onActivityStateChange(Activity activity, int newState) { | 219 public void onActivityStateChange(Activity activity, int newState) { |
| 218 if (newState == ActivityState.STOPPED) { | 220 if (newState == ActivityState.STOPPED) { |
| 219 onActivityStopped(); | 221 onActivityStopped(); |
| 220 } else if (newState == ActivityState.STARTED) { | 222 } else if (newState == ActivityState.STARTED) { |
| 221 onActivityStarted(); | 223 onActivityStarted(); |
| 222 } | 224 } |
| 223 } | 225 } |
| 224 | 226 |
| 225 @Override | 227 @Override |
| 226 public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, | 228 public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, |
| 227 int oldTop, int oldRight, int oldBottom) { | 229 int oldTop, int oldRight, int oldBottom) { |
| 228 keyboardVisibilityPossiblyChanged(UiUtils.isKeyboardShowing(mActivityRef
.get(), v)); | 230 keyboardVisibilityPossiblyChanged(UiUtils.isKeyboardShowing(getActivity(
).get(), v)); |
| 229 } | 231 } |
| 230 | 232 |
| 231 private int generateNextRequestCode() { | 233 private int generateNextRequestCode() { |
| 232 int requestCode = REQUEST_CODE_PREFIX + mNextRequestCode; | 234 int requestCode = REQUEST_CODE_PREFIX + mNextRequestCode; |
| 233 mNextRequestCode = (mNextRequestCode + 1) % REQUEST_CODE_RANGE_SIZE; | 235 mNextRequestCode = (mNextRequestCode + 1) % REQUEST_CODE_RANGE_SIZE; |
| 234 return requestCode; | 236 return requestCode; |
| 235 } | 237 } |
| 236 | 238 |
| 237 private void storeCallbackData(int requestCode, IntentCallback callback, Int
eger errorId) { | 239 private void storeCallbackData(int requestCode, IntentCallback callback, Int
eger errorId) { |
| 238 mOutstandingIntents.put(requestCode, callback); | 240 mOutstandingIntents.put(requestCode, callback); |
| 239 mIntentErrors.put( | 241 mIntentErrors.put( |
| 240 requestCode, errorId == null ? null : mApplicationContext.getStr
ing(errorId)); | 242 requestCode, errorId == null ? null : mApplicationContext.getStr
ing(errorId)); |
| 241 } | 243 } |
| 242 | 244 |
| 243 private class ActivityAndroidPermissionDelegate implements AndroidPermission
Delegate { | 245 private class ActivityAndroidPermissionDelegate implements AndroidPermission
Delegate { |
| 244 @Override | 246 @Override |
| 245 public boolean hasPermission(String permission) { | 247 public boolean hasPermission(String permission) { |
| 246 return mApplicationContext.checkPermission(permission, Process.myPid
(), Process.myUid()) | 248 return mApplicationContext.checkPermission(permission, Process.myPid
(), Process.myUid()) |
| 247 == PackageManager.PERMISSION_GRANTED; | 249 == PackageManager.PERMISSION_GRANTED; |
| 248 } | 250 } |
| 249 | 251 |
| 250 @Override | 252 @Override |
| 251 public boolean canRequestPermission(String permission) { | 253 public boolean canRequestPermission(String permission) { |
| 252 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; | 254 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; |
| 253 | 255 |
| 254 Activity activity = mActivityRef.get(); | 256 Activity activity = getActivity().get(); |
| 255 if (activity == null) return false; | 257 if (activity == null) return false; |
| 256 | 258 |
| 257 if (isPermissionRevokedByPolicy(permission)) { | 259 if (isPermissionRevokedByPolicy(permission)) { |
| 258 return false; | 260 return false; |
| 259 } | 261 } |
| 260 | 262 |
| 261 if (activity.shouldShowRequestPermissionRationale(permission)) { | 263 if (activity.shouldShowRequestPermissionRationale(permission)) { |
| 262 return true; | 264 return true; |
| 263 } | 265 } |
| 264 | 266 |
| 265 // Check whether we have ever asked for this permission by checking
whether we saved | 267 // Check whether we have ever asked for this permission by checking
whether we saved |
| 266 // a preference associated with it before. | 268 // a preference associated with it before. |
| 267 String permissionQueriedKey = getHasRequestedPermissionKey(permissio
n); | 269 String permissionQueriedKey = getHasRequestedPermissionKey(permissio
n); |
| 268 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferen
ces(activity); | 270 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferen
ces(activity); |
| 269 if (!prefs.getBoolean(permissionQueriedKey, false)) return true; | 271 if (!prefs.getBoolean(permissionQueriedKey, false)) return true; |
| 270 | 272 |
| 271 return false; | 273 return false; |
| 272 } | 274 } |
| 273 | 275 |
| 274 @Override | 276 @Override |
| 275 public boolean isPermissionRevokedByPolicy(String permission) { | 277 public boolean isPermissionRevokedByPolicy(String permission) { |
| 276 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; | 278 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; |
| 277 | 279 |
| 278 Activity activity = mActivityRef.get(); | 280 Activity activity = getActivity().get(); |
| 279 if (activity == null) return false; | 281 if (activity == null) return false; |
| 280 | 282 |
| 281 return activity.getPackageManager().isPermissionRevokedByPolicy( | 283 return activity.getPackageManager().isPermissionRevokedByPolicy( |
| 282 permission, activity.getPackageName()); | 284 permission, activity.getPackageName()); |
| 283 } | 285 } |
| 284 | 286 |
| 285 @Override | 287 @Override |
| 286 public void requestPermissions( | 288 public void requestPermissions( |
| 287 final String[] permissions, final PermissionCallback callback) { | 289 final String[] permissions, final PermissionCallback callback) { |
| 288 if (requestPermissionsInternal(permissions, callback)) return; | 290 if (requestPermissionsInternal(permissions, callback)) return; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 304 } | 306 } |
| 305 }); | 307 }); |
| 306 } | 308 } |
| 307 | 309 |
| 308 /** | 310 /** |
| 309 * Issues the permission request and returns whether it was sent success
fully. | 311 * Issues the permission request and returns whether it was sent success
fully. |
| 310 */ | 312 */ |
| 311 private boolean requestPermissionsInternal( | 313 private boolean requestPermissionsInternal( |
| 312 String[] permissions, PermissionCallback callback) { | 314 String[] permissions, PermissionCallback callback) { |
| 313 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; | 315 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; |
| 314 Activity activity = mActivityRef.get(); | 316 Activity activity = getActivity().get(); |
| 315 if (activity == null) return false; | 317 if (activity == null) return false; |
| 316 | 318 |
| 317 int requestCode = generateNextRequestCode(); | 319 int requestCode = generateNextRequestCode(); |
| 318 mOutstandingPermissionRequests.put(requestCode, callback); | 320 mOutstandingPermissionRequests.put(requestCode, callback); |
| 319 activity.requestPermissions(permissions, requestCode); | 321 activity.requestPermissions(permissions, requestCode); |
| 320 return true; | 322 return true; |
| 321 } | 323 } |
| 322 } | 324 } |
| 323 } | 325 } |
| OLD | NEW |