Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.24.4

* Updates plugin to prevent message calls when application will terminate.

## 3.24.3

* Adds support to get failing url from DNS errors on iOS 26+.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import XCTest

@testable import webview_flutter_wkwebview

#if os(iOS)
import Flutter
import UIKit
#endif

class WebViewFlutterPluginTests: XCTestCase {
#if os(iOS)
func testInstanceManagerIsDeallocatedInApplicationWillTerminate() {
let plugin = WebViewFlutterPlugin(binaryMessenger: TestBinaryMessenger())
plugin.proxyApiRegistrar!.setUp()

let view = UIView()
_ = plugin.proxyApiRegistrar!.instanceManager.addHostCreatedInstance(view)

// Attaches an associated object to the InstanceManager to listen for when it is deallocated.
var finalizer: TestFinalizer? = TestFinalizer()

let key = malloc(1)!
defer {
free(key)
}
objc_setAssociatedObject(
plugin.proxyApiRegistrar!.instanceManager, key, finalizer, .OBJC_ASSOCIATION_RETAIN)
let expectation = self.expectation(description: "Wait for InstanceManager to be deallocated.")
TestFinalizer.onDeinit = {
expectation.fulfill()
}

// Ensure method is from `FlutterApplicationLifeCycleDelegate`.
(plugin as FlutterApplicationLifeCycleDelegate).applicationWillTerminate!(
UIApplication.shared)
XCTAssertNil(plugin.proxyApiRegistrar)

finalizer = nil
waitForExpectations(timeout: 5.0)
}
#endif
}

class TestFinalizer {
static var onDeinit: (() -> Void)?

deinit {
Self.onDeinit?()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,31 @@ public class WebViewFlutterPlugin: NSObject, FlutterPlugin {
let plugin = WebViewFlutterPlugin(binaryMessenger: binaryMessenger)

let viewFactory = FlutterViewFactory(instanceManager: plugin.proxyApiRegistrar!.instanceManager)

#if os(iOS)
registrar.addApplicationDelegate(plugin)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why application delegate rather than the newer scene delegate that replaces it?

#endif

registrar.register(viewFactory, withId: "plugins.flutter.io/webview")
registrar.publish(plugin)
}

public func detachFromEngine(for registrar: FlutterPluginRegistrar) {
proxyApiRegistrar!.ignoreCallsToDart = true
proxyApiRegistrar!.tearDown()
tearDownProxyAPIRegistrar()
}

private func tearDownProxyAPIRegistrar() {
proxyApiRegistrar?.ignoreCallsToDart = true
proxyApiRegistrar?.tearDown()
try? proxyApiRegistrar?.instanceManager.removeAllObjects()
proxyApiRegistrar = nil
}
Comment on lines +44 to 49
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The proxyApiRegistrar is an optional that is set to nil at the end of this method. Since tearDownProxyAPIRegistrar is now called from both detachFromEngine and applicationWillTerminate, it is possible for it to be called twice during application shutdown (for example, if the engine is detached and then the application terminates). The force-unwrapping of proxyApiRegistrar will cause a crash on the second call. It should be handled safely using a guard or optional chaining.

  private func tearDownProxyAPIRegistrar() {
    guard let registrar = proxyApiRegistrar else {
      return
    }
    registrar.ignoreCallsToDart = true
    registrar.tearDown()
    proxyApiRegistrar = nil
  }

}

#if os(iOS)
extension WebViewFlutterPlugin: FlutterApplicationLifeCycleDelegate {
public func applicationWillTerminate(_ application: UIApplication) {
tearDownProxyAPIRegistrar()
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 60;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -42,6 +42,8 @@
8F1488FE2D2DE27000191744 /* HTTPCookieProxyAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F1488C82D2DE27000191744 /* HTTPCookieProxyAPITests.swift */; };
8F1488FF2D2DE27000191744 /* NavigationActionProxyAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F1488CB2D2DE27000191744 /* NavigationActionProxyAPITests.swift */; };
8F1489012D2DE91C00191744 /* AuthenticationChallengeResponseProxyAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F1489002D2DE91C00191744 /* AuthenticationChallengeResponseProxyAPITests.swift */; };
8F63D06B2F8812E400EC5076 /* WebViewFlutterPluginTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F63D06A2F8812E400EC5076 /* WebViewFlutterPluginTests.swift */; };
8F63D06C2F8812E400EC5076 /* PlatformViewImplTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F63D0692F8812E400EC5076 /* PlatformViewImplTests.swift */; };
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The project file references PlatformViewImplTests.swift (also seen on lines 133, 181, and 508), but this file is not included in the pull request. This will cause a build failure in the example app's test target as the compiler will be unable to find the file.

