Make special exception for cleartext-not-permitted

#exofixit

PiperOrigin-RevId: 344246408
This commit is contained in:
olly 2020-11-25 15:05:03 +00:00 committed by Andrew Lewis
parent 1201466b5c
commit 2fbad2105e
6 changed files with 41 additions and 6 deletions

View File

@ -21,7 +21,7 @@
<string name="unexpected_intent_action">Unexpected intent action: <xliff:g id="action">%1$s</xliff:g></string> <string name="unexpected_intent_action">Unexpected intent action: <xliff:g id="action">%1$s</xliff:g></string>
<string name="error_cleartext_not_permitted">Cleartext traffic not permitted</string> <string name="error_cleartext_not_permitted">Cleartext HTTP traffic not permitted. See https://exoplayer.dev/issues/cleartext-not-permitted</string>
<string name="error_generic">Playback failed</string> <string name="error_generic">Playback failed</string>

View File

@ -443,8 +443,14 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
transferInitializing(dataSpec); transferInitializing(dataSpec);
try { try {
boolean connectionOpened = blockUntilConnectTimeout(); boolean connectionOpened = blockUntilConnectTimeout();
if (exception != null) { @Nullable IOException connectionOpenException = exception;
throw new OpenException(exception, dataSpec, getStatus(urlRequest)); if (connectionOpenException != null) {
@Nullable String message = connectionOpenException.getMessage();
if (message != null
&& Util.toLowerInvariant(message).contains("err_cleartext_not_permitted")) {
throw new CleartextNotPermittedException(connectionOpenException, dataSpec);
}
throw new OpenException(connectionOpenException, dataSpec, getStatus(urlRequest));
} else if (!connectionOpened) { } else if (!connectionOpened) {
// The timeout was reached before the connection was opened. // The timeout was reached before the connection was opened.
throw new OpenException(new SocketTimeoutException(), dataSpec, getStatus(urlRequest)); throw new OpenException(new SocketTimeoutException(), dataSpec, getStatus(urlRequest));

View File

@ -242,6 +242,11 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
responseBody = Assertions.checkNotNull(response.body()); responseBody = Assertions.checkNotNull(response.body());
responseByteStream = responseBody.byteStream(); responseByteStream = responseBody.byteStream();
} catch (IOException e) { } catch (IOException e) {
@Nullable String message = e.getMessage();
if (message != null
&& Util.toLowerInvariant(message).matches("cleartext communication.*not permitted.*")) {
throw new CleartextNotPermittedException(e, dataSpec);
}
throw new HttpDataSourceException( throw new HttpDataSourceException(
"Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN); "Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN);
} }

View File

@ -271,7 +271,24 @@ public interface HttpDataSource extends DataSource {
this.dataSpec = dataSpec; this.dataSpec = dataSpec;
this.type = type; this.type = type;
} }
}
/**
* Thrown when cleartext HTTP traffic is not permitted. For more information including how to
* enable cleartext traffic, see the <a
* href="https://exoplayer.dev/issues/cleartext-not-permitted">corresponding troubleshooting
* topic</a>.
*/
final class CleartextNotPermittedException extends HttpDataSourceException {
public CleartextNotPermittedException(IOException cause, DataSpec dataSpec) {
super(
"Cleartext HTTP traffic not permitted. See"
+ " https://exoplayer.dev/issues/cleartext-not-permitted",
cause,
dataSpec,
TYPE_OPEN);
}
} }
/** /**
@ -285,7 +302,6 @@ public interface HttpDataSource extends DataSource {
super("Invalid content type: " + contentType, dataSpec, TYPE_OPEN); super("Invalid content type: " + contentType, dataSpec, TYPE_OPEN);
this.contentType = contentType; this.contentType = contentType;
} }
} }
/** /**

View File

@ -306,6 +306,11 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou
try { try {
connection = makeConnection(dataSpec); connection = makeConnection(dataSpec);
} catch (IOException e) { } catch (IOException e) {
@Nullable String message = e.getMessage();
if (message != null
&& Util.toLowerInvariant(message).matches("cleartext http traffic.*not permitted.*")) {
throw new CleartextNotPermittedException(e, dataSpec);
}
throw new HttpDataSourceException( throw new HttpDataSourceException(
"Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN); "Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN);
} }

View File

@ -19,6 +19,7 @@ import static java.lang.Math.min;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.upstream.HttpDataSource.CleartextNotPermittedException;
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException; import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
import com.google.android.exoplayer2.upstream.Loader.UnexpectedLoaderException; import com.google.android.exoplayer2.upstream.Loader.UnexpectedLoaderException;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -86,14 +87,16 @@ public class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPolicy {
/** /**
* Retries for any exception that is not a subclass of {@link ParserException}, {@link * Retries for any exception that is not a subclass of {@link ParserException}, {@link
* FileNotFoundException} or {@link UnexpectedLoaderException}. The retry delay is calculated as * FileNotFoundException}, {@link CleartextNotPermittedException} or {@link
* {@code Math.min((errorCount - 1) * 1000, 5000)}. * UnexpectedLoaderException}. The retry delay is calculated as {@code Math.min((errorCount - 1) *
* 1000, 5000)}.
*/ */
@Override @Override
public long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) { public long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) {
IOException exception = loadErrorInfo.exception; IOException exception = loadErrorInfo.exception;
return exception instanceof ParserException return exception instanceof ParserException
|| exception instanceof FileNotFoundException || exception instanceof FileNotFoundException
|| exception instanceof CleartextNotPermittedException
|| exception instanceof UnexpectedLoaderException || exception instanceof UnexpectedLoaderException
? C.TIME_UNSET ? C.TIME_UNSET
: min((loadErrorInfo.errorCount - 1) * 1000, 5000); : min((loadErrorInfo.errorCount - 1) * 1000, 5000);