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 |
36 private static final String TAG = "cr.MediaResourceGetter"; | 37 private static final String TAG = "cr_MediaResource"; |
37 private static final MediaMetadata EMPTY_METADATA = new MediaMetadata(0, 0, 0, false); | 38 private static final MediaMetadata EMPTY_METADATA = new MediaMetadata(0, 0, 0, false); |
38 | 39 |
39 private final MediaMetadataRetriever mRetriever = new MediaMetadataRetriever (); | 40 private final MediaMetadataRetriever mRetriever = new MediaMetadataRetriever (); |
40 | 41 |
41 @VisibleForTesting | 42 @VisibleForTesting |
42 static class MediaMetadata { | 43 static class MediaMetadata { |
43 private final int mDurationInMilliseconds; | 44 private final int mDurationInMilliseconds; |
44 private final int mWidth; | 45 private final int mWidth; |
45 private final int mHeight; | 46 private final int mHeight; |
46 private final boolean mSuccess; | 47 private final boolean mSuccess; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 height = Integer.parseInt(heightString); | 189 height = Integer.parseInt(heightString); |
189 } catch (NumberFormatException e) { | 190 } catch (NumberFormatException e) { |
190 Log.w(TAG, "non-numeric height: %s", heightString); | 191 Log.w(TAG, "non-numeric height: %s", heightString); |
191 return EMPTY_METADATA; | 192 return EMPTY_METADATA; |
192 } | 193 } |
193 } | 194 } |
194 MediaMetadata result = new MediaMetadata(durationMillis, width, heig ht, true); | 195 MediaMetadata result = new MediaMetadata(durationMillis, width, heig ht, true); |
195 Log.d(TAG, "extracted valid metadata: %s", result); | 196 Log.d(TAG, "extracted valid metadata: %s", result); |
196 return result; | 197 return result; |
197 } catch (RuntimeException e) { | 198 } catch (RuntimeException e) { |
198 Log.e(TAG, "Unable to extract metadata: %s", e.getMessage()); | 199 Log.e(TAG, "Unable to extract metadata: %s", e); |
199 return EMPTY_METADATA; | 200 return EMPTY_METADATA; |
200 } | 201 } |
201 } | 202 } |
202 | 203 |
203 @VisibleForTesting | 204 @VisibleForTesting |
204 boolean configure(Context context, String url, String cookies, String userAg ent) { | 205 boolean configure(Context context, String url, String cookies, String userAg ent) { |
205 URI uri; | 206 URI uri; |
206 try { | 207 try { |
207 uri = URI.create(url); | 208 uri = URI.create(url); |
208 } catch (IllegalArgumentException e) { | 209 } catch (IllegalArgumentException e) { |
209 Log.e(TAG, "Cannot parse uri: %s", e.getMessage()); | 210 Log.e(TAG, "Cannot parse uri: %s", e); |
210 return false; | 211 return false; |
211 } | 212 } |
212 String scheme = uri.getScheme(); | 213 String scheme = uri.getScheme(); |
213 if (scheme == null || scheme.equals("file")) { | 214 if (scheme == null || scheme.equals("file")) { |
214 File file = uriToFile(uri.getPath()); | 215 File file = uriToFile(uri.getPath()); |
215 if (!file.exists()) { | 216 if (!file.exists()) { |
216 Log.e(TAG, "File does not exist."); | 217 Log.e(TAG, "File does not exist."); |
217 return false; | 218 return false; |
218 } | 219 } |
219 if (!filePathAcceptable(file, context)) { | 220 if (!filePathAcceptable(file, context)) { |
220 Log.e(TAG, "Refusing to read from unsafe file location."); | 221 Log.e(TAG, "Refusing to read from unsafe file location."); |
221 return false; | 222 return false; |
222 } | 223 } |
223 try { | 224 try { |
224 configure(file.getAbsolutePath()); | 225 configure(file.getAbsolutePath()); |
225 return true; | 226 return true; |
226 } catch (RuntimeException e) { | 227 } catch (RuntimeException e) { |
227 Log.e(TAG, "Error configuring data source: %s", e.getMessage()); | 228 Log.e(TAG, "Error configuring data source: %s", e); |
228 return false; | 229 return false; |
229 } | 230 } |
230 } | 231 } |
232 if (scheme.equals("content")) { | |
233 try { | |
234 configure(context, Uri.parse(uri.toString())); | |
235 return true; | |
236 } catch (RuntimeException e) { | |
237 Log.e(TAG, "Error configuring data source: %s", e); | |
238 return false; | |
239 } | |
240 } | |
231 if (uri.getPath() != null && uri.getPath().endsWith(".m3u8")) { | 241 if (uri.getPath() != null && uri.getPath().endsWith(".m3u8")) { |
232 // MediaMetadataRetriever does not work with HLS correctly. | 242 // MediaMetadataRetriever does not work with HLS correctly. |
233 return false; | 243 return false; |
234 } | 244 } |
235 final String host = uri.getHost(); | 245 final String host = uri.getHost(); |
236 if (!isLoopbackAddress(host) && !isNetworkReliable(context)) { | 246 if (!isLoopbackAddress(host) && !isNetworkReliable(context)) { |
237 Log.w(TAG, "non-file URI can't be read due to unsuitable network con ditions"); | 247 Log.w(TAG, "non-file URI can't be read due to unsuitable network con ditions"); |
238 return false; | 248 return false; |
239 } | 249 } |
240 Map<String, String> headersMap = new HashMap<String, String>(); | 250 Map<String, String> headersMap = new HashMap<String, String>(); |
241 if (!TextUtils.isEmpty(cookies)) { | 251 if (!TextUtils.isEmpty(cookies)) { |
242 headersMap.put("Cookie", cookies); | 252 headersMap.put("Cookie", cookies); |
243 } | 253 } |
244 if (!TextUtils.isEmpty(userAgent)) { | 254 if (!TextUtils.isEmpty(userAgent)) { |
245 headersMap.put("User-Agent", userAgent); | 255 headersMap.put("User-Agent", userAgent); |
246 } | 256 } |
247 try { | 257 try { |
248 configure(url, headersMap); | 258 configure(url, headersMap); |
249 return true; | 259 return true; |
250 } catch (RuntimeException e) { | 260 } catch (RuntimeException e) { |
251 Log.e(TAG, "Error configuring data source: %s", e.getMessage()); | 261 Log.e(TAG, "Error configuring data source: %s", e); |
252 return false; | 262 return false; |
253 } | 263 } |
254 } | 264 } |
255 | 265 |
256 /** | 266 /** |
257 * @return true if the device is on an ethernet or wifi network. | 267 * @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 | 268 * If anything goes wrong (e.g., permission denied while trying to access |
259 * the network state), returns false. | 269 * the network state), returns false. |
260 */ | 270 */ |
261 @VisibleForTesting | 271 @VisibleForTesting |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 @VisibleForTesting | 400 @VisibleForTesting |
391 void configure(String url, Map<String, String> headers) { | 401 void configure(String url, Map<String, String> headers) { |
392 mRetriever.setDataSource(url, headers); | 402 mRetriever.setDataSource(url, headers); |
393 } | 403 } |
394 | 404 |
395 @VisibleForTesting | 405 @VisibleForTesting |
396 void configure(String path) { | 406 void configure(String path) { |
397 mRetriever.setDataSource(path); | 407 mRetriever.setDataSource(path); |
398 } | 408 } |
399 | 409 |
410 void configure(Context context, Uri uri) { | |
Ted C
2016/01/26 21:49:02
this should be private since it is not used outsid
horo
2016/01/27 06:46:57
Done.
Added unit tests.
| |
411 mRetriever.setDataSource(context, uri); | |
412 } | |
413 | |
400 @VisibleForTesting | 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 |