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

Commit 895b36e

Browse files
[webview_flutter_wkwebview] Add support for AutoMediaPlaybackPolicy on iOS (#6659)
1 parent c0eb51e commit 895b36e

12 files changed

+2917
-1002
lines changed

packages/webview_flutter/webview_flutter_wkwebview/lib/src/v4/src/webkit_webview_controller.dart

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,54 @@ import '../../foundation/foundation.dart';
1717
import '../../web_kit/web_kit.dart';
1818
import 'webkit_proxy.dart';
1919

20+
/// Media types that can require a user gesture to begin playing.
21+
///
22+
/// See [WebKitWebViewControllerCreationParams.mediaTypesRequiringUserAction].
23+
enum PlaybackMediaTypes {
24+
/// A media type that contains audio.
25+
audio,
26+
27+
/// A media type that contains video.
28+
video;
29+
30+
WKAudiovisualMediaType _toWKAudiovisualMediaType() {
31+
switch (this) {
32+
case PlaybackMediaTypes.audio:
33+
return WKAudiovisualMediaType.audio;
34+
case PlaybackMediaTypes.video:
35+
return WKAudiovisualMediaType.video;
36+
}
37+
}
38+
}
39+
2040
/// Object specifying creation parameters for a [WebKitWebViewController].
2141
@immutable
2242
class WebKitWebViewControllerCreationParams
2343
extends PlatformWebViewControllerCreationParams {
2444
/// Constructs a [WebKitWebViewControllerCreationParams].
2545
WebKitWebViewControllerCreationParams({
2646
@visibleForTesting this.webKitProxy = const WebKitProxy(),
27-
}) : _configuration = webKitProxy.createWebViewConfiguration();
47+
this.mediaTypesRequiringUserAction = const <PlaybackMediaTypes>{
48+
PlaybackMediaTypes.audio,
49+
PlaybackMediaTypes.video,
50+
},
51+
this.allowsInlineMediaPlayback = false,
52+
}) : _configuration = webKitProxy.createWebViewConfiguration() {
53+
if (mediaTypesRequiringUserAction.isEmpty) {
54+
_configuration.setMediaTypesRequiringUserActionForPlayback(
55+
<WKAudiovisualMediaType>{WKAudiovisualMediaType.none},
56+
);
57+
} else {
58+
_configuration.setMediaTypesRequiringUserActionForPlayback(
59+
mediaTypesRequiringUserAction
60+
.map<WKAudiovisualMediaType>(
61+
(PlaybackMediaTypes type) => type._toWKAudiovisualMediaType(),
62+
)
63+
.toSet(),
64+
);
65+
}
66+
_configuration.setAllowsInlineMediaPlayback(allowsInlineMediaPlayback);
67+
}
2868

2969
/// Constructs a [WebKitWebViewControllerCreationParams] using a
3070
/// [PlatformWebViewControllerCreationParams].
@@ -33,10 +73,31 @@ class WebKitWebViewControllerCreationParams
3373
// ignore: avoid_unused_constructor_parameters
3474
PlatformWebViewControllerCreationParams params, {
3575
@visibleForTesting WebKitProxy webKitProxy = const WebKitProxy(),
36-
}) : this(webKitProxy: webKitProxy);
76+
Set<PlaybackMediaTypes> mediaTypesRequiringUserAction =
77+
const <PlaybackMediaTypes>{
78+
PlaybackMediaTypes.audio,
79+
PlaybackMediaTypes.video,
80+
},
81+
bool allowsInlineMediaPlayback = false,
82+
}) : this(
83+
webKitProxy: webKitProxy,
84+
mediaTypesRequiringUserAction: mediaTypesRequiringUserAction,
85+
allowsInlineMediaPlayback: allowsInlineMediaPlayback,
86+
);
3787

3888
final WKWebViewConfiguration _configuration;
3989

