| 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.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.pm.PackageManager; | 9 import android.content.pm.PackageManager; |
| 10 import android.media.MediaMetadataRetriever; | 10 import android.media.MediaMetadataRetriever; |
| 11 import android.net.ConnectivityManager; | 11 import android.net.ConnectivityManager; |
| 12 import android.net.NetworkInfo; | 12 import android.net.NetworkInfo; |
| 13 import android.net.Uri; |
| 13 import android.os.ParcelFileDescriptor; | 14 import android.os.ParcelFileDescriptor; |
| 14 import android.text.TextUtils; | 15 import android.text.TextUtils; |
| 15 | 16 |
| 16 import org.chromium.base.Log; | 17 import org.chromium.base.Log; |
| 17 import org.chromium.base.PathUtils; | 18 import org.chromium.base.PathUtils; |
| 18 import org.chromium.base.VisibleForTesting; | 19 import org.chromium.base.VisibleForTesting; |
| 19 import org.chromium.base.annotations.CalledByNative; | 20 import org.chromium.base.annotations.CalledByNative; |
| 20 import org.chromium.base.annotations.JNINamespace; | 21 import org.chromium.base.annotations.JNINamespace; |
| 21 | 22 |
| 22 import java.io.File; | 23 import java.io.File; |
| 23 import java.io.IOException; | 24 import java.io.IOException; |
| 24 import java.net.URI; | 25 import java.net.URI; |
| 25 import java.util.ArrayList; | 26 import java.util.ArrayList; |
| 26 import java.util.HashMap; | 27 import java.util.HashMap; |
| 27 import java.util.List; | 28 import java.util.List; |
| 28 import java.util.Map; | 29 import java.util.Map; |
| 29 | 30 |
| 30 /** | 31 /** |
| 31 * Java counterpart of android MediaResourceGetter. | 32 * Java counterpart of android MediaResourceGetter. |
| 32 */ | 33 */ |
| 33 @JNINamespace("content") | 34 @JNINamespace("content") |
| 34 class MediaResourceGetter { | 35 class MediaResourceGetter { |
| 35 | 36 private static final String TAG = "cr_MediaResource"; |
| 36 private static final String TAG = "cr.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 @VisibleForTesting | 41 @VisibleForTesting |
| 42 static class MediaMetadata { | 42 static class MediaMetadata { |
| 43 private final int mDurationInMilliseconds; | 43 private final int mDurationInMilliseconds; |
| 44 private final int mWidth; | 44 private final int mWidth; |
| 45 private final int mHeight; | 45 private final int mHeight; |
| 46 private final boolean mSuccess; | 46 private final boolean mSuccess; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 height = Integer.parseInt(heightString); | 188 height = Integer.parseInt(heightString); |
| 189 } catch (NumberFormatException e) { | 189 } catch (NumberFormatException e) { |
| 190 Log.w(TAG, "non-numeric height: %s", heightString); | 190 Log.w(TAG, "non-numeric height: %s", heightString); |
| 191 return EMPTY_METADATA; | 191 return EMPTY_METADATA; |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 MediaMetadata result = new MediaMetadata(durationMillis, width, heig
ht, true); | 194 MediaMetadata result = new MediaMetadata(durationMillis, width, heig
ht, true); |
| 195 Log.d(TAG, "extracted valid metadata: %s", result); | 195 Log.d(TAG, "extracted valid metadata: %s", result); |
| 196 return result; | 196 return result; |
| 197 } catch (RuntimeException e) { | 197 } catch (RuntimeException e) { |
| 198 Log.e(TAG, "Unable to extract metadata: %s", e.getMessage()); | 198 Log.e(TAG, "Unable to extract metadata: %s", e); |
| 199 return EMPTY_METADATA; | 199 return EMPTY_METADATA; |
| 200 } | 200 } |
| 201 } | 201 } |
| 202 | 202 |
| 203 @VisibleForTesting | 203 @VisibleForTesting |
| 204 boolean configure(Context context, String url, String cookies, String userAg
ent) { | 204 boolean configure(Context context, String url, String cookies, String userAg
ent) { |
| 205 URI uri; | 205 URI uri; |
| 206 try { | 206 try { |
| 207 uri = URI.create(url); | 207 uri = URI.create(url); |
| 208 } catch (IllegalArgumentException e) { | 208 } catch (IllegalArgumentException e) { |
| 209 Log.e(TAG, "Cannot parse uri: %s", e.getMessage()); | 209 Log.e(TAG, "Cannot parse uri: %s", e); |
| 210 return false; | 210 return false; |
| 211 } | 211 } |
| 212 String scheme = uri.getScheme(); | 212 String scheme = uri.getScheme(); |
| 213 if (scheme == null || scheme.equals("file")) { | 213 if (scheme == null || scheme.equals("file")) { |
| 214 File file = uriToFile(uri.getPath()); | 214 File file = uriToFile(uri.getPath()); |
| 215 if (!file.exists()) { | 215 if (!file.exists()) { |
| 216 Log.e(TAG, "File does not exist."); | 216 Log.e(TAG, "File does not exist."); |
| 217 return false; | 217 return false; |
| 218 } | 218 } |
| 219 if (!filePathAcceptable(file, context)) { | 219 if (!filePathAcceptable(file, context)) { |
| 220 Log.e(TAG, "Refusing to read from unsafe file location."); | 220 Log.e(TAG, "Refusing to read from unsafe file location."); |
| 221 return false; | 221 return false; |
| 222 } | 222 } |
| 223 try { | 223 try { |
| 224 configure(file.getAbsolutePath()); | 224 configure(file.getAbsolutePath()); |
| 225 return true; | 225 return true; |
| 226 } catch (RuntimeException e) { | 226 } catch (RuntimeException e) { |
| 227 Log.e(TAG, "Error configuring data source: %s", e.getMessage()); | 227 Log.e(TAG, "Error configuring data source: %s", e); |
| 228 return false; | 228 return false; |
| 229 } | 229 } |
| 230 } | 230 } |
| 231 if (scheme.equals("content")) { |
| 232 try { |
| 233 configure(context, Uri.parse(uri.toString())); |
| 234 return true; |
| 235 } catch (RuntimeException e) { |
| 236 Log.e(TAG, "Error configuring data source: %s", e); |
| 237 return false; |
| 238 } |
| 239 } |
| 231 if (uri.getPath() != null && uri.getPath().endsWith(".m3u8")) { | 240 if (uri.getPath() != null && uri.getPath().endsWith(".m3u8")) { |
| 232 // MediaMetadataRetriever does not work with HLS correctly. | 241 // MediaMetadataRetriever does not work with HLS correctly. |
| 233 return false; | 242 return false; |
| 234 } | 243 } |
| 235 final String host = uri.getHost(); | 244 final String host = uri.getHost(); |
| 236 if (!isLoopbackAddress(host) && !isNetworkReliable(context)) { | 245 if (!isLoopbackAddress(host) && !isNetworkReliable(context)) { |
| 237 Log.w(TAG, "non-file URI can't be read due to unsuitable network con
ditions"); | 246 Log.w(TAG, "non-file URI can't be read due to unsuitable network con
ditions"); |
| 238 return false; | 247 return false; |
| 239 } | 248 } |
| 240 Map<String, String> headersMap = new HashMap<String, String>(); | 249 Map<String, String> headersMap = new HashMap<String, String>(); |
| 241 if (!TextUtils.isEmpty(cookies)) { | 250 if (!TextUtils.isEmpty(cookies)) { |
| 242 headersMap.put("Cookie", cookies); | 251 headersMap.put("Cookie", cookies); |
| 243 } | 252 } |
| 244 if (!TextUtils.isEmpty(userAgent)) { | 253 if (!TextUtils.isEmpty(userAgent)) { |
| 245 headersMap.put("User-Agent", userAgent); | 254 headersMap.put("User-Agent", userAgent); |
| 246 } | 255 } |
| 247 try { | 256 try { |
| 248 configure(url, headersMap); | 257 configure(url, headersMap); |
| 249 return true; | 258 return true; |
| 250 } catch (RuntimeException e) { | 259 } catch (RuntimeException e) { |
| 251 Log.e(TAG, "Error configuring data source: %s", e.getMessage()); | 260 Log.e(TAG, "Error configuring data source: %s", e); |
| 252 return false; | 261 return false; |
| 253 } | 262 } |
| 254 } | 263 } |
| 255 | 264 |
| 256 /** | 265 /** |
| 257 * @return true if the device is on an ethernet or wifi network. | 266 * @return true if the device is on an ethernet or wifi network. |
| 258 * If anything goes wrong (e.g., permission denied while trying to access | 267 * If anything goes wrong (e.g., permission denied while trying to access |
| 259 * the network state), returns false. | 268 * the network state), returns false. |
| 260 */ | 269 */ |
| 261 @VisibleForTesting | 270 @VisibleForTesting |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 void configure(String url, Map<String, String> headers) { | 400 void configure(String url, Map<String, String> headers) { |
| 392 mRetriever.setDataSource(url, headers); | 401 mRetriever.setDataSource(url, headers); |
| 393 } | 402 } |
| 394 | 403 |
| 395 @VisibleForTesting | 404 @VisibleForTesting |
| 396 void configure(String path) { | 405 void configure(String path) { |
| 397 mRetriever.setDataSource(path); | 406 mRetriever.setDataSource(path); |
| 398 } | 407 } |
| 399 | 408 |
| 400 @VisibleForTesting | 409 @VisibleForTesting |
| 410 void configure(Context context, Uri uri) { |
| 411 mRetriever.setDataSource(context, uri); |
| 412 } |
| 413 |
| 414 @VisibleForTesting |
| 401 String extractMetadata(int key) { | 415 String extractMetadata(int key) { |
| 402 return mRetriever.extractMetadata(key); | 416 return mRetriever.extractMetadata(key); |
| 403 } | 417 } |
| 404 } | 418 } |
| OLD | NEW |