| 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.media; | 5 package org.chromium.media; |
| 6 | 6 |
| 7 import android.content.Context; | |
| 8 import android.media.MediaPlayer; | 7 import android.media.MediaPlayer; |
| 9 import android.media.MediaPlayer.TrackInfo; | 8 import android.media.MediaPlayer.TrackInfo; |
| 10 import android.net.Uri; | 9 import android.net.Uri; |
| 11 import android.os.AsyncTask; | 10 import android.os.AsyncTask; |
| 12 import android.os.Build; | 11 import android.os.Build; |
| 13 import android.os.ParcelFileDescriptor; | 12 import android.os.ParcelFileDescriptor; |
| 14 import android.text.TextUtils; | 13 import android.text.TextUtils; |
| 15 import android.util.Base64; | 14 import android.util.Base64; |
| 16 import android.util.Base64InputStream; | 15 import android.util.Base64InputStream; |
| 17 import android.view.Surface; | 16 import android.view.Surface; |
| 18 | 17 |
| 18 import org.chromium.base.ContextUtils; |
| 19 import org.chromium.base.Log; | 19 import org.chromium.base.Log; |
| 20 import org.chromium.base.StreamUtil; | 20 import org.chromium.base.StreamUtil; |
| 21 import org.chromium.base.annotations.CalledByNative; | 21 import org.chromium.base.annotations.CalledByNative; |
| 22 import org.chromium.base.annotations.JNINamespace; | 22 import org.chromium.base.annotations.JNINamespace; |
| 23 | 23 |
| 24 import java.io.ByteArrayInputStream; | 24 import java.io.ByteArrayInputStream; |
| 25 import java.io.File; | 25 import java.io.File; |
| 26 import java.io.FileOutputStream; | 26 import java.io.FileOutputStream; |
| 27 import java.io.IOException; | 27 import java.io.IOException; |
| 28 import java.io.InputStream; | 28 import java.io.InputStream; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 getLocalPlayer().pause(); | 170 getLocalPlayer().pause(); |
| 171 } | 171 } |
| 172 | 172 |
| 173 @CalledByNative | 173 @CalledByNative |
| 174 protected void seekTo(int msec) throws IllegalStateException { | 174 protected void seekTo(int msec) throws IllegalStateException { |
| 175 getLocalPlayer().seekTo(msec); | 175 getLocalPlayer().seekTo(msec); |
| 176 } | 176 } |
| 177 | 177 |
| 178 @CalledByNative | 178 @CalledByNative |
| 179 protected boolean setDataSource( | 179 protected boolean setDataSource( |
| 180 Context context, String url, String cookies, String userAgent, boole
an hideUrlLog) { | 180 String url, String cookies, String userAgent, boolean hideUrlLog) { |
| 181 Uri uri = Uri.parse(url); | 181 Uri uri = Uri.parse(url); |
| 182 HashMap<String, String> headersMap = new HashMap<String, String>(); | 182 HashMap<String, String> headersMap = new HashMap<String, String>(); |
| 183 if (hideUrlLog) headersMap.put("x-hide-urls-from-log", "true"); | 183 if (hideUrlLog) headersMap.put("x-hide-urls-from-log", "true"); |
| 184 if (!TextUtils.isEmpty(cookies)) headersMap.put("Cookie", cookies); | 184 if (!TextUtils.isEmpty(cookies)) headersMap.put("Cookie", cookies); |
| 185 if (!TextUtils.isEmpty(userAgent)) headersMap.put("User-Agent", userAgen
t); | 185 if (!TextUtils.isEmpty(userAgent)) headersMap.put("User-Agent", userAgen
t); |
| 186 // The security origin check is enforced for devices above K. For device
s below K, | 186 // The security origin check is enforced for devices above K. For device
s below K, |
| 187 // only anonymous media HTTP request (no cookies) may be considered same
-origin. | 187 // only anonymous media HTTP request (no cookies) may be considered same
-origin. |
| 188 // Note that if the server rejects the request we must not consider it s
ame-origin. | 188 // Note that if the server rejects the request we must not consider it s
ame-origin. |
| 189 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { | 189 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { |
| 190 headersMap.put("allow-cross-domain-redirect", "false"); | 190 headersMap.put("allow-cross-domain-redirect", "false"); |
| 191 } | 191 } |
| 192 try { | 192 try { |
| 193 getLocalPlayer().setDataSource(context, uri, headersMap); | 193 getLocalPlayer().setDataSource(ContextUtils.getApplicationContext(),
uri, headersMap); |
| 194 return true; | 194 return true; |
| 195 } catch (Exception e) { | 195 } catch (Exception e) { |
| 196 return false; | 196 return false; |
| 197 } | 197 } |
| 198 } | 198 } |
| 199 | 199 |
| 200 @CalledByNative | 200 @CalledByNative |
| 201 protected boolean setDataSourceFromFd(int fd, long offset, long length) { | 201 protected boolean setDataSourceFromFd(int fd, long offset, long length) { |
| 202 try { | 202 try { |
| 203 ParcelFileDescriptor parcelFd = ParcelFileDescriptor.adoptFd(fd); | 203 ParcelFileDescriptor parcelFd = ParcelFileDescriptor.adoptFd(fd); |
| 204 getLocalPlayer().setDataSource(parcelFd.getFileDescriptor(), offset,
length); | 204 getLocalPlayer().setDataSource(parcelFd.getFileDescriptor(), offset,
length); |
| 205 parcelFd.close(); | 205 parcelFd.close(); |
| 206 return true; | 206 return true; |
| 207 } catch (IOException e) { | 207 } catch (IOException e) { |
| 208 Log.e(TAG, "Failed to set data source from file descriptor: " + e); | 208 Log.e(TAG, "Failed to set data source from file descriptor: " + e); |
| 209 return false; | 209 return false; |
| 210 } | 210 } |
| 211 } | 211 } |
| 212 | 212 |
| 213 @CalledByNative | 213 @CalledByNative |
| 214 protected boolean setDataUriDataSource(final Context context, final String u
rl) { | 214 protected boolean setDataUriDataSource(final String url) { |
| 215 if (mLoadDataUriTask != null) { | 215 if (mLoadDataUriTask != null) { |
| 216 mLoadDataUriTask.cancel(true); | 216 mLoadDataUriTask.cancel(true); |
| 217 mLoadDataUriTask = null; | 217 mLoadDataUriTask = null; |
| 218 } | 218 } |
| 219 | 219 |
| 220 if (!url.startsWith("data:")) return false; | 220 if (!url.startsWith("data:")) return false; |
| 221 int headerStop = url.indexOf(','); | 221 int headerStop = url.indexOf(','); |
| 222 if (headerStop == -1) return false; | 222 if (headerStop == -1) return false; |
| 223 String header = url.substring(0, headerStop); | 223 String header = url.substring(0, headerStop); |
| 224 final String data = url.substring(headerStop + 1); | 224 final String data = url.substring(headerStop + 1); |
| 225 | 225 |
| 226 String headerContent = header.substring(5); | 226 String headerContent = header.substring(5); |
| 227 String headerInfo[] = headerContent.split(";"); | 227 String headerInfo[] = headerContent.split(";"); |
| 228 if (headerInfo.length != 2) return false; | 228 if (headerInfo.length != 2) return false; |
| 229 if (!"base64".equals(headerInfo[1])) return false; | 229 if (!"base64".equals(headerInfo[1])) return false; |
| 230 | 230 |
| 231 mLoadDataUriTask = new LoadDataUriTask(context, data); | 231 mLoadDataUriTask = new LoadDataUriTask(data); |
| 232 mLoadDataUriTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | 232 mLoadDataUriTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
| 233 return true; | 233 return true; |
| 234 } | 234 } |
| 235 | 235 |
| 236 private class LoadDataUriTask extends AsyncTask<Void, Void, Boolean> { | 236 private class LoadDataUriTask extends AsyncTask<Void, Void, Boolean> { |
| 237 private final String mData; | 237 private final String mData; |
| 238 private final Context mContext; | |
| 239 private File mTempFile; | 238 private File mTempFile; |
| 240 | 239 |
| 241 public LoadDataUriTask(Context context, String data) { | 240 public LoadDataUriTask(String data) { |
| 242 mData = data; | 241 mData = data; |
| 243 mContext = context; | |
| 244 } | 242 } |
| 245 | 243 |
| 246 @Override | 244 @Override |
| 247 protected Boolean doInBackground(Void... params) { | 245 protected Boolean doInBackground(Void... params) { |
| 248 FileOutputStream fos = null; | 246 FileOutputStream fos = null; |
| 249 try { | 247 try { |
| 250 mTempFile = File.createTempFile("decoded", "mediadata"); | 248 mTempFile = File.createTempFile("decoded", "mediadata"); |
| 251 fos = new FileOutputStream(mTempFile); | 249 fos = new FileOutputStream(mTempFile); |
| 252 InputStream stream = new ByteArrayInputStream(mData.getBytes()); | 250 InputStream stream = new ByteArrayInputStream(mData.getBytes()); |
| 253 Base64InputStream decoder = new Base64InputStream(stream, Base64
.DEFAULT); | 251 Base64InputStream decoder = new Base64InputStream(stream, Base64
.DEFAULT); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 267 | 265 |
| 268 @Override | 266 @Override |
| 269 protected void onPostExecute(Boolean result) { | 267 protected void onPostExecute(Boolean result) { |
| 270 if (isCancelled()) { | 268 if (isCancelled()) { |
| 271 deleteFile(); | 269 deleteFile(); |
| 272 return; | 270 return; |
| 273 } | 271 } |
| 274 | 272 |
| 275 if (result) { | 273 if (result) { |
| 276 try { | 274 try { |
| 277 getLocalPlayer().setDataSource(mContext, Uri.fromFile(mTempF
ile)); | 275 getLocalPlayer().setDataSource( |
| 276 ContextUtils.getApplicationContext(), Uri.fromFile(m
TempFile)); |
| 278 } catch (IOException e) { | 277 } catch (IOException e) { |
| 279 result = false; | 278 result = false; |
| 280 } | 279 } |
| 281 } | 280 } |
| 282 | 281 |
| 283 deleteFile(); | 282 deleteFile(); |
| 284 assert (mNativeMediaPlayerBridge != 0); | 283 assert (mNativeMediaPlayerBridge != 0); |
| 285 nativeOnDidSetDataUriDataSource(mNativeMediaPlayerBridge, result); | 284 nativeOnDidSetDataUriDataSource(mNativeMediaPlayerBridge, result); |
| 286 } | 285 } |
| 287 | 286 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 Log.e(TAG, "Cannot access metadata: " + e); | 388 Log.e(TAG, "Cannot access metadata: " + e); |
| 390 } catch (NoSuchFieldException e) { | 389 } catch (NoSuchFieldException e) { |
| 391 Log.e(TAG, "Cannot find matching fields in Metadata class: " + e); | 390 Log.e(TAG, "Cannot find matching fields in Metadata class: " + e); |
| 392 } | 391 } |
| 393 return new AllowedOperations(canPause, canSeekForward, canSeekBackward); | 392 return new AllowedOperations(canPause, canSeekForward, canSeekBackward); |
| 394 } | 393 } |
| 395 | 394 |
| 396 private native void nativeOnDidSetDataUriDataSource(long nativeMediaPlayerBr
idge, | 395 private native void nativeOnDidSetDataUriDataSource(long nativeMediaPlayerBr
idge, |
| 397 boolean success); | 396 boolean success); |
| 398 } | 397 } |
| OLD | NEW |