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 |