90+
/// Media types that require a user gesture to begin playing.
91+
///
92+
/// Defaults to include [PlaybackMediaTypes.audio] and
93+
/// [PlaybackMediaTypes.video].
94+
final Set<PlaybackMediaTypes> mediaTypesRequiringUserAction;
95+
96+
/// Whether inline playback of HTML5 videos is allowed.
97+
///
98+
/// Defaults to false.
99+
final bool allowsInlineMediaPlayback;
100+
40101
/// Handles constructing objects and calling static methods for the WebKit
41102
/// native library.
42103
@visibleForTesting
@@ -226,11 +287,6 @@ class WebKitWebViewController extends PlatformWebViewController {
226287
return result.toString();
227288
}
228289

229-
/// Controls whether inline playback of HTML5 videos is allowed.
230-
Future<void> setAllowsInlineMediaPlayback(bool allow) {
231-
return _webView.configuration.setAllowsInlineMediaPlayback(allow);
232-
}
233-
234290
@override
235291
Future<String?> getTitle() => _webView.getTitle();
236292

packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ dev_dependencies:
2929
sdk: flutter
3030
flutter_test:
3131
sdk: flutter
32-
mockito: ^5.1.0
32+
mockito: ^5.3.2
3333
pigeon: ^3.0.3
Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
// Mocks generated by Mockito 5.2.0 from annotations
1+
// Mocks generated by Mockito 5.3.2 from annotations
22
// in webview_flutter_wkwebview/example/ios/.symlinks/plugins/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart.
33
// Do not manually edit this file.
44

5+
// ignore_for_file: no_leading_underscores_for_library_prefixes
56
import 'package:mockito/mockito.dart' as _i1;
67
import 'package:webview_flutter_wkwebview/src/common/web_kit.pigeon.dart'
78
as _i3;
@@ -17,6 +18,7 @@ import '../common/test_web_kit.pigeon.dart' as _i2;
1718
// ignore_for_file: prefer_const_constructors
1819
// ignore_for_file: unnecessary_parenthesis
1920
// ignore_for_file: camel_case_types
21+
// ignore_for_file: subtype_of_sealed_class
2022

2123
/// A class which mocks [TestNSObjectHostApi].
2224
///
@@ -28,21 +30,47 @@ class MockTestNSObjectHostApi extends _i1.Mock
2830
}
2931

3032
@override
31-
void dispose(int? identifier) =>
32-
super.noSuchMethod(Invocation.method(#dispose, [identifier]),
33-
returnValueForMissingStub: null);
33+
void dispose(int? identifier) => super.noSuchMethod(
34+
Invocation.method(
35+
#dispose,
36+
[identifier],
37+
),
38+
returnValueForMissingStub: null,
39+
);
3440
@override
35-
void addObserver(int? identifier, int? observerIdentifier, String? keyPath,
36-
List<_i3.NSKeyValueObservingOptionsEnumData?>? options) =>
41+
void addObserver(
42+
int? identifier,
43+
int? observerIdentifier,
44+
String? keyPath,
45+
List<_i3.NSKeyValueObservingOptionsEnumData?>? options,
46+
) =>
3747
super.noSuchMethod(
38-
Invocation.method(
39-
#addObserver, [identifier, observerIdentifier, keyPath, options]),
40-
returnValueForMissingStub: null);
48+
Invocation.method(
49+
#addObserver,
50+
[
51+
identifier,
52+
observerIdentifier,
53+
keyPath,
54+
options,
55+
],
56+
),
57+
returnValueForMissingStub: null,
58+
);
4159
@override
4260
void removeObserver(
43-
int? identifier, int? observerIdentifier, String? keyPath) =>
61+
int? identifier,
62+
int? observerIdentifier,
63+
String? keyPath,
64+
) =>
4465
super.noSuchMethod(
45-
Invocation.method(
46-
#removeObserver, [identifier, observerIdentifier, keyPath]),
47-
returnValueForMissingStub: null);
66+
Invocation.method(
67+
#removeObserver,
68+
[
69+
identifier,
70+
observerIdentifier,
71+
keyPath,
72+
],
73+
),
74+
returnValueForMissingStub: null,
75+
);
4876
}

0 commit comments

Comments
 (0)