Commit 0ee39637 by olly Committed by Oliver Woodman

Follow 307/308 POST redirects for license requests

I was considering putting this directly in DefaultHttpDataSource, however:

- We'd need to modify at least OkHttpDataSource as well. I'm not sure whether
  Cronet follows this type of redirect automatically or not.
- HttpDataSource instances don't know how they're going to be used, so it's
  probably correct that they behave like the underlying network stack.

Issue: #4108

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=192745408
parent 22b8ab5c
...@@ -51,13 +51,15 @@ ...@@ -51,13 +51,15 @@
* Add release method to Cache interface. * Add release method to Cache interface.
* Prevent multiple instances of SimpleCache in the same folder. * Prevent multiple instances of SimpleCache in the same folder.
Previous instance must be released. Previous instance must be released.
* Store redirected URI * Cache redirect URLs
([#2360](https://github.com/google/ExoPlayer/issues/2360)). ([#2360](https://github.com/google/ExoPlayer/issues/2360)).
* DRM: * DRM:
* Allow multiple listeners for `DefaultDrmSessionManager`. * Allow multiple listeners for `DefaultDrmSessionManager`.
* Pass `DrmSessionManager` to `ExoPlayerFactory` instead of `RendererFactory`. * Pass `DrmSessionManager` to `ExoPlayerFactory` instead of `RendererFactory`.
* Change minimum API requirement for CBC and pattern encryption from 24 to 25 * Change minimum API requirement for CBC and pattern encryption from 24 to 25
([#4022][https://github.com/google/ExoPlayer/issues/4022]). ([#4022][https://github.com/google/ExoPlayer/issues/4022]).
* Fix handling of 307/308 redirects when making license requests
([#4108](https://github.com/google/ExoPlayer/issues/4108)).
* Removed default renderer time offset of 60000000 from internal player. The * Removed default renderer time offset of 60000000 from internal player. The
actual renderer timestamp offset can be obtained by listening to actual renderer timestamp offset can be obtained by listening to
`BaseRenderer.onStreamChanged`. `BaseRenderer.onStreamChanged`.
......
...@@ -24,10 +24,12 @@ import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest; ...@@ -24,10 +24,12 @@ import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest;
import com.google.android.exoplayer2.upstream.DataSourceInputStream; import com.google.android.exoplayer2.upstream.DataSourceInputStream;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
...@@ -37,6 +39,8 @@ import java.util.UUID; ...@@ -37,6 +39,8 @@ import java.util.UUID;
@TargetApi(18) @TargetApi(18)
public final class HttpMediaDrmCallback implements MediaDrmCallback { public final class HttpMediaDrmCallback implements MediaDrmCallback {
private static final int MAX_MANUAL_REDIRECTS = 5;
private final HttpDataSource.Factory dataSourceFactory; private final HttpDataSource.Factory dataSourceFactory;
private final String defaultLicenseUrl; private final String defaultLicenseUrl;
private final boolean forceDefaultLicenseUrl; private final boolean forceDefaultLicenseUrl;
...@@ -138,14 +142,46 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback { ...@@ -138,14 +142,46 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
dataSource.setRequestProperty(requestProperty.getKey(), requestProperty.getValue()); dataSource.setRequestProperty(requestProperty.getKey(), requestProperty.getValue());
} }
} }
DataSpec dataSpec = new DataSpec(Uri.parse(url), data, 0, 0, C.LENGTH_UNSET, null,
DataSpec.FLAG_ALLOW_GZIP); int manualRedirectCount = 0;
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec); while (true) {
try { DataSpec dataSpec =
return Util.toByteArray(inputStream); new DataSpec(
} finally { Uri.parse(url),
Util.closeQuietly(inputStream); data,
/* absoluteStreamPosition= */ 0,
/* position= */ 0,
/* length= */ C.LENGTH_UNSET,
/* key= */ null,
DataSpec.FLAG_ALLOW_GZIP);
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
try {
return Util.toByteArray(inputStream);
} catch (InvalidResponseCodeException e) {
// For POST requests, the underlying network stack will not normally follow 307 or 308
// redirects automatically. Do so manually here.
boolean manuallyRedirect =
(e.responseCode == 307 || e.responseCode == 308)
&& manualRedirectCount++ < MAX_MANUAL_REDIRECTS;
url = manuallyRedirect ? getRedirectUrl(e) : null;
if (url == null) {
throw e;
}
} finally {
Util.closeQuietly(inputStream);
}
}
}
private static String getRedirectUrl(InvalidResponseCodeException exception) {
Map<String, List<String>> headerFields = exception.headerFields;
if (headerFields != null) {
List<String> locationHeaders = headerFields.get("Location");
if (locationHeaders != null && !locationHeaders.isEmpty()) {
return locationHeaders.get(0);
}
} }
return null;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment