OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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.Manifest; | 7 import android.Manifest; |
8 import android.annotation.TargetApi; | 8 import android.annotation.TargetApi; |
9 import android.app.Activity; | 9 import android.app.Activity; |
10 import android.content.ClipData; | 10 import android.content.ClipData; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 // on the accept type and then display that to the user. | 160 // on the accept type and then display that to the user. |
161 if (captureCamera() && camera != null) { | 161 if (captureCamera() && camera != null) { |
162 if (mWindowAndroid.showIntent(camera, this, R.string.low_memory_erro
r)) return; | 162 if (mWindowAndroid.showIntent(camera, this, R.string.low_memory_erro
r)) return; |
163 } else if (captureCamcorder() && camcorder != null) { | 163 } else if (captureCamcorder() && camcorder != null) { |
164 if (mWindowAndroid.showIntent(camcorder, this, R.string.low_memory_e
rror)) return; | 164 if (mWindowAndroid.showIntent(camcorder, this, R.string.low_memory_e
rror)) return; |
165 } else if (captureMicrophone() && soundRecorder != null) { | 165 } else if (captureMicrophone() && soundRecorder != null) { |
166 if (mWindowAndroid.showIntent(soundRecorder, this, R.string.low_memo
ry_error)) return; | 166 if (mWindowAndroid.showIntent(soundRecorder, this, R.string.low_memo
ry_error)) return; |
167 } | 167 } |
168 | 168 |
169 Intent getContentIntent = new Intent(Intent.ACTION_GET_CONTENT); | 169 Intent getContentIntent = new Intent(Intent.ACTION_GET_CONTENT); |
170 getContentIntent.addCategory(Intent.CATEGORY_OPENABLE); | |
171 | 170 |
172 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && mAllo
wMultiple) { | 171 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && mAllo
wMultiple) { |
173 getContentIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); | 172 getContentIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); |
174 } | 173 } |
175 | 174 |
176 ArrayList<Intent> extraIntents = new ArrayList<Intent>(); | 175 ArrayList<Intent> extraIntents = new ArrayList<Intent>(); |
177 if (!noSpecificType()) { | 176 if (!noSpecificType()) { |
178 // Create a chooser based on the accept type that was specified in t
he webpage. Note | 177 // Create a chooser based on the accept type that was specified in t
he webpage. Note |
179 // that if the web page specified multiple accept types, we will hav
e built a generic | 178 // that if the web page specified multiple accept types, we will hav
e built a generic |
180 // chooser above. | 179 // chooser above. |
181 if (shouldShowImageTypes()) { | 180 if (shouldShowImageTypes()) { |
182 if (camera != null) extraIntents.add(camera); | 181 if (camera != null) extraIntents.add(camera); |
183 getContentIntent.setType(ALL_IMAGE_TYPES); | 182 getContentIntent.setType(ALL_IMAGE_TYPES); |
184 } else if (shouldShowVideoTypes()) { | 183 } else if (shouldShowVideoTypes()) { |
185 if (camcorder != null) extraIntents.add(camcorder); | 184 if (camcorder != null) extraIntents.add(camcorder); |
186 getContentIntent.setType(ALL_VIDEO_TYPES); | 185 getContentIntent.setType(ALL_VIDEO_TYPES); |
187 } else if (shouldShowAudioTypes()) { | 186 } else if (shouldShowAudioTypes()) { |
188 if (soundRecorder != null) extraIntents.add(soundRecorder); | 187 if (soundRecorder != null) extraIntents.add(soundRecorder); |
189 getContentIntent.setType(ALL_AUDIO_TYPES); | 188 getContentIntent.setType(ALL_AUDIO_TYPES); |
190 } | 189 } |
| 190 |
| 191 // If any types are specified, then only accept openable files, as c
oercing |
| 192 // virtual files may yield to a MIME type different than expected. |
| 193 getContentIntent.addCategory(Intent.CATEGORY_OPENABLE); |
191 } | 194 } |
192 | 195 |
193 if (extraIntents.isEmpty()) { | 196 if (extraIntents.isEmpty()) { |
194 // We couldn't resolve an accept type, so fallback to a generic choo
ser. | 197 // We couldn't resolve an accept type, so fallback to a generic choo
ser. |
195 getContentIntent.setType(ANY_TYPES); | 198 getContentIntent.setType(ANY_TYPES); |
196 if (camera != null) extraIntents.add(camera); | 199 if (camera != null) extraIntents.add(camera); |
197 if (camcorder != null) extraIntents.add(camcorder); | 200 if (camcorder != null) extraIntents.add(camcorder); |
198 if (soundRecorder != null) extraIntents.add(soundRecorder); | 201 if (soundRecorder != null) extraIntents.add(soundRecorder); |
199 } | 202 } |
200 | 203 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 File photoFile = File.createTempFile(String.valueOf(System.currentTimeMi
llis()), ".jpg", | 259 File photoFile = File.createTempFile(String.valueOf(System.currentTimeMi
llis()), ".jpg", |
257 UiUtils.getDirectoryForImageCapture(context)); | 260 UiUtils.getDirectoryForImageCapture(context)); |
258 return photoFile; | 261 return photoFile; |
259 } | 262 } |
260 | 263 |
261 /** | 264 /** |
262 * Callback method to handle the intent results and pass on the path to the
native | 265 * Callback method to handle the intent results and pass on the path to the
native |
263 * SelectFileDialog. | 266 * SelectFileDialog. |
264 * @param window The window that has access to the application activity. | 267 * @param window The window that has access to the application activity. |
265 * @param resultCode The result code whether the intent returned successfull
y. | 268 * @param resultCode The result code whether the intent returned successfull
y. |
266 * @param contentResolver The content resolver used to extract the path of t
he selected file. | 269 * @param context Application context. |
267 * @param results The results of the requested intent. | 270 * @param results The results of the requested intent. |
268 */ | 271 */ |
269 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) | 272 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) |
270 @Override | 273 @Override |
271 public void onIntentCompleted(WindowAndroid window, int resultCode, | 274 public void onIntentCompleted( |
272 ContentResolver contentResolver, Intent results) { | 275 WindowAndroid window, int resultCode, Context context, Intent result
s) { |
273 if (resultCode != Activity.RESULT_OK) { | 276 if (resultCode != Activity.RESULT_OK) { |
274 onFileNotSelected(); | 277 onFileNotSelected(); |
275 return; | 278 return; |
276 } | 279 } |
277 | 280 |
278 if (results == null | 281 if (results == null |
279 || (results.getData() == null | 282 || (results.getData() == null |
280 && (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY
_BEAN_MR2 | 283 && (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY
_BEAN_MR2 |
281 || results.getClipData() == null))) { | 284 || results.getClipData() == null))) { |
282 // If we have a successful return but no data, then assume this is t
he camera returning | 285 // If we have a successful return but no data, then assume this is t
he camera returning |
(...skipping 23 matching lines...) Expand all Loading... |
306 int itemCount = clipData.getItemCount(); | 309 int itemCount = clipData.getItemCount(); |
307 if (itemCount == 0) { | 310 if (itemCount == 0) { |
308 onFileNotSelected(); | 311 onFileNotSelected(); |
309 return; | 312 return; |
310 } | 313 } |
311 | 314 |
312 Uri[] filePathArray = new Uri[itemCount]; | 315 Uri[] filePathArray = new Uri[itemCount]; |
313 for (int i = 0; i < itemCount; ++i) { | 316 for (int i = 0; i < itemCount; ++i) { |
314 filePathArray[i] = clipData.getItemAt(i).getUri(); | 317 filePathArray[i] = clipData.getItemAt(i).getUri(); |
315 } | 318 } |
316 GetDisplayNameTask task = new GetDisplayNameTask(contentResolver, tr
ue); | 319 GetDisplayNameTask task = new GetDisplayNameTask(context, true); |
317 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, filePathArray
); | 320 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, filePathArray
); |
318 return; | 321 return; |
319 } | 322 } |
320 | 323 |
321 if (ContentResolver.SCHEME_FILE.equals(results.getData().getScheme())) { | 324 if (ContentResolver.SCHEME_FILE.equals(results.getData().getScheme())) { |
322 nativeOnFileSelected( | 325 nativeOnFileSelected( |
323 mNativeSelectFileDialog, results.getData().getSchemeSpecific
Part(), ""); | 326 mNativeSelectFileDialog, results.getData().getSchemeSpecific
Part(), ""); |
324 return; | 327 return; |
325 } | 328 } |
326 | 329 |
327 if (ContentResolver.SCHEME_CONTENT.equals(results.getScheme())) { | 330 if (ContentResolver.SCHEME_CONTENT.equals(results.getScheme())) { |
328 GetDisplayNameTask task = new GetDisplayNameTask(contentResolver, fa
lse); | 331 GetDisplayNameTask task = new GetDisplayNameTask(context, false); |
329 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, results.getDa
ta()); | 332 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, results.getDa
ta()); |
330 return; | 333 return; |
331 } | 334 } |
332 | 335 |
333 onFileNotSelected(); | 336 onFileNotSelected(); |
334 window.showError(R.string.opening_file_error); | 337 window.showError(R.string.opening_file_error); |
335 } | 338 } |
336 | 339 |
337 @Override | 340 @Override |
338 public void onRequestPermissionsResult(String[] permissions, int[] grantResu
lts) { | 341 public void onRequestPermissionsResult(String[] permissions, int[] grantResu
lts) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 for (String type : mFileTypes) { | 397 for (String type : mFileTypes) { |
395 if (type.startsWith(accept)) { | 398 if (type.startsWith(accept)) { |
396 return true; | 399 return true; |
397 } | 400 } |
398 } | 401 } |
399 return false; | 402 return false; |
400 } | 403 } |
401 | 404 |
402 private class GetDisplayNameTask extends AsyncTask<Uri, Void, String[]> { | 405 private class GetDisplayNameTask extends AsyncTask<Uri, Void, String[]> { |
403 String[] mFilePaths; | 406 String[] mFilePaths; |
404 final ContentResolver mContentResolver; | 407 final Context mContext; |
405 final boolean mIsMultiple; | 408 final boolean mIsMultiple; |
406 | 409 |
407 public GetDisplayNameTask(ContentResolver contentResolver, boolean isMul
tiple) { | 410 public GetDisplayNameTask(Context context, boolean isMultiple) { |
408 mContentResolver = contentResolver; | 411 mContext = context; |
409 mIsMultiple = isMultiple; | 412 mIsMultiple = isMultiple; |
410 } | 413 } |
411 | 414 |
412 @Override | 415 @Override |
413 protected String[] doInBackground(Uri...uris) { | 416 protected String[] doInBackground(Uri...uris) { |
414 mFilePaths = new String[uris.length]; | 417 mFilePaths = new String[uris.length]; |
415 String[] displayNames = new String[uris.length]; | 418 String[] displayNames = new String[uris.length]; |
416 try { | 419 try { |
417 for (int i = 0; i < uris.length; i++) { | 420 for (int i = 0; i < uris.length; i++) { |
418 mFilePaths[i] = uris[i].toString(); | 421 mFilePaths[i] = uris[i].toString(); |
419 displayNames[i] = ContentUriUtils.getDisplayName( | 422 displayNames[i] = ContentUriUtils.getDisplayName( |
420 uris[i], mContentResolver, MediaStore.MediaColumns.D
ISPLAY_NAME); | 423 uris[i], mContext, MediaStore.MediaColumns.DISPLAY_N
AME); |
421 } | 424 } |
422 } catch (SecurityException e) { | 425 } catch (SecurityException e) { |
423 // Some third party apps will present themselves as being able | 426 // Some third party apps will present themselves as being able |
424 // to handle the ACTION_GET_CONTENT intent but then declare them
selves | 427 // to handle the ACTION_GET_CONTENT intent but then declare them
selves |
425 // as exported=false (or more often omit the exported keyword in | 428 // as exported=false (or more often omit the exported keyword in |
426 // the manifest which defaults to false after JB). | 429 // the manifest which defaults to false after JB). |
427 // In those cases trying to access the contents raises a securit
y exception | 430 // In those cases trying to access the contents raises a securit
y exception |
428 // which we should not crash on. See crbug.com/382367 for detail
s. | 431 // which we should not crash on. See crbug.com/382367 for detail
s. |
429 Log.w(TAG, "Unable to extract results from the content provider"
); | 432 Log.w(TAG, "Unable to extract results from the content provider"
); |
430 return null; | 433 return null; |
(...skipping 20 matching lines...) Expand all Loading... |
451 private static SelectFileDialog create(long nativeSelectFileDialog) { | 454 private static SelectFileDialog create(long nativeSelectFileDialog) { |
452 return new SelectFileDialog(nativeSelectFileDialog); | 455 return new SelectFileDialog(nativeSelectFileDialog); |
453 } | 456 } |
454 | 457 |
455 private native void nativeOnFileSelected(long nativeSelectFileDialogImpl, | 458 private native void nativeOnFileSelected(long nativeSelectFileDialogImpl, |
456 String filePath, String displayName); | 459 String filePath, String displayName); |
457 private native void nativeOnMultipleFilesSelected(long nativeSelectFileDialo
gImpl, | 460 private native void nativeOnMultipleFilesSelected(long nativeSelectFileDialo
gImpl, |
458 String[] filePathArray, String[] displayNameArray); | 461 String[] filePathArray, String[] displayNameArray); |
459 private native void nativeOnFileNotSelected(long nativeSelectFileDialogImpl)
; | 462 private native void nativeOnFileNotSelected(long nativeSelectFileDialogImpl)
; |
460 } | 463 } |
OLD | NEW |