diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md index b8e5e0bba5e0..85767577c403 100644 --- a/packages/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.4 + +* Fix a bug where `allowsInlineMediaPlayback` is not respected on iOS. + ## 2.0.3 * Fixes bug where scroll bars on the Android non-hybrid WebView are rendered on diff --git a/packages/webview_flutter/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/example/integration_test/webview_flutter_test.dart index 2c7c765f34bf..408eec5730df 100644 --- a/packages/webview_flutter/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/example/integration_test/webview_flutter_test.dart @@ -61,8 +61,6 @@ void main() { expect(currentUrl, 'https://www.google.com/'); }); - // enable this once https://github.com/flutter/flutter/issues/31510 - // is resolved. testWidgets('loadUrl with headers', (WidgetTester tester) async { final Completer controllerCompleter = Completer(); @@ -343,6 +341,11 @@ void main() { function play() { var video = document.getElementById("video"); video.play(); + video.addEventListener('timeupdate', videoTimeUpdateHandler, false); + } + function videoTimeUpdateHandler(e) { + var video = document.getElementById("video"); + VideoTestTime.postMessage(video.currentTime); } function isPaused() { var video = document.getElementById("video"); @@ -420,7 +423,7 @@ void main() { isPaused = await controller.evaluateJavascript('isPaused();'); expect(isPaused, _webviewBool(true)); - }, skip: true /* https://github.com/flutter/flutter/issues/72572 */); + }); testWidgets('Changes to initialMediaPlaybackPolicy are ignored', (WidgetTester tester) async { @@ -479,24 +482,36 @@ void main() { isPaused = await controller.evaluateJavascript('isPaused();'); expect(isPaused, _webviewBool(false)); - }, skip: true /* https://github.com/flutter/flutter/issues/72572 */); + }); testWidgets('Video plays inline when allowsInlineMediaPlayback is true', (WidgetTester tester) async { Completer controllerCompleter = Completer(); Completer pageLoaded = Completer(); + Completer videoPlaying = Completer(); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( - key: GlobalKey(), initialUrl: 'data:text/html;charset=utf-8;base64,$videoTestBase64', onWebViewCreated: (WebViewController controller) { controllerCompleter.complete(controller); }, javascriptMode: JavascriptMode.unrestricted, + javascriptChannels: { + JavascriptChannel( + name: 'VideoTestTime', + onMessageReceived: (JavascriptMessage message) { + final double currentTime = double.parse(message.message); + // Let it play for at least 1 second to make sure the related video's properties are set. + if (currentTime > 1) { + videoPlaying.complete(null); + } + }, + ), + }, onPageFinished: (String url) { pageLoaded.complete(null); }, @@ -508,23 +523,46 @@ void main() { WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - String isFullScreen = + // Pump once to trigger the video play. + await tester.pump(); + + // Makes sure we get the correct event that indicates the video is actually playing. + await videoPlaying.future; + + String fullScreen = await controller.evaluateJavascript('isFullScreen();'); - expect(isFullScreen, _webviewBool(false)); + expect(fullScreen, _webviewBool(false)); + }); - controllerCompleter = Completer(); - pageLoaded = Completer(); + testWidgets( + 'Video plays full screen when allowsInlineMediaPlayback is false', + (WidgetTester tester) async { + Completer controllerCompleter = + Completer(); + Completer pageLoaded = Completer(); + Completer videoPlaying = Completer(); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: WebView( - key: GlobalKey(), initialUrl: 'data:text/html;charset=utf-8;base64,$videoTestBase64', onWebViewCreated: (WebViewController controller) { controllerCompleter.complete(controller); }, javascriptMode: JavascriptMode.unrestricted, + javascriptChannels: { + JavascriptChannel( + name: 'VideoTestTime', + onMessageReceived: (JavascriptMessage message) { + final double currentTime = double.parse(message.message); + // Let it play for at least 1 second to make sure the related video's properties are set. + if (currentTime > 1) { + videoPlaying.complete(null); + } + }, + ), + }, onPageFinished: (String url) { pageLoaded.complete(null); }, @@ -533,13 +571,19 @@ void main() { ), ), ); - - controller = await controllerCompleter.future; + WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - isFullScreen = await controller.evaluateJavascript('isFullScreen();'); - expect(isFullScreen, _webviewBool(true)); - }, skip: true /* https://github.com/flutter/flutter/issues/72572 */); + // Pump once to trigger the video play. + await tester.pump(); + + // Makes sure we get the correct event that indicates the video is actually playing. + await videoPlaying.future; + + String fullScreen = + await controller.evaluateJavascript('isFullScreen();'); + expect(fullScreen, _webviewBool(true)); + }); }); group('Audio playback policy', () { @@ -639,7 +683,7 @@ void main() { isPaused = await controller.evaluateJavascript('isPaused();'); expect(isPaused, _webviewBool(true)); - }, skip: true /* https://github.com/flutter/flutter/issues/72572 */); + }); testWidgets('Changes to initialMediaPlaybackPolocy are ignored', (WidgetTester tester) async { @@ -708,7 +752,7 @@ void main() { isPaused = await controller.evaluateJavascript('isPaused();'); expect(isPaused, _webviewBool(false)); - }, skip: true /* https://github.com/flutter/flutter/issues/72572 */); + }); }); testWidgets('getTitle', (WidgetTester tester) async { diff --git a/packages/webview_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/webview_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 1d526a16ed0f..919434a6254f 100644 --- a/packages/webview_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/packages/webview_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/packages/webview_flutter/ios/Classes/FlutterWebView.m b/packages/webview_flutter/ios/Classes/FlutterWebView.m index 7ca36e33031c..8f4053a0b822 100644 --- a/packages/webview_flutter/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/ios/Classes/FlutterWebView.m @@ -89,6 +89,7 @@ - (instancetype)initWithFrame:(CGRect)frame NSDictionary* settings = args[@"settings"]; WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init]; + [self applyConfigurationSettings:settings toConfiguration:configuration]; configuration.userContentController = userContentController; [self updateAutoMediaPlaybackPolicy:args[@"autoMediaPlaybackPolicy"] inConfiguration:configuration]; @@ -347,9 +348,6 @@ - (NSString*)applySettings:(NSDictionary*)settings { } else if ([key isEqualToString:@"userAgent"]) { NSString* userAgent = settings[key]; [self updateUserAgent:[userAgent isEqual:[NSNull null]] ? nil : userAgent]; - } else if ([key isEqualToString:@"allowsInlineMediaPlayback"]) { - NSNumber* allowsInlineMediaPlayback = settings[key]; - _webView.configuration.allowsInlineMediaPlayback = [allowsInlineMediaPlayback boolValue]; } else { [unknownKeys addObject:key]; } @@ -361,6 +359,18 @@ - (NSString*)applySettings:(NSDictionary*)settings { [unknownKeys componentsJoinedByString:@", "]]; } +- (void)applyConfigurationSettings:(NSDictionary*)settings + toConfiguration:(WKWebViewConfiguration*)configuration { + NSAssert(configuration != _webView.configuration, + @"configuration needs to be updated before webView.configuration."); + for (NSString* key in settings) { + if ([key isEqualToString:@"allowsInlineMediaPlayback"]) { + NSNumber* allowsInlineMediaPlayback = settings[key]; + configuration.allowsInlineMediaPlayback = [allowsInlineMediaPlayback boolValue]; + } + } +} + - (void)updateJsMode:(NSNumber*)mode { WKPreferences* preferences = [[_webView configuration] preferences]; switch ([mode integerValue]) { diff --git a/packages/webview_flutter/pubspec.yaml b/packages/webview_flutter/pubspec.yaml index a89ded4e9014..f4fb0efe83e2 100644 --- a/packages/webview_flutter/pubspec.yaml +++ b/packages/webview_flutter/pubspec.yaml @@ -1,7 +1,7 @@ name: webview_flutter description: A Flutter plugin that provides a WebView widget on Android and iOS. homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter -version: 2.0.3 +version: 2.0.4 environment: sdk: ">=2.12.0-259.9.beta <3.0.0"