Fixed iOS and macOS InAppWebView memory leaks

This commit is contained in:
Lorenzo Pichilli 2023-11-11 19:08:14 +01:00
parent be570be6b0
commit 18c3c1fa51
3 changed files with 29 additions and 29 deletions

View File

@ -12,6 +12,7 @@
- Merged "Android - Fix context menu position for pages with horizontal scroll" [#1504](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1504) (thanks to [lrorpilla](https://github.com/lrorpilla)) - Merged "Android - Fix context menu position for pages with horizontal scroll" [#1504](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1504) (thanks to [lrorpilla](https://github.com/lrorpilla))
- Fixed "iOS about:blank popup not loading page" [#1500](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1500) - Fixed "iOS about:blank popup not loading page" [#1500](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1500)
- Fixed "iOS macOS - This method should not be called on the main thread as it may lead to UI unresponsiveness" [#1678](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1678) - Fixed "iOS macOS - This method should not be called on the main thread as it may lead to UI unresponsiveness" [#1678](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1678)
- Fixed iOS and macOS InAppWebView memory leaks
## 6.0.0-beta.25 ## 6.0.0-beta.25

View File

@ -2256,12 +2256,12 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
} }
return true return true
} }
callback.defaultBehaviour = { (response: JsAlertResponse?) in callback.defaultBehaviour = { [weak self] (response: JsAlertResponse?) in
if !completionHandlerCalled { if !completionHandlerCalled {
completionHandlerCalled = true completionHandlerCalled = true
let responseMessage = response?.message let responseMessage = response?.message
let confirmButtonTitle = response?.confirmButtonTitle let confirmButtonTitle = response?.confirmButtonTitle
self.createAlertDialog(message: message, responseMessage: responseMessage, self?.createAlertDialog(message: message, responseMessage: responseMessage,
confirmButtonTitle: confirmButtonTitle, completionHandler: completionHandler) confirmButtonTitle: confirmButtonTitle, completionHandler: completionHandler)
} }
} }
@ -2325,13 +2325,13 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
} }
return true return true
} }
callback.defaultBehaviour = { (response: JsConfirmResponse?) in callback.defaultBehaviour = { [weak self] (response: JsConfirmResponse?) in
if !completionHandlerCalled { if !completionHandlerCalled {
completionHandlerCalled = true completionHandlerCalled = true
let responseMessage = response?.message let responseMessage = response?.message
let confirmButtonTitle = response?.confirmButtonTitle let confirmButtonTitle = response?.confirmButtonTitle
let cancelButtonTitle = response?.cancelButtonTitle let cancelButtonTitle = response?.cancelButtonTitle
self.createConfirmDialog(message: message, responseMessage: responseMessage, confirmButtonTitle: confirmButtonTitle, cancelButtonTitle: cancelButtonTitle, completionHandler: completionHandler) self?.createConfirmDialog(message: message, responseMessage: responseMessage, confirmButtonTitle: confirmButtonTitle, cancelButtonTitle: cancelButtonTitle, completionHandler: completionHandler)
} }
} }
callback.error = { (code: String, message: String?, details: Any?) in callback.error = { (code: String, message: String?, details: Any?) in
@ -2406,14 +2406,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
} }
return true return true
} }
callback.defaultBehaviour = { (response: JsPromptResponse?) in callback.defaultBehaviour = { [weak self] (response: JsPromptResponse?) in
if !completionHandlerCalled { if !completionHandlerCalled {
completionHandlerCalled = true completionHandlerCalled = true
let responseMessage = response?.message let responseMessage = response?.message
let confirmButtonTitle = response?.confirmButtonTitle let confirmButtonTitle = response?.confirmButtonTitle
let cancelButtonTitle = response?.cancelButtonTitle let cancelButtonTitle = response?.cancelButtonTitle
let value = response?.value let value = response?.value
self.createPromptDialog(message: message, defaultValue: defaultValue, responseMessage: responseMessage, confirmButtonTitle: confirmButtonTitle, self?.createPromptDialog(message: message, defaultValue: defaultValue, responseMessage: responseMessage, confirmButtonTitle: confirmButtonTitle,
cancelButtonTitle: cancelButtonTitle, value: value, completionHandler: completionHandler) cancelButtonTitle: cancelButtonTitle, value: value, completionHandler: completionHandler)
} }
} }
@ -2520,11 +2520,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
callback.nonNullSuccess = { (handledByClient: Bool) in callback.nonNullSuccess = { (handledByClient: Bool) in
return !handledByClient return !handledByClient
} }
callback.defaultBehaviour = { (handledByClient: Bool?) in callback.defaultBehaviour = { [weak self] (handledByClient: Bool?) in
if inAppWebViewManager?.windowWebViews[windowId] != nil { if inAppWebViewManager?.windowWebViews[windowId] != nil {
inAppWebViewManager?.windowWebViews.removeValue(forKey: windowId) inAppWebViewManager?.windowWebViews.removeValue(forKey: windowId)
} }
self.loadUrl(urlRequest: navigationAction.request, allowingReadAccessTo: nil) self?.loadUrl(urlRequest: navigationAction.request, allowingReadAccessTo: nil)
} }
callback.error = { [weak callback] (code: String, message: String?, details: Any?) in callback.error = { [weak callback] (code: String, message: String?, details: Any?) in
print(code + ", " + (message ?? "")) print(code + ", " + (message ?? ""))
@ -2807,8 +2807,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
callback.nonNullSuccess = { (handledByClient: Bool) in callback.nonNullSuccess = { (handledByClient: Bool) in
return !handledByClient return !handledByClient
} }
callback.defaultBehaviour = { (handledByClient: Bool?) in callback.defaultBehaviour = { [weak self] (handledByClient: Bool?) in
if let printJob = self.plugin?.printJobManager?.jobs[printJobId] { if let printJob = self?.plugin?.printJobManager?.jobs[printJobId] {
printJob?.disposeNoDismiss() printJob?.disposeNoDismiss()
} }
} }
@ -2831,24 +2831,24 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
} }
let callback = WebViewChannelDelegate.CallJsHandlerCallback() let callback = WebViewChannelDelegate.CallJsHandlerCallback()
callback.defaultBehaviour = { (response: Any?) in callback.defaultBehaviour = { [weak self] (response: Any?) in
var json = "null" var json = "null"
if let r = response as? String { if let r = response as? String {
json = r json = r
} }
self.evaluateJavaScript(""" self?.evaluateJavaScript("""
if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].resolve(\(json)); window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].resolve(\(json));
delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)]; delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)];
} }
""", completionHandler: nil) """, completionHandler: nil)
} }
callback.error = { (code: String, message: String?, details: Any?) in callback.error = { [weak self] (code: String, message: String?, details: Any?) in
let errorMessage = code + (message != nil ? ", " + (message ?? "") : "") let errorMessage = code + (message != nil ? ", " + (message ?? "") : "")
print(errorMessage) print(errorMessage)
self.evaluateJavaScript(""" self?.evaluateJavaScript("""
if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].reject(new Error('\(errorMessage.replacingOccurrences(of: "\'", with: "\\'"))')); window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].reject(new Error('\(errorMessage.replacingOccurrences(of: "\'", with: "\\'"))'));
delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)]; delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)];

