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

Commit 97ac042

Browse files
author
Chris Yang
authored
[flutter_webview] Fix allowsInlineMediaPlayback ignored on iOS (#3791)
1 parent 3f2e2ac commit 97ac042

File tree

5 files changed

+80
-22
lines changed

5 files changed

+80
-22
lines changed

packages/webview_flutter/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.4
2+
3+
* Fix a bug where `allowsInlineMediaPlayback` is not respected on iOS.
4+
15
## 2.0.3
26

37
* Fixes bug where scroll bars on the Android non-hybrid WebView are rendered on

packages/webview_flutter/example/integration_test/webview_flutter_test.dart

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ void main() {
6161
expect(currentUrl, 'https://www.google.com/');
6262
});
6363

64-
// enable this once https://github.com/flutter/flutter/issues/31510
65-
// is resolved.
6664
testWidgets('loadUrl with headers', (WidgetTester tester) async {
6765
final Completer<WebViewController> controllerCompleter =
6866
Completer<WebViewController>();
@@ -343,6 +341,11 @@ void main() {
343341
function play() {
344342
var video = document.getElementById("video");
345343
video.play();
344+
video.addEventListener('timeupdate', videoTimeUpdateHandler, false);
345+
}
346+
function videoTimeUpdateHandler(e) {
347+
var video = document.getElementById("video");
348+
VideoTestTime.postMessage(video.currentTime);
346349
}
347350
function isPaused() {
348351
var video = document.getElementById("video");
@@ -420,7 +423,7 @@ void main() {
420423

421424
isPaused = await controller.evaluateJavascript('isPaused();');
422425
expect(isPaused, _webviewBool(true));
423-
}, skip: true /* https://github.com/flutter/flutter/issues/72572 */);
426+
});
424427

425428
testWidgets('Changes to initialMediaPlaybackPolicy are ignored',
426429
(WidgetTester tester) async {
@@ -479,24 +482,36 @@ void main() {
479482

480483
isPaused = await controller.evaluateJavascript('isPaused();');
481484
expect(isPaused, _webviewBool(false));
482-
}, skip: true /* https://github.com/flutter/flutter/issues/72572 */);
485+
});
483486

484487
testWidgets('Video plays inline when allowsInlineMediaPlayback is true',
485488
(WidgetTester tester) async {
486489
Completer<WebViewController> controllerCompleter =
487490
Completer<WebViewController>();
488491
Completer<void> pageLoaded = Completer<void>();
492+
Completer<void> videoPlaying = Completer<void>();
489493

490494
await tester.pumpWidget(
491495
Directionality(
492496
textDirection: TextDirection.ltr,
493497
child: WebView(
494-
key: GlobalKey(),
495498
initialUrl: 'data:text/html;charset=utf-8;base64,$videoTestBase64',
496499
onWebViewCreated: (WebViewController controller) {
497500
controllerCompleter.complete(controller);
498501
},
499502
javascriptMode: JavascriptMode.unrestricted,
503+
javascriptChannels: <JavascriptChannel>{
504+
JavascriptChannel(
505+
name: 'VideoTestTime',
506+
onMessageReceived: (JavascriptMessage message) {
507+
final double currentTime = double.parse(message.message);
508+
// Let it play for at least 1 second to make sure the related video's properties are set.
509+
if (currentTime > 1) {
510+
videoPlaying.complete(null);
511+
}
512+
},
513+
),
514+
},
500515
onPageFinished: (String url) {
501516
pageLoaded.complete(null);
502517
},
@@ -508,23 +523,46 @@ void main() {
508523
WebViewController controller = await controllerCompleter.future;
509524
await pageLoaded.future;
510525

511-
String isFullScreen =
526+
// Pump once to trigger the video play.
527+
await tester.pump();
528+
529+
// Makes sure we get the correct event that indicates the video is actually playing.
530+
await videoPlaying.future;
531+
532+
String fullScreen =
512533
await controller.evaluateJavascript('isFullScreen();');
513-
expect(isFullScreen, _webviewBool(false));
534+
expect(fullScreen, _webviewBool(false));
535+
});
514536

515-
controllerCompleter = Completer<WebViewController>();
516-
pageLoaded = Completer<void>();
537+
testWidgets(
538+
'Video plays full screen when allowsInlineMediaPlayback is false',
539+
(WidgetTester tester) async {
540+
Completer<WebViewController> controllerCompleter =
541+
Completer<WebViewController>();
542+
Completer<void> pageLoaded = Completer<void>();
543+
Completer<void> videoPlaying = Completer<void>();
517544

518545
await tester.pumpWidget(
519546
Directionality(
520547
textDirection: TextDirection.ltr,
521548
child: WebView(
522-
key: GlobalKey(),
523549
initialUrl: 'data:text/html;charset=utf-8;base64,$videoTestBase64',
524550
onWebViewCreated: (WebViewController controller) {
525551
controllerCompleter.complete(controller);
526552
},
527553
javascriptMode: JavascriptMode.unrestricted,
554+
javascriptChannels: <JavascriptChannel>{
555+
JavascriptChannel(
556+
name: 'VideoTestTime',
557+
onMessageReceived: (JavascriptMessage message) {
558+
final double currentTime = double.parse(message.message);
559+
// Let it play for at least 1 second to make sure the related video's properties are set.
560+
if (currentTime > 1) {
561+
videoPlaying.complete(null);
562+
}
563+
},
564+
),
565+
},
528566
onPageFinished: (String url) {
529567
pageLoaded.complete(null);
530568
},
@@ -533,13 +571,19 @@ void main() {
533571
),
534572
),
535573
);
536-
537-
controller = await controllerCompleter.future;
574+
WebViewController controller = await controllerCompleter.future;
538575
await pageLoaded.future;
539576

540-
isFullScreen = await controller.evaluateJavascript('isFullScreen();');
541-
expect(isFullScreen, _webviewBool(true));
542-
}, skip: true /* https://github.com/flutter/flutter/issues/72572 */);
577+
// Pump once to trigger the video play.
578+
await tester.pump();
579+
580+
// Makes sure we get the correct event that indicates the video is actually playing.
581+
await videoPlaying.future;
582+
583+
String fullScreen =
584+
await controller.evaluateJavascript('isFullScreen();');
585+
expect(fullScreen, _webviewBool(true));
586+
});
543587
});
544588

545589
group('Audio playback policy', () {
@@ -639,7 +683,7 @@ void main() {
639683

640684
isPaused = await controller.evaluateJavascript('isPaused();');
641685
expect(isPaused, _webviewBool(true));
642-
}, skip: true /* https://github.com/flutter/flutter/issues/72572 */);
686+
});
643687

