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

Commit cd79ce5

Browse files
committed
fix and test non disposing webview
1 parent ffb36e0 commit cd79ce5

File tree

12 files changed

+120
-32
lines changed

12 files changed

+120
-32
lines changed

packages/webview_flutter/webview_flutter/example/ios/Flutter/AppFrameworkInfo.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121
<key>CFBundleVersion</key>
2222
<string>1.0</string>
2323
<key>MinimumOSVersion</key>
24-
<string>9.0</string>
24+
<string>11.0</string>
2525
</dict>
2626
</plist>

packages/webview_flutter/webview_flutter/example/ios/Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Uncomment this line to define a global platform for your project
2-
# platform :ios, '9.0'
2+
# platform :ios, '11.0'
33

44
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
55
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

packages/webview_flutter/webview_flutter/example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 46;
6+
objectVersion = 54;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -274,7 +274,7 @@
274274
isa = PBXProject;
275275
attributes = {
276276
DefaultBuildSystemTypeForWorkspace = Original;
277-
LastUpgradeCheck = 1030;
277+
LastUpgradeCheck = 1300;
278278
ORGANIZATIONNAME = "The Flutter Authors";
279279
TargetAttributes = {
280280
68BDCAE823C3F7CB00D9C032 = {
@@ -363,10 +363,12 @@
363363
};
364364
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
365365
isa = PBXShellScriptBuildPhase;
366+
alwaysOutOfDate = 1;
366367
buildActionMask = 2147483647;
367368
files = (
368369
);
369370
inputPaths = (
371+
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
370372
);
371373
name = "Thin Binary";
372374
outputPaths = (
@@ -377,6 +379,7 @@
377379
};
378380
9740EEB61CF901F6004384FC /* Run Script */ = {
379381
isa = PBXShellScriptBuildPhase;
382+
alwaysOutOfDate = 1;
380383
buildActionMask = 2147483647;
381384
files = (
382385
);
@@ -552,7 +555,7 @@
552555
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
553556
GCC_WARN_UNUSED_FUNCTION = YES;
554557
GCC_WARN_UNUSED_VARIABLE = YES;
555-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
558+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
556559
MTL_ENABLE_DEBUG_INFO = YES;
557560
ONLY_ACTIVE_ARCH = YES;
558561
SDKROOT = iphoneos;
@@ -602,7 +605,7 @@
602605
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
603606
GCC_WARN_UNUSED_FUNCTION = YES;
604607
GCC_WARN_UNUSED_VARIABLE = YES;
605-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
608+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
606609
MTL_ENABLE_DEBUG_INFO = NO;
607610
SDKROOT = iphoneos;
608611
TARGETED_DEVICE_FAMILY = "1,2";

packages/webview_flutter/webview_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1030"
3+
LastUpgradeVersion = "1300"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

packages/webview_flutter/webview_flutter/example/ios/Runner/Info.plist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,9 @@
4141
</array>
4242
<key>UIViewControllerBasedStatusBarAppearance</key>
4343
<false/>
44+
<key>CADisableMinimumFrameDurationOnPhone</key>
45+
<true/>
46+
<key>UIApplicationSupportsIndirectInputEvents</key>
47+
<true/>
4448
</dict>
4549
</plist>

packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import 'package:integration_test/integration_test.dart';
2121
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
2222
import 'package:webview_flutter_wkwebview/src/common/instance_manager.dart';
2323
import 'package:webview_flutter_wkwebview/src/common/weak_reference_utils.dart';
24+
import 'package:webview_flutter_wkwebview/src/web_kit/web_kit.dart';
2425
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
2526

2627
Future<void> main() async {
@@ -47,7 +48,7 @@ Future<void> main() async {
4748
final String headersUrl = '$prefixUrl/headers';
4849

4950
testWidgets(
50-
'withWeakRefenceTo allows encapsulating class to be garbage collected',
51+
'withWeakReferenceTo allows encapsulating class to be garbage collected',
5152
(WidgetTester tester) async {
5253
final Completer<int> gcCompleter = Completer<int>();
5354
final InstanceManager instanceManager = InstanceManager(
@@ -68,6 +69,40 @@ Future<void> main() async {
6869
expect(gcIdentifier, 0);
6970
}, timeout: const Timeout(Duration(seconds: 10)));
7071

72+
testWidgets(
73+
'WKWebView is released by garbage collection',
74+
(WidgetTester tester) async {
75+
final Completer<void> webViewGCCompleter = Completer<void>();
76+
77+
late final InstanceManager instanceManager;
78+
instanceManager =
79+
InstanceManager(onWeakReferenceRemoved: (int identifier) {
80+
final Copyable instance =
81+
instanceManager.getInstanceWithWeakReference(identifier)!;
82+
if (instance is WKWebView) {
83+
if (!webViewGCCompleter.isCompleted) {
84+
webViewGCCompleter.complete();
85+
}
86+
}
87+
});
88+
89+
// ignore: unused_local_variable
90+
WebKitWebViewController? controller = WebKitWebViewController(
91+
WebKitWebViewControllerCreationParams(instanceManager: instanceManager),
92+
);
93+
controller = null;
94+
95+
// Force garbage collection.
96+
await IntegrationTestWidgetsFlutterBinding.instance
97+
.watchPerformance(() async {
98+
await tester.pumpAndSettle();
99+
});
100+
101+
await expectLater(webViewGCCompleter.future, completes);
102+
},
103+
timeout: const Timeout(Duration(seconds: 10)),
104+
);
105+
71106
testWidgets('loadRequest', (WidgetTester tester) async {
72107
final PlatformWebViewController controller = PlatformWebViewController(
73108
const PlatformWebViewControllerCreationParams(),
@@ -113,6 +148,8 @@ Future<void> main() async {
113148
),
114149
);
115150

151+
await tester.pumpAndSettle();
152+
116153
await pageLoads.stream.firstWhere((String url) => url == headersUrl);
117154

118155
final String content = await controller.runJavaScriptReturningResult(
@@ -147,6 +184,8 @@ Future<void> main() async {
147184
'data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+',
148185
);
149186

187+
await tester.pumpAndSettle();
188+
150189
await pageFinished.future;
151190

152191
await controller.runJavaScript('Echo.postMessage("hello");');
@@ -250,6 +289,8 @@ Future<void> main() async {
250289
),
251290
);
252291

292+
await tester.pumpAndSettle();
293+
253294
await pageLoaded.future;
254295

255296
bool isPaused =
@@ -509,6 +550,8 @@ Future<void> main() async {
509550
),
510551
);
511552

553+
await tester.pumpAndSettle();
554+
512555
await pageLoaded.future;
513556

514557
// On at least iOS, it does not appear to be guaranteed that the native
@@ -824,6 +867,7 @@ Future<void> main() async {
824867
)..setOnPageFinished((_) => pageLoaded.complete()));
825868

826869
await controller.runJavaScript('window.open("$primaryUrl", "_blank")');
870+
await tester.pumpAndSettle();
827871
await pageLoaded.future;
828872
final String? currentUrl = await controller.currentUrl();
829873
expect(currentUrl, primaryUrl);

packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 50;
6+
objectVersion = 54;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -379,10 +379,12 @@
379379
/* Begin PBXShellScriptBuildPhase section */
380380
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
381381
isa = PBXShellScriptBuildPhase;
382+
alwaysOutOfDate = 1;
382383
buildActionMask = 2147483647;
383384
files = (
384385
);
385386
inputPaths = (
387+
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
386388
);
387389
name = "Thin Binary";
388390
outputPaths = (
@@ -415,6 +417,7 @@
415417
};
416418
9740EEB61CF901F6004384FC /* Run Script */ = {
417419
isa = PBXShellScriptBuildPhase;
420+
alwaysOutOfDate = 1;
418421
buildActionMask = 2147483647;
419422
files = (
420423
);

packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner/Info.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,7 @@
4343
<false/>
4444
<key>CADisableMinimumFrameDurationOnPhone</key>
4545
<true/>
46+
<key>UIApplicationSupportsIndirectInputEvents</key>
47+
<true/>
4648
</dict>
4749
</plist>

packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_proxy.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'common/instance_manager.dart';
56
import 'foundation/foundation.dart';
67
import 'web_kit/web_kit.dart';
78

@@ -39,10 +40,13 @@ class WebKitProxy {
3940
Map<NSKeyValueChangeKey, Object?> change,
4041
)?
4142
observeValue,
43+
InstanceManager? instanceManager,
4244
}) createWebView;
4345

4446
/// Constructs a [WKWebViewConfiguration].
45-
final WKWebViewConfiguration Function() createWebViewConfiguration;
47+
final WKWebViewConfiguration Function({
48+
InstanceManager? instanceManager,
49+
}) createWebViewConfiguration;
4650

4751
/// Constructs a [WKScriptMessageHandler].
4852
final WKScriptMessageHandler Function({
@@ -72,7 +76,7 @@ class WebKitProxy {
7276
void Function(WKWebView webView)? webViewWebContentProcessDidTerminate,
7377
}) createNavigationDelegate;
7478

75-
/// Contructs a [WKUIDelegate].
79+
/// Constructs a [WKUIDelegate].
7680
final WKUIDelegate Function({
7781
void Function(
7882
WKWebView webView,

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

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ class WebKitWebViewControllerCreationParams
4949
PlaybackMediaTypes.video,
5050
},
5151
this.allowsInlineMediaPlayback = false,
52-
}) : _configuration = webKitProxy.createWebViewConfiguration() {
52+
@visibleForTesting InstanceManager? instanceManager,
53+
}) : _instanceManager = instanceManager ?? NSObject.globalInstanceManager {
54+
_configuration = webKitProxy.createWebViewConfiguration(
55+
instanceManager: _instanceManager,
56+
);
57+
5358
if (mediaTypesRequiringUserAction.isEmpty) {
5459
_configuration.setMediaTypesRequiringUserActionForPlayback(
5560
<WKAudiovisualMediaType>{WKAudiovisualMediaType.none},
@@ -79,13 +84,15 @@ class WebKitWebViewControllerCreationParams
7984
PlaybackMediaTypes.video,
8085
},
8186
bool allowsInlineMediaPlayback = false,
87+
@visibleForTesting InstanceManager? instanceManager,
8288
}) : this(
8389
webKitProxy: webKitProxy,
8490
mediaTypesRequiringUserAction: mediaTypesRequiringUserAction,
8591
allowsInlineMediaPlayback: allowsInlineMediaPlayback,
92+
instanceManager: instanceManager,
8693
);
8794

88-
final WKWebViewConfiguration _configuration;
95+
late final WKWebViewConfiguration _configuration;
8996

9097
/// Media types that require a user gesture to begin playing.
9198
///
@@ -102,6 +109,10 @@ class WebKitWebViewControllerCreationParams
102109
/// native library.
103110
@visibleForTesting
104111
final WebKitProxy webKitProxy;
112+
113+
// Maintains instances used to communicate with the native objects they
114+
// represent.
115+
final InstanceManager _instanceManager;
105116
}
106117

107118
/// An implementation of [PlatformWebViewController] with the WebKit api.
@@ -122,12 +133,12 @@ class WebKitWebViewController extends PlatformWebViewController {
122133
}
123134

124135
/// The WebKit WebView being controlled.
125-
late final WKWebView _webView = withWeakRefenceTo(this, (
126-
WeakReference<WebKitWebViewController> weakReference,
127-
) {
128-
return _webKitParams.webKitProxy.createWebView(
129-
_webKitParams._configuration,
130-
observeValue: (
136+
late final WKWebView _webView = _webKitParams.webKitProxy.createWebView(
137+
_webKitParams._configuration,
138+
observeValue: withWeakRefenceTo(this, (
139+
WeakReference<WebKitWebViewController> weakReference,
140+
) {
141+
return (
131142
String keyPath,
132143
NSObject object,
133144
Map<NSKeyValueChangeKey, Object?> change,
@@ -139,9 +150,10 @@ class WebKitWebViewController extends PlatformWebViewController {
139150
change[NSKeyValueChangeKey.newValue]! as double;
140151
progressCallback((progress * 100).round());
141152
}
142-
},
143-
);
144-
});
153+
};
154+
}),
155+
instanceManager: _webKitParams._instanceManager,
156+
);
145157

146158
final Map<String, WebKitJavaScriptChannelParams> _javaScriptChannelParams =
147159
<String, WebKitJavaScriptChannelParams>{};

0 commit comments

Comments
 (0)