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.content.browser; | 5 package org.chromium.content.browser; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.content.pm.PackageManager; | 8 import android.content.pm.PackageManager; |
9 import android.media.MediaMetadataRetriever; | 9 import android.media.MediaMetadataRetriever; |
10 import android.net.ConnectivityManager; | 10 import android.net.ConnectivityManager; |
(...skipping 20 matching lines...) Expand all Loading... |
31 * Java counterpart of android MediaResourceGetter. | 31 * Java counterpart of android MediaResourceGetter. |
32 */ | 32 */ |
33 @JNINamespace("content") | 33 @JNINamespace("content") |
34 class MediaResourceGetter { | 34 class MediaResourceGetter { |
35 | 35 |
36 private static final String TAG = "MediaResourceGetter"; | 36 private static final String TAG = "MediaResourceGetter"; |
37 private static final MediaMetadata EMPTY_METADATA = new MediaMetadata(0,0,0,
false); | 37 private static final MediaMetadata EMPTY_METADATA = new MediaMetadata(0,0,0,
false); |
38 | 38 |
39 private final MediaMetadataRetriever mRetriever = new MediaMetadataRetriever
(); | 39 private final MediaMetadataRetriever mRetriever = new MediaMetadataRetriever
(); |
40 | 40 |
41 private static String PACKAGE_NAME = null; | |
42 | |
43 @VisibleForTesting | 41 @VisibleForTesting |
44 static class MediaMetadata { | 42 static class MediaMetadata { |
45 private final int mDurationInMilliseconds; | 43 private final int mDurationInMilliseconds; |
46 private final int mWidth; | 44 private final int mWidth; |
47 private final int mHeight; | 45 private final int mHeight; |
48 private final boolean mSuccess; | 46 private final boolean mSuccess; |
49 | 47 |
50 MediaMetadata(int durationInMilliseconds, int width, int height, boolean
success) { | 48 MediaMetadata(int durationInMilliseconds, int width, int height, boolean
success) { |
51 mDurationInMilliseconds = durationInMilliseconds; | 49 mDurationInMilliseconds = durationInMilliseconds; |
52 mWidth = width; | 50 mWidth = width; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 return false; | 107 return false; |
110 return true; | 108 return true; |
111 } | 109 } |
112 } | 110 } |
113 | 111 |
114 @CalledByNative | 112 @CalledByNative |
115 private static MediaMetadata extractMediaMetadata(final Context context, | 113 private static MediaMetadata extractMediaMetadata(final Context context, |
116 final String url, | 114 final String url, |
117 final String cookies, | 115 final String cookies, |
118 final String userAgent) { | 116 final String userAgent) { |
119 PACKAGE_NAME = context.getPackageName(); | |
120 return new MediaResourceGetter().extract( | 117 return new MediaResourceGetter().extract( |
121 context, url, cookies, userAgent); | 118 context, url, cookies, userAgent); |
122 } | 119 } |
123 | 120 |
124 @CalledByNative | 121 @CalledByNative |
125 private static MediaMetadata extractMediaMetadataFromFd(int fd, | 122 private static MediaMetadata extractMediaMetadataFromFd(int fd, |
126 long offset, | 123 long offset, |
127 long length) { | 124 long length) { |
128 return new MediaResourceGetter().extract(fd, offset, length); | 125 return new MediaResourceGetter().extract(fd, offset, length); |
129 } | 126 } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 Log.e(TAG, "Cannot parse uri.", e); | 216 Log.e(TAG, "Cannot parse uri.", e); |
220 return false; | 217 return false; |
221 } | 218 } |
222 String scheme = uri.getScheme(); | 219 String scheme = uri.getScheme(); |
223 if (scheme == null || scheme.equals("file")) { | 220 if (scheme == null || scheme.equals("file")) { |
224 File file = uriToFile(uri.getPath()); | 221 File file = uriToFile(uri.getPath()); |
225 if (!file.exists()) { | 222 if (!file.exists()) { |
226 Log.e(TAG, "File does not exist."); | 223 Log.e(TAG, "File does not exist."); |
227 return false; | 224 return false; |
228 } | 225 } |
229 if (!filePathAcceptable(file)) { | 226 if (!filePathAcceptable(file, context)) { |
230 Log.e(TAG, "Refusing to read from unsafe file location."); | 227 Log.e(TAG, "Refusing to read from unsafe file location."); |
231 return false; | 228 return false; |
232 } | 229 } |
233 try { | 230 try { |
234 configure(file.getAbsolutePath()); | 231 configure(file.getAbsolutePath()); |
235 return true; | 232 return true; |
236 } catch (RuntimeException e) { | 233 } catch (RuntimeException e) { |
237 Log.e(TAG, "Error configuring data source", e); | 234 Log.e(TAG, "Error configuring data source", e); |
238 return false; | 235 return false; |
239 } | 236 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 || host.equals("127.0.0.1") // typical IP v4 expression | 295 || host.equals("127.0.0.1") // typical IP v4 expression |
299 || host.equals("[::1]")); // typical IP v6 expression | 296 || host.equals("[::1]")); // typical IP v6 expression |
300 } | 297 } |
301 | 298 |
302 /** | 299 /** |
303 * @param file the file whose path should be checked | 300 * @param file the file whose path should be checked |
304 * @return true if and only if the file is in a location that we consider | 301 * @return true if and only if the file is in a location that we consider |
305 * safe to read from, such as /mnt/sdcard. | 302 * safe to read from, such as /mnt/sdcard. |
306 */ | 303 */ |
307 @VisibleForTesting | 304 @VisibleForTesting |
308 boolean filePathAcceptable(File file) { | 305 boolean filePathAcceptable(File file, Context context) { |
309 final String path; | 306 final String path; |
310 try { | 307 try { |
311 path = file.getCanonicalPath(); | 308 path = file.getCanonicalPath(); |
312 } catch (IOException e) { | 309 } catch (IOException e) { |
313 // Canonicalization has failed. Assume malicious, give up. | 310 // Canonicalization has failed. Assume malicious, give up. |
314 Log.w(TAG, "canonicalization of file path failed"); | 311 Log.w(TAG, "canonicalization of file path failed"); |
315 return false; | 312 return false; |
316 } | 313 } |
317 // In order to properly match the roots we must also canonicalize the | 314 // In order to properly match the roots we must also canonicalize the |
318 // well-known paths we are matching against. If we don't, then we can | 315 // well-known paths we are matching against. If we don't, then we can |
319 // get unusual results in testing systems or possibly on rooted devices. | 316 // get unusual results in testing systems or possibly on rooted devices. |
320 // Note that canonicalized directory paths always end with '/'. | 317 // Note that canonicalized directory paths always end with '/'. |
321 List<String> acceptablePaths = canonicalize(getRawAcceptableDirectories(
)); | 318 List<String> acceptablePaths = canonicalize(getRawAcceptableDirectories(
context)); |
322 acceptablePaths.add(getExternalStorageDirectory()); | 319 acceptablePaths.add(getExternalStorageDirectory()); |
323 Log.d(TAG, "canonicalized file path: " + path); | 320 Log.d(TAG, "canonicalized file path: " + path); |
324 for (String acceptablePath : acceptablePaths) { | 321 for (String acceptablePath : acceptablePaths) { |
325 if (path.startsWith(acceptablePath)) { | 322 if (path.startsWith(acceptablePath)) { |
326 return true; | 323 return true; |
327 } | 324 } |
328 } | 325 } |
329 return false; | 326 return false; |
330 } | 327 } |
331 | 328 |
(...skipping 25 matching lines...) Expand all Loading... |
357 return null; | 354 return null; |
358 } | 355 } |
359 NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); | 356 NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); |
360 if (info == null) { | 357 if (info == null) { |
361 Log.d(TAG, "no active network"); | 358 Log.d(TAG, "no active network"); |
362 return null; | 359 return null; |
363 } | 360 } |
364 return info.getType(); | 361 return info.getType(); |
365 } | 362 } |
366 | 363 |
367 private List<String> getRawAcceptableDirectories() { | 364 private List<String> getRawAcceptableDirectories(Context context) { |
368 List<String> result = new ArrayList<String>(); | 365 List<String> result = new ArrayList<String>(); |
369 result.add("/mnt/sdcard/"); | 366 result.add("/mnt/sdcard/"); |
370 result.add("/sdcard/"); | 367 result.add("/sdcard/"); |
371 if (PACKAGE_NAME != null) | 368 result.add("/data/data/" + context.getPackageName() + "/cache/"); |
372 result.add("/data/data/" + PACKAGE_NAME + "/cache/"); | |
373 return result; | 369 return result; |
374 } | 370 } |
375 | 371 |
376 private List<String> canonicalize(List<String> paths) { | 372 private List<String> canonicalize(List<String> paths) { |
377 List<String> result = new ArrayList<String>(paths.size()); | 373 List<String> result = new ArrayList<String>(paths.size()); |
378 try { | 374 try { |
379 for (String path : paths) { | 375 for (String path : paths) { |
380 result.add(new File(path).getCanonicalPath()); | 376 result.add(new File(path).getCanonicalPath()); |
381 } | 377 } |
382 return result; | 378 return result; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 @VisibleForTesting | 411 @VisibleForTesting |
416 void configure(String path) { | 412 void configure(String path) { |
417 mRetriever.setDataSource(path); | 413 mRetriever.setDataSource(path); |
418 } | 414 } |
419 | 415 |
420 @VisibleForTesting | 416 @VisibleForTesting |
421 String extractMetadata(int key) { | 417 String extractMetadata(int key) { |
422 return mRetriever.extractMetadata(key); | 418 return mRetriever.extractMetadata(key); |
423 } | 419 } |
424 } | 420 } |
OLD | NEW |