644688
testWidgets('Changes to initialMediaPlaybackPolocy are ignored',
645689
(WidgetTester tester) async {
@@ -708,7 +752,7 @@ void main() {
708752

709753
isPaused = await controller.evaluateJavascript('isPaused();');
710754
expect(isPaused, _webviewBool(false));
711-
}, skip: true /* https://github.com/flutter/flutter/issues/72572 */);
755+
});
712756
});
713757

714758
testWidgets('getTitle', (WidgetTester tester) async {

packages/webview_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/webview_flutter/ios/Classes/FlutterWebView.m

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ - (instancetype)initWithFrame:(CGRect)frame
8989
NSDictionary<NSString*, id>* settings = args[@"settings"];
9090

9191
WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
92+
[self applyConfigurationSettings:settings toConfiguration:configuration];
9293
configuration.userContentController = userContentController;
9394
[self updateAutoMediaPlaybackPolicy:args[@"autoMediaPlaybackPolicy"]
9495
inConfiguration:configuration];
@@ -347,9 +348,6 @@ - (NSString*)applySettings:(NSDictionary<NSString*, id>*)settings {
347348
} else if ([key isEqualToString:@"userAgent"]) {
348349
NSString* userAgent = settings[key];
349350
[self updateUserAgent:[userAgent isEqual:[NSNull null]] ? nil : userAgent];
350-
} else if ([key isEqualToString:@"allowsInlineMediaPlayback"]) {
351-
NSNumber* allowsInlineMediaPlayback = settings[key];
352-
_webView.configuration.allowsInlineMediaPlayback = [allowsInlineMediaPlayback boolValue];
353351
} else {
354352
[unknownKeys addObject:key];
355353
}
@@ -361,6 +359,18 @@ - (NSString*)applySettings:(NSDictionary<NSString*, id>*)settings {
361359
[unknownKeys componentsJoinedByString:@", "]];
362360
}
363361

362+
- (void)applyConfigurationSettings:(NSDictionary<NSString*, id>*)settings
363+
toConfiguration:(WKWebViewConfiguration*)configuration {
364+
NSAssert(configuration != _webView.configuration,
365+
@"configuration needs to be updated before webView.configuration.");
366+
for (NSString* key in settings) {
367+
if ([key isEqualToString:@"allowsInlineMediaPlayback"]) {
368+
NSNumber* allowsInlineMediaPlayback = settings[key];
369+
configuration.allowsInlineMediaPlayback = [allowsInlineMediaPlayback boolValue];
370+
}
371+
}
372+
}
373+
364374
- (void)updateJsMode:(NSNumber*)mode {
365375
WKPreferences* preferences = [[_webView configuration] preferences];
366376
switch ([mode integerValue]) {

packages/webview_flutter/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: webview_flutter
22
description: A Flutter plugin that provides a WebView widget on Android and iOS.
33
homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter
4-
version: 2.0.3
4+
version: 2.0.4
55

66
environment:
77
sdk: ">=2.12.0-259.9.beta <3.0.0"

0 commit comments

Comments
 (0)