From d550e53dc3314a0eb51e8882a2b87420e931e5b3 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Wed, 8 Mar 2023 21:34:47 -0500 Subject: [PATCH] Revert "[video_player] Passing http headers to file constructor (#3266)" This reverts commit 73e7ef741357f4c1cc6cedaebb72f04719c47668. --- .../video_player/video_player/CHANGELOG.md | 3 +- .../video_player/lib/video_player.dart | 9 +- .../video_player/video_player/pubspec.yaml | 2 +- .../video_player/test/video_player_test.dart | 16 ---- .../video_player_android/CHANGELOG.md | 4 - .../plugins/videoplayer/VideoPlayer.java | 49 ++++++----- .../plugins/videoplayer/VideoPlayerTest.java | 88 +------------------ .../lib/src/android_video_player.dart | 1 - .../video_player_android/pubspec.yaml | 2 +- .../test/android_video_player_test.dart | 12 --- 10 files changed, 35 insertions(+), 151 deletions(-) diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md index 67c9fc4fce09..5c4c9df601b5 100644 --- a/packages/video_player/video_player/CHANGELOG.md +++ b/packages/video_player/video_player/CHANGELOG.md @@ -1,6 +1,5 @@ -## 2.6.0 +## NEXT -* Adds option to configure HTTP headers via `VideoPlayerController` to fix access to M3U8 files on Android. * Aligns Dart and Flutter SDK constraints. ## 2.5.3 diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart index feaf77c5fe99..2b5c6252c9d2 100644 --- a/packages/video_player/video_player/lib/video_player.dart +++ b/packages/video_player/video_player/lib/video_player.dart @@ -230,7 +230,7 @@ class VideoPlayerController extends ValueNotifier { /// null. /// **Android only**: The [formatHint] option allows the caller to override /// the video format detection code. - /// [httpHeaders] option allows to specify HTTP headers. + /// [httpHeaders] option allows to specify HTTP headers /// for the request to the [dataSource]. VideoPlayerController.network( this.dataSource, { @@ -246,16 +246,14 @@ class VideoPlayerController extends ValueNotifier { /// Constructs a [VideoPlayerController] playing a video from a file. /// /// This will load the file from a file:// URI constructed from [file]'s path. - /// [httpHeaders] option allows to specify HTTP headers, mainly used for hls files like (m3u8). VideoPlayerController.file(File file, - {Future? closedCaptionFile, - this.videoPlayerOptions, - this.httpHeaders = const {}}) + {Future? closedCaptionFile, this.videoPlayerOptions}) : _closedCaptionFileFuture = closedCaptionFile, dataSource = Uri.file(file.absolute.path).toString(), dataSourceType = DataSourceType.file, package = null, formatHint = null, + httpHeaders = const {}, super(VideoPlayerValue(duration: Duration.zero)); /// Constructs a [VideoPlayerController] playing a video from a contentUri. @@ -346,7 +344,6 @@ class VideoPlayerController extends ValueNotifier { dataSourceDescription = DataSource( sourceType: DataSourceType.file, uri: dataSource, - httpHeaders: httpHeaders, ); break; case DataSourceType.contentUri: diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml index cf2c61758a49..7d4aca6794a1 100644 --- a/packages/video_player/video_player/pubspec.yaml +++ b/packages/video_player/video_player/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for displaying inline video with other Flutter widgets on Android, iOS, and web. repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 -version: 2.6.0 +version: 2.5.3 environment: sdk: ">=2.17.0 <3.0.0" diff --git a/packages/video_player/video_player/test/video_player_test.dart b/packages/video_player/video_player/test/video_player_test.dart index a24ac843f6c9..023202d19518 100644 --- a/packages/video_player/video_player/test/video_player_test.dart +++ b/packages/video_player/video_player/test/video_player_test.dart @@ -358,22 +358,6 @@ void main() { reason: 'Actual string: $uri'); }, skip: kIsWeb /* Web does not support file assets. */); - test('file with headers (m3u8)', () async { - final VideoPlayerController controller = VideoPlayerController.file( - File('a.avi'), - httpHeaders: {'Authorization': 'Bearer token'}, - ); - await controller.initialize(); - - final String uri = fakeVideoPlayerPlatform.dataSources[0].uri!; - expect(uri.startsWith('file:///'), true, reason: 'Actual string: $uri'); - expect(uri.endsWith('/a.avi'), true, reason: 'Actual string: $uri'); - - expect( - fakeVideoPlayerPlatform.dataSources[0].httpHeaders, - {'Authorization': 'Bearer token'}, - ); - }, skip: kIsWeb /* Web does not support file assets. */); test('successful initialize on controller with error clears error', () async { final VideoPlayerController controller = VideoPlayerController.network( diff --git a/packages/video_player/video_player_android/CHANGELOG.md b/packages/video_player/video_player_android/CHANGELOG.md index 86c83e5ec809..3e09f66f9f1a 100644 --- a/packages/video_player/video_player_android/CHANGELOG.md +++ b/packages/video_player/video_player_android/CHANGELOG.md @@ -1,7 +1,3 @@ -## 2.4.0 - -* Allows setting the ExoPlayer user agent by passing a User-Agent HTTP header. - ## 2.3.12 * Clarifies explanation of endorsement in README. diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index 2aed171033ab..e130c995aa2a 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -56,14 +56,10 @@ final class VideoPlayer { private final EventChannel eventChannel; - private static final String USER_AGENT = "User-Agent"; - @VisibleForTesting boolean isInitialized = false; private final VideoPlayerOptions options; - private DefaultHttpDataSource.Factory httpDataSourceFactory = new DefaultHttpDataSource.Factory(); - VideoPlayer( Context context, EventChannel eventChannel, @@ -77,11 +73,23 @@ final class VideoPlayer { this.options = options; ExoPlayer exoPlayer = new ExoPlayer.Builder(context).build(); + Uri uri = Uri.parse(dataSource); + DataSource.Factory dataSourceFactory; - buildHttpDataSourceFactory(httpHeaders); - DataSource.Factory dataSourceFactory = - new DefaultDataSource.Factory(context, httpDataSourceFactory); + if (isHTTP(uri)) { + DefaultHttpDataSource.Factory httpDataSourceFactory = + new DefaultHttpDataSource.Factory() + .setUserAgent("ExoPlayer") + .setAllowCrossProtocolRedirects(true); + + if (httpHeaders != null && !httpHeaders.isEmpty()) { + httpDataSourceFactory.setDefaultRequestProperties(httpHeaders); + } + dataSourceFactory = httpDataSourceFactory; + } else { + dataSourceFactory = new DefaultDataSource.Factory(context); + } MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, formatHint, context); @@ -98,29 +106,20 @@ final class VideoPlayer { EventChannel eventChannel, TextureRegistry.SurfaceTextureEntry textureEntry, VideoPlayerOptions options, - QueuingEventSink eventSink, - DefaultHttpDataSource.Factory httpDataSourceFactory) { + QueuingEventSink eventSink) { this.eventChannel = eventChannel; this.textureEntry = textureEntry; this.options = options; - this.httpDataSourceFactory = httpDataSourceFactory; setUpVideoPlayer(exoPlayer, eventSink); } - @VisibleForTesting - public void buildHttpDataSourceFactory(@NonNull Map httpHeaders) { - final boolean httpHeadersNotEmpty = !httpHeaders.isEmpty(); - final String userAgent = - httpHeadersNotEmpty && httpHeaders.containsKey(USER_AGENT) - ? httpHeaders.get(USER_AGENT) - : "ExoPlayer"; - - httpDataSourceFactory.setUserAgent(userAgent).setAllowCrossProtocolRedirects(true); - - if (httpHeadersNotEmpty) { - httpDataSourceFactory.setDefaultRequestProperties(httpHeaders); + private static boolean isHTTP(Uri uri) { + if (uri == null || uri.getScheme() == null) { + return false; } + String scheme = uri.getScheme(); + return scheme.equals("http") || scheme.equals("https"); } private MediaSource buildMediaSource( @@ -150,11 +149,13 @@ private MediaSource buildMediaSource( switch (type) { case C.CONTENT_TYPE_SS: return new SsMediaSource.Factory( - new DefaultSsChunkSource.Factory(mediaDataSourceFactory), mediaDataSourceFactory) + new DefaultSsChunkSource.Factory(mediaDataSourceFactory), + new DefaultDataSource.Factory(context, mediaDataSourceFactory)) .createMediaSource(MediaItem.fromUri(uri)); case C.CONTENT_TYPE_DASH: return new DashMediaSource.Factory( - new DefaultDashChunkSource.Factory(mediaDataSourceFactory), mediaDataSourceFactory) + new DefaultDashChunkSource.Factory(mediaDataSourceFactory), + new DefaultDataSource.Factory(context, mediaDataSourceFactory)) .createMediaSource(MediaItem.fromUri(uri)); case C.CONTENT_TYPE_HLS: return new HlsMediaSource.Factory(mediaDataSourceFactory) diff --git a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java index 5a646d8d41c3..194f7905b63a 100644 --- a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java +++ b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java @@ -5,20 +5,15 @@ package io.flutter.plugins.videoplayer; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; import io.flutter.plugin.common.EventChannel; import io.flutter.view.TextureRegistry; import java.util.HashMap; -import java.util.Map; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,7 +29,6 @@ public class VideoPlayerTest { private TextureRegistry.SurfaceTextureEntry fakeSurfaceTextureEntry; private VideoPlayerOptions fakeVideoPlayerOptions; private QueuingEventSink fakeEventSink; - private DefaultHttpDataSource.Factory httpDataSourceFactorySpy; @Captor private ArgumentCaptor> eventCaptor; @@ -47,76 +41,6 @@ public void before() { fakeSurfaceTextureEntry = mock(TextureRegistry.SurfaceTextureEntry.class); fakeVideoPlayerOptions = mock(VideoPlayerOptions.class); fakeEventSink = mock(QueuingEventSink.class); - httpDataSourceFactorySpy = spy(new DefaultHttpDataSource.Factory()); - } - - @Test - public void videoPlayer_buildsHttpDataSourceFactoryProperlyWhenHttpHeadersNull() { - VideoPlayer videoPlayer = - new VideoPlayer( - fakeExoPlayer, - fakeEventChannel, - fakeSurfaceTextureEntry, - fakeVideoPlayerOptions, - fakeEventSink, - httpDataSourceFactorySpy); - - videoPlayer.buildHttpDataSourceFactory(new HashMap<>()); - - verify(httpDataSourceFactorySpy).setUserAgent("ExoPlayer"); - verify(httpDataSourceFactorySpy).setAllowCrossProtocolRedirects(true); - verify(httpDataSourceFactorySpy, never()).setDefaultRequestProperties(any()); - } - - @Test - public void - videoPlayer_buildsHttpDataSourceFactoryProperlyWhenHttpHeadersNonNullAndUserAgentSpecified() { - VideoPlayer videoPlayer = - new VideoPlayer( - fakeExoPlayer, - fakeEventChannel, - fakeSurfaceTextureEntry, - fakeVideoPlayerOptions, - fakeEventSink, - httpDataSourceFactorySpy); - Map httpHeaders = - new HashMap() { - { - put("header", "value"); - put("User-Agent", "userAgent"); - } - }; - - videoPlayer.buildHttpDataSourceFactory(httpHeaders); - - verify(httpDataSourceFactorySpy).setUserAgent("userAgent"); - verify(httpDataSourceFactorySpy).setAllowCrossProtocolRedirects(true); - verify(httpDataSourceFactorySpy).setDefaultRequestProperties(httpHeaders); - } - - @Test - public void - videoPlayer_buildsHttpDataSourceFactoryProperlyWhenHttpHeadersNonNullAndUserAgentNotSpecified() { - VideoPlayer videoPlayer = - new VideoPlayer( - fakeExoPlayer, - fakeEventChannel, - fakeSurfaceTextureEntry, - fakeVideoPlayerOptions, - fakeEventSink, - httpDataSourceFactorySpy); - Map httpHeaders = - new HashMap() { - { - put("header", "value"); - } - }; - - videoPlayer.buildHttpDataSourceFactory(httpHeaders); - - verify(httpDataSourceFactorySpy).setUserAgent("ExoPlayer"); - verify(httpDataSourceFactorySpy).setAllowCrossProtocolRedirects(true); - verify(httpDataSourceFactorySpy).setDefaultRequestProperties(httpHeaders); } @Test @@ -127,8 +51,7 @@ public void sendInitializedSendsExpectedEvent_90RotationDegrees() { fakeEventChannel, fakeSurfaceTextureEntry, fakeVideoPlayerOptions, - fakeEventSink, - httpDataSourceFactorySpy); + fakeEventSink); Format testFormat = new Format.Builder().setWidth(100).setHeight(200).setRotationDegrees(90).build(); @@ -156,8 +79,7 @@ public void sendInitializedSendsExpectedEvent_270RotationDegrees() { fakeEventChannel, fakeSurfaceTextureEntry, fakeVideoPlayerOptions, - fakeEventSink, - httpDataSourceFactorySpy); + fakeEventSink); Format testFormat = new Format.Builder().setWidth(100).setHeight(200).setRotationDegrees(270).build(); @@ -185,8 +107,7 @@ public void sendInitializedSendsExpectedEvent_0RotationDegrees() { fakeEventChannel, fakeSurfaceTextureEntry, fakeVideoPlayerOptions, - fakeEventSink, - httpDataSourceFactorySpy); + fakeEventSink); Format testFormat = new Format.Builder().setWidth(100).setHeight(200).setRotationDegrees(0).build(); @@ -214,8 +135,7 @@ public void sendInitializedSendsExpectedEvent_180RotationDegrees() { fakeEventChannel, fakeSurfaceTextureEntry, fakeVideoPlayerOptions, - fakeEventSink, - httpDataSourceFactorySpy); + fakeEventSink); Format testFormat = new Format.Builder().setWidth(100).setHeight(200).setRotationDegrees(180).build(); diff --git a/packages/video_player/video_player_android/lib/src/android_video_player.dart b/packages/video_player/video_player_android/lib/src/android_video_player.dart index c8a2b7adbcbd..cee6d7d38f66 100644 --- a/packages/video_player/video_player_android/lib/src/android_video_player.dart +++ b/packages/video_player/video_player_android/lib/src/android_video_player.dart @@ -49,7 +49,6 @@ class AndroidVideoPlayer extends VideoPlayerPlatform { break; case DataSourceType.file: uri = dataSource.uri; - httpHeaders = dataSource.httpHeaders; break; case DataSourceType.contentUri: uri = dataSource.uri; diff --git a/packages/video_player/video_player_android/pubspec.yaml b/packages/video_player/video_player_android/pubspec.yaml index 03307eb3b063..1c007f68f128 100644 --- a/packages/video_player/video_player_android/pubspec.yaml +++ b/packages/video_player/video_player_android/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_android description: Android implementation of the video_player plugin. repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 -version: 2.4.0 +version: 2.3.12 environment: sdk: ">=2.17.0 <3.0.0" diff --git a/packages/video_player/video_player_android/test/android_video_player_test.dart b/packages/video_player/video_player_android/test/android_video_player_test.dart index 00feb2743966..6aa24e5c1808 100644 --- a/packages/video_player/video_player_android/test/android_video_player_test.dart +++ b/packages/video_player/video_player_android/test/android_video_player_test.dart @@ -176,18 +176,6 @@ void main() { expect(textureId, 3); }); - test('create with file (some headers)', () async { - final int? textureId = await player.create(DataSource( - sourceType: DataSourceType.file, - uri: 'someUri', - httpHeaders: {'Authorization': 'Bearer token'}, - )); - expect(log.log.last, 'create'); - expect(log.createMessage?.uri, 'someUri'); - expect(log.createMessage?.httpHeaders, - {'Authorization': 'Bearer token'}); - expect(textureId, 3); - }); test('setLooping', () async { await player.setLooping(1, true); expect(log.log.last, 'setLooping');