8FEC64852DA2C6DC00C48569 /* GetTrustResultResponseProxyAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FEC64812DA2C6DC00C48569 /* GetTrustResultResponseProxyAPITests.swift */; };
8FEC64862DA2C6DC00C48569 /* WebpagePreferencesProxyAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FEC64842DA2C6DC00C48569 /* WebpagePreferencesProxyAPITests.swift */; };
8FEC64872DA2C6DC00C48569 /* SecCertificateProxyAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FEC64822DA2C6DC00C48569 /* SecCertificateProxyAPITests.swift */; };
Expand Down Expand Up @@ -128,6 +130,8 @@
8F1488E02D2DE27000191744 /* WebViewConfigurationProxyAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WebViewConfigurationProxyAPITests.swift; path = ../../darwin/Tests/WebViewConfigurationProxyAPITests.swift; sourceTree = SOURCE_ROOT; };
8F1488E12D2DE27000191744 /* WebViewProxyAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WebViewProxyAPITests.swift; path = ../../darwin/Tests/WebViewProxyAPITests.swift; sourceTree = SOURCE_ROOT; };
8F1489002D2DE91C00191744 /* AuthenticationChallengeResponseProxyAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AuthenticationChallengeResponseProxyAPITests.swift; path = ../../darwin/Tests/AuthenticationChallengeResponseProxyAPITests.swift; sourceTree = SOURCE_ROOT; };
8F63D0692F8812E400EC5076 /* PlatformViewImplTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PlatformViewImplTests.swift; path = ../../darwin/Tests/PlatformViewImplTests.swift; sourceTree = SOURCE_ROOT; };
8F63D06A2F8812E400EC5076 /* WebViewFlutterPluginTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WebViewFlutterPluginTests.swift; path = ../../darwin/Tests/WebViewFlutterPluginTests.swift; sourceTree = SOURCE_ROOT; };
8FEC64812DA2C6DC00C48569 /* GetTrustResultResponseProxyAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GetTrustResultResponseProxyAPITests.swift; path = ../../darwin/Tests/GetTrustResultResponseProxyAPITests.swift; sourceTree = SOURCE_ROOT; };
8FEC64822DA2C6DC00C48569 /* SecCertificateProxyAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SecCertificateProxyAPITests.swift; path = ../../darwin/Tests/SecCertificateProxyAPITests.swift; sourceTree = SOURCE_ROOT; };
8FEC64832DA2C6DC00C48569 /* SecTrustProxyAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SecTrustProxyAPITests.swift; path = ../../darwin/Tests/SecTrustProxyAPITests.swift; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -174,6 +178,8 @@
68BDCAEA23C3F7CB00D9C032 /* RunnerTests */ = {
isa = PBXGroup;
children = (
8F63D0692F8812E400EC5076 /* PlatformViewImplTests.swift */,
8F63D06A2F8812E400EC5076 /* WebViewFlutterPluginTests.swift */,
8F0E23512EEB5D6B002AB342 /* ColorProxyAPITests.swift */,
8F0EDFD22E1F4967001938E6 /* ProxyAPIRegistrarTests.swift */,
8FEC64812DA2C6DC00C48569 /* GetTrustResultResponseProxyAPITests.swift */,
Expand Down Expand Up @@ -498,6 +504,8 @@
8F1488F42D2DE27000191744 /* URLCredentialProxyAPITests.swift in Sources */,
8F1488F52D2DE27000191744 /* URLAuthenticationChallengeProxyAPITests.swift in Sources */,
8F1488F62D2DE27000191744 /* NavigationDelegateProxyAPITests.swift in Sources */,
8F63D06B2F8812E400EC5076 /* WebViewFlutterPluginTests.swift in Sources */,
8F63D06C2F8812E400EC5076 /* PlatformViewImplTests.swift in Sources */,
8F1488F72D2DE27000191744 /* UIDelegateProxyAPITests.swift in Sources */,
8F1488F82D2DE27000191744 /* ScrollViewDelegateProxyAPITests.swift in Sources */,
8F1488FA2D2DE27000191744 /* FWFWebViewFlutterWKWebViewExternalAPITests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview
description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control.
repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
version: 3.24.3
version: 3.24.4

environment:
sdk: ^3.9.0
Expand Down
Loading