View File

@ -1653,12 +1653,12 @@ public class InAppWebView: WKWebView, WKUIDelegate,
} }
return true return true
} }
callback.defaultBehaviour = { (response: JsAlertResponse?) in callback.defaultBehaviour = { [weak self] (response: JsAlertResponse?) in
if !completionHandlerCalled { if !completionHandlerCalled {
completionHandlerCalled = true completionHandlerCalled = true
let responseMessage = response?.message let responseMessage = response?.message
let confirmButtonTitle = response?.confirmButtonTitle let confirmButtonTitle = response?.confirmButtonTitle
self.createAlertDialog(message: message, responseMessage: responseMessage, self?.createAlertDialog(message: message, responseMessage: responseMessage,
confirmButtonTitle: confirmButtonTitle, completionHandler: completionHandler) confirmButtonTitle: confirmButtonTitle, completionHandler: completionHandler)
} }
} }
@ -1714,13 +1714,13 @@ public class InAppWebView: WKWebView, WKUIDelegate,
} }
return true return true
} }
callback.defaultBehaviour = { (response: JsConfirmResponse?) in callback.defaultBehaviour = { [weak self] (response: JsConfirmResponse?) in
if !completionHandlerCalled { if !completionHandlerCalled {
completionHandlerCalled = true completionHandlerCalled = true
let responseMessage = response?.message let responseMessage = response?.message
let confirmButtonTitle = response?.confirmButtonTitle let confirmButtonTitle = response?.confirmButtonTitle
let cancelButtonTitle = response?.cancelButtonTitle let cancelButtonTitle = response?.cancelButtonTitle
self.createConfirmDialog(message: message, responseMessage: responseMessage, confirmButtonTitle: confirmButtonTitle, cancelButtonTitle: cancelButtonTitle, completionHandler: completionHandler) self?.createConfirmDialog(message: message, responseMessage: responseMessage, confirmButtonTitle: confirmButtonTitle, cancelButtonTitle: cancelButtonTitle, completionHandler: completionHandler)
} }
} }
callback.error = { (code: String, message: String?, details: Any?) in callback.error = { (code: String, message: String?, details: Any?) in
@ -1780,14 +1780,14 @@ public class InAppWebView: WKWebView, WKUIDelegate,
} }
return true return true
} }
callback.defaultBehaviour = { (response: JsPromptResponse?) in callback.defaultBehaviour = { [weak self] (response: JsPromptResponse?) in
if !completionHandlerCalled { if !completionHandlerCalled {
completionHandlerCalled = true completionHandlerCalled = true
let responseMessage = response?.message let responseMessage = response?.message
let confirmButtonTitle = response?.confirmButtonTitle let confirmButtonTitle = response?.confirmButtonTitle
let cancelButtonTitle = response?.cancelButtonTitle let cancelButtonTitle = response?.cancelButtonTitle
let value = response?.value let value = response?.value
self.createPromptDialog(message: message, defaultValue: defaultValue, responseMessage: responseMessage, confirmButtonTitle: confirmButtonTitle, self?.createPromptDialog(message: message, defaultValue: defaultValue, responseMessage: responseMessage, confirmButtonTitle: confirmButtonTitle,
cancelButtonTitle: cancelButtonTitle, value: value, completionHandler: completionHandler) cancelButtonTitle: cancelButtonTitle, value: value, completionHandler: completionHandler)
} }
} }
@ -1826,7 +1826,6 @@ public class InAppWebView: WKWebView, WKUIDelegate,
) )
inAppWebViewManager?.windowWebViews[windowId] = webViewTransport inAppWebViewManager?.windowWebViews[windowId] = webViewTransport
windowWebView.stopLoading()
let createWindowAction = CreateWindowAction(navigationAction: navigationAction, windowId: windowId, windowFeatures: windowFeatures, isDialog: nil) let createWindowAction = CreateWindowAction(navigationAction: navigationAction, windowId: windowId, windowFeatures: windowFeatures, isDialog: nil)
@ -1834,11 +1833,11 @@ public class InAppWebView: WKWebView, WKUIDelegate,
callback.nonNullSuccess = { (handledByClient: Bool) in callback.nonNullSuccess = { (handledByClient: Bool) in
return !handledByClient return !handledByClient
} }
callback.defaultBehaviour = { (handledByClient: Bool?) in callback.defaultBehaviour = { [weak self] (handledByClient: Bool?) in
if inAppWebViewManager?.windowWebViews[windowId] != nil { if inAppWebViewManager?.windowWebViews[windowId] != nil {
inAppWebViewManager?.windowWebViews.removeValue(forKey: windowId) inAppWebViewManager?.windowWebViews.removeValue(forKey: windowId)
} }
self.loadUrl(urlRequest: navigationAction.request, allowingReadAccessTo: nil) self?.loadUrl(urlRequest: navigationAction.request, allowingReadAccessTo: nil)
} }
callback.error = { [weak callback] (code: String, message: String?, details: Any?) in callback.error = { [weak callback] (code: String, message: String?, details: Any?) in
print(code + ", " + (message ?? "")) print(code + ", " + (message ?? ""))
@ -2111,8 +2110,8 @@ public class InAppWebView: WKWebView, WKUIDelegate,
callback.nonNullSuccess = { (handledByClient: Bool) in callback.nonNullSuccess = { (handledByClient: Bool) in
return !handledByClient return !handledByClient
} }
callback.defaultBehaviour = { (handledByClient: Bool?) in callback.defaultBehaviour = { [weak self] (handledByClient: Bool?) in
if let printJob = self.plugin?.printJobManager?.jobs[printJobId] { if let printJob = self?.plugin?.printJobManager?.jobs[printJobId] {
printJob?.disposeNoDismiss() printJob?.disposeNoDismiss()
} }
} }
@ -2135,24 +2134,24 @@ public class InAppWebView: WKWebView, WKUIDelegate,
} }
let callback = WebViewChannelDelegate.CallJsHandlerCallback() let callback = WebViewChannelDelegate.CallJsHandlerCallback()
callback.defaultBehaviour = { (response: Any?) in callback.defaultBehaviour = { [weak self] (response: Any?) in
var json = "null" var json = "null"
if let r = response as? String { if let r = response as? String {
json = r json = r
} }
self.evaluateJavaScript(""" self?.evaluateJavaScript("""
if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].resolve(\(json)); window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].resolve(\(json));
delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)]; delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)];
} }
""", completionHandler: nil) """, completionHandler: nil)
} }
callback.error = { (code: String, message: String?, details: Any?) in callback.error = { [weak self] (code: String, message: String?, details: Any?) in
let errorMessage = code + (message != nil ? ", " + (message ?? "") : "") let errorMessage = code + (message != nil ? ", " + (message ?? "") : "")
print(errorMessage) print(errorMessage)
self.evaluateJavaScript(""" self?.evaluateJavaScript("""
if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) {
window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].reject(new Error('\(errorMessage.replacingOccurrences(of: "\'", with: "\\'"))')); window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)].reject(new Error('\(errorMessage.replacingOccurrences(of: "\'", with: "\\'"))'));
delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)]; delete window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)];