Skip to content

Commit

Permalink
[flutter_webview] Fix allowsInlineMediaPlayback ignored on iOS (flu…
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Yang committed Apr 7, 2021
1 parent 3f2e2ac commit 97ac042
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 22 deletions.
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

0 comments on commit 97ac042

Please sign in to comment.