Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[flutter_webview] Fix allowsInlineMediaPlayback ignored on iOS #3791

Merged
merged 9 commits into from
Apr 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/webview_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<WebViewController> controllerCompleter =
Completer<WebViewController>();
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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<WebViewController> controllerCompleter =
Completer<WebViewController>();
Completer<void> pageLoaded = Completer<void>();
Completer<void> videoPlaying = Completer<void>();

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>{
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);
},
Expand All @@ -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<WebViewController>();
pageLoaded = Completer<void>();
testWidgets(
'Video plays full screen when allowsInlineMediaPlayback is false',
(WidgetTester tester) async {
Completer<WebViewController> controllerCompleter =
Completer<WebViewController>();
Completer<void> pageLoaded = Completer<void>();
Completer<void> videoPlaying = Completer<void>();

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>{
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);
},
Expand All @@ -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', () {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions packages/webview_flutter/ios/Classes/FlutterWebView.m
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ - (instancetype)initWithFrame:(CGRect)frame
NSDictionary<NSString*, id>* settings = args[@"settings"];

WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
[self applyConfigurationSettings:settings toConfiguration:configuration];
configuration.userContentController = userContentController;
[self updateAutoMediaPlaybackPolicy:args[@"autoMediaPlaybackPolicy"]
inConfiguration:configuration];
Expand Down Expand Up @@ -347,9 +348,6 @@ - (NSString*)applySettings:(NSDictionary<NSString*, id>*)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];
}
Expand All @@ -361,6 +359,18 @@ - (NSString*)applySettings:(NSDictionary<NSString*, id>*)settings {
[unknownKeys componentsJoinedByString:@", "]];
}

- (void)applyConfigurationSettings:(NSDictionary<NSString*, id>*)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]) {
Expand Down
2 changes: 1 addition & 1 deletion packages/webview_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down