Skip to content

Commit a03b900

Browse files
[webview_flutter_wkwebview] Fixes inspectable compile-time error and crash from equal NSURLs (#4340)
Fixes flutter/flutter#128422 by using pointer equality in the `NSMapTable`. From my understanding and testing it seems that the default mode for [NSMapTable](https://developer.apple.com/documentation/foundation/nsmaptable?language=objc) is to copy objects that implement `NSCopyable`. The only class we wrap that does seems to implement `NSCopyable` is `NSURL` so this class eventually led to a race condition where adding an `NSURL` that was equivalent to an already added one would replace the original. Note that we should probably now add an error when adding an already present instance. However, a clear method needs to be added to the `InstanceManager` first so that hot reload will continue working. This is the current solution on Android. Fixes flutter/flutter#129587 by adding a compile-time check around the use of `WKWebView.inspectable`. Solution used from: https://stackoverflow.com/questions/76216183/how-to-debug-wkwebview-in-ios-16-4-1-using-xcode-14-2
1 parent cdae854 commit a03b900

File tree

6 files changed

+37
-5
lines changed

6 files changed

+37
-5
lines changed

packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 3.6.1
2+
3+
* Fixes bug where a native `NSURL` could be removed from an `InstanceManager` if it is equal to an
4+
already present `NSURL`.
5+
* Fixes compile-time error from using `WKWebView.inspectable` on unsupported Xcode versions.
6+
17
## 3.6.0
28

39
* Adds support to enable debugging of web contents on the latest versions of WebKit. See

packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFInstanceManagerTests.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,20 @@ - (void)testDeallocCallbackIsIgnoredIfNull {
5252
// Tests that this doesn't cause a EXC_BAD_ACCESS crash.
5353
[instanceManager removeInstanceWithIdentifier:0];
5454
}
55+
56+
- (void)testObjectsAreStoredWithPointerHashcode {
57+
FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init];
58+
59+
NSURL *url1 = [NSURL URLWithString:@"https://www.flutter.dev"];
60+
NSURL *url2 = [NSURL URLWithString:@"https://www.flutter.dev"];
61+
62+
// Ensure urls are considered equal.
63+
XCTAssertTrue([url1 isEqual:url2]);
64+
65+
[instanceManager addHostCreatedInstance:url1];
66+
[instanceManager addHostCreatedInstance:url2];
67+
68+
XCTAssertNotEqual([instanceManager identifierWithStrongReferenceForInstance:url1],
69+
[instanceManager identifierWithStrongReferenceForInstance:url2]);
70+
}
5571
@end

packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FWFWebViewHostApiTests.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ - (void)testContentInsetsSumAlwaysZeroAfterSetFrame {
465465
XCTAssertTrue(CGRectEqualToRect(webView.frame, CGRectMake(0, 0, 300, 100)));
466466
}
467467

468-
- (void)testSetInspectable API_AVAILABLE(ios(16.4), macos(13.3), tvos(16.4)) {
468+
- (void)testSetInspectable API_AVAILABLE(ios(16.4), macos(13.3)) {
469469
FWFWebView *mockWebView = OCMClassMock([FWFWebView class]);
470470

471471
FWFInstanceManager *instanceManager = [[FWFInstanceManager alloc] init];

packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFInstanceManager.m

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,17 @@ - (instancetype)init {
6767
_deallocCallback = _deallocCallback ? _deallocCallback : ^(long identifier) {
6868
};
6969
_lockQueue = dispatch_queue_create("FWFInstanceManager", DISPATCH_QUEUE_SERIAL);
70-
_identifiers = [NSMapTable weakToStrongObjectsMapTable];
71-
_weakInstances = [NSMapTable strongToWeakObjectsMapTable];
72-
_strongInstances = [NSMapTable strongToStrongObjectsMapTable];
70+
// Pointer equality is used to prevent collisions of objects that override the `isEqualTo:`
71+
// method.
72+
_identifiers =
73+
[NSMapTable mapTableWithKeyOptions:NSMapTableWeakMemory | NSMapTableObjectPointerPersonality
74+
valueOptions:NSMapTableStrongMemory];
75+
_weakInstances = [NSMapTable
76+
mapTableWithKeyOptions:NSMapTableStrongMemory
77+
valueOptions:NSMapTableWeakMemory | NSMapTableObjectPointerPersonality];
78+
_strongInstances = [NSMapTable
79+
mapTableWithKeyOptions:NSMapTableStrongMemory
80+
valueOptions:NSMapTableStrongMemory | NSMapTableObjectPointerPersonality];
7381
_nextIdentifier = FWFMinHostCreatedIdentifier;
7482
}
7583
return self;

packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FWFWebViewHostApi.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,9 @@ - (void)setInspectableForWebViewWithIdentifier:(NSNumber *)identifier
201201
inspectable:(NSNumber *)inspectable
202202
error:(FlutterError *_Nullable *_Nonnull)error {
203203
if (@available(macOS 13.3, iOS 16.4, tvOS 16.4, *)) {
204+
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130300 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 160400
204205
[[self webViewForIdentifier:identifier] setInspectable:inspectable.boolValue];
206+
#endif
205207
} else {
206208
*error = [FlutterError errorWithCode:@"FWFUnsupportedVersionError"
207209
message:@"setInspectable is only supported on versions 16.4+."

packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: webview_flutter_wkwebview
22
description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control.
33
repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
5-
version: 3.6.0
5+
version: 3.6.1
66

77
environment:
88
sdk: ">=2.18.0 <4.0.0"

0 commit comments

Comments
 (0)