implemented WKDownloadDelegate iOS protocol for iOS 14.5

This commit is contained in:
Lorenzo Pichilli 2022-04-23 17:39:39 +02:00
parent 9e6feccbf6
commit 8315b811a8
4 changed files with 121 additions and 38 deletions

View File

@ -25,6 +25,7 @@ public class NavigationAction {
navigationActionMap.put("navigationType", null);
navigationActionMap.put("sourceFrame", null);
navigationActionMap.put("targetFrame", null);
navigationActionMap.put("shouldPerformDownload", null);
return navigationActionMap;
}

View File

@ -9,7 +9,10 @@ import Flutter
import Foundation
import WebKit
public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, UIGestureRecognizerDelegate, PullToRefreshDelegate {
public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
WKNavigationDelegate, WKScriptMessageHandler, UIGestureRecognizerDelegate,
WKDownloadDelegate,
PullToRefreshDelegate {
var windowId: Int64?
var windowCreated = false
@ -1517,11 +1520,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
var action = response["action"] as? Int
action = action != nil ? action : 0;
switch action {
case 1:
decisionHandler(.grant)
break
default:
decisionHandler(.deny)
case 1:
decisionHandler(.grant)
break
case 2:
decisionHandler(.prompt)
break
default:
decisionHandler(.deny)
}
return;
}
@ -1555,11 +1561,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
var action = response["action"] as? Int
action = action != nil ? action : 0;
switch action {
case 1:
decisionHandler(.grant)
break
default:
decisionHandler(.deny)
case 1:
decisionHandler(.grant)
break
case 2:
decisionHandler(.prompt)
break
default:
decisionHandler(.deny)
}
return;
}
@ -1578,6 +1587,39 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
})
}
@available(iOS 14.5, *)
public func download(_ download: WKDownload, decideDestinationUsing response: URLResponse, suggestedFilename: String, completionHandler: @escaping (URL?) -> Void) {
if let url = response.url, let useOnDownloadStart = settings?.useOnDownloadStart, useOnDownloadStart {
let downloadStartRequest = DownloadStartRequest(url: url.absoluteString,
userAgent: nil,
contentDisposition: nil,
mimeType: response.mimeType,
contentLength: response.expectedContentLength,
suggestedFilename: suggestedFilename,
textEncodingName: response.textEncodingName)
onDownloadStartRequest(request: downloadStartRequest)
}
download.delegate = nil
// cancel the download
completionHandler(nil)
}
@available(iOS 14.5, *)
public func webView(_ webView: WKWebView, navigationResponse: WKNavigationResponse, didBecome download: WKDownload) {
let response = navigationResponse.response
if let url = response.url, let useOnDownloadStart = settings?.useOnDownloadStart, useOnDownloadStart {
let downloadStartRequest = DownloadStartRequest(url: url.absoluteString,
userAgent: nil,
contentDisposition: nil,
mimeType: response.mimeType,
contentLength: response.expectedContentLength,
suggestedFilename: response.suggestedFilename,
textEncodingName: response.textEncodingName)
onDownloadStartRequest(request: downloadStartRequest)
}
download.delegate = nil
}
public func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
@ -1587,6 +1629,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
return
}
if #available(iOS 14.5, *), navigationAction.request.url!.absoluteString.hasSuffix(".dat") {
decisionHandler(.download)
return
}
if navigationAction.request.url != nil {
if let useShouldOverrideUrlLoading = settings?.useShouldOverrideUrlLoading, useShouldOverrideUrlLoading {
@ -1605,7 +1652,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
if let r = result {
response = r as! [String: Any]
let action = response["action"] as? Int
let navigationActionPolicy = WKNavigationActionPolicy.init(rawValue: action ?? WKNavigationActionPolicy.cancel.rawValue) ??
let navigationActionPolicy = WKNavigationActionPolicy
.init(rawValue: action ?? WKNavigationActionPolicy.cancel.rawValue) ??
WKNavigationActionPolicy.cancel
decisionHandler(navigationActionPolicy)
return;
@ -1647,15 +1695,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
var response: [String: Any]
if let r = result {
response = r as! [String: Any]
var action = response["action"] as? Int
action = action != nil ? action : 0;
switch action {
case 1:
decisionHandler(.allow)
break
default:
decisionHandler(.cancel)
}
let action = response["action"] as? Int
let navigationActionPolicy = WKNavigationResponsePolicy
.init(rawValue: action ?? WKNavigationResponsePolicy.cancel.rawValue) ??
WKNavigationResponsePolicy.cancel
decisionHandler(navigationActionPolicy)
return;
}
decisionHandler(.allow)
@ -1664,21 +1708,26 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
}
if let useOnDownloadStart = settings?.useOnDownloadStart, useOnDownloadStart {
let mimeType = navigationResponse.response.mimeType
if let url = navigationResponse.response.url, navigationResponse.isForMainFrame {
if url.scheme != "file", mimeType != nil, !mimeType!.starts(with: "text/") {
let downloadStartRequest = DownloadStartRequest(url: url.absoluteString,
userAgent: nil,
contentDisposition: nil,
mimeType: mimeType,
contentLength: navigationResponse.response.expectedContentLength,
suggestedFilename: navigationResponse.response.suggestedFilename,
textEncodingName: navigationResponse.response.textEncodingName)
onDownloadStartRequest(request: downloadStartRequest)
if useOnNavigationResponse == nil || !useOnNavigationResponse! {
decisionHandler(.cancel)
if #available(iOS 14.5, *), !navigationResponse.canShowMIMEType {
decisionHandler(.download)
return
} else {
let mimeType = navigationResponse.response.mimeType
if let url = navigationResponse.response.url, navigationResponse.isForMainFrame {
if url.scheme != "file", mimeType != nil, !mimeType!.starts(with: "text/") {
let downloadStartRequest = DownloadStartRequest(url: url.absoluteString,
userAgent: nil,
contentDisposition: nil,
mimeType: mimeType,
contentLength: navigationResponse.response.expectedContentLength,
suggestedFilename: navigationResponse.response.suggestedFilename,
textEncodingName: navigationResponse.response.textEncodingName)
onDownloadStartRequest(request: downloadStartRequest)
if useOnNavigationResponse == nil || !useOnNavigationResponse! {
decisionHandler(.cancel)
}
return
}
return
}
}
}

View File

@ -10,6 +10,10 @@ import WebKit
extension WKNavigationAction {
public func toMap () -> [String:Any?] {
var shouldPerformDownload: Bool? = nil
if #available(iOS 14.5, *) {
shouldPerformDownload = self.shouldPerformDownload
}
return [
"request": request.toMap(),
"isForMainFrame": targetFrame?.isMainFrame ?? false,
@ -17,7 +21,8 @@ extension WKNavigationAction {
"isRedirect": nil,
"navigationType": navigationType.rawValue,
"sourceFrame": sourceFrame.toMap(),
"targetFrame": targetFrame?.toMap()
"targetFrame": targetFrame?.toMap(),
"shouldPerformDownload": shouldPerformDownload
]
}
}

View File

@ -4717,6 +4717,11 @@ class PermissionResponseAction {
///Grants origin the permission to access the given resources.
static const GRANT = const PermissionResponseAction._internal(1);
///Prompt the user for permission for the requested resource.
///
///**NOTE**: available only on iOS 15.0+. It will fallback to [DENY].
static const PROMPT = const PermissionResponseAction._internal(2);
bool operator ==(value) => value == _value;
@override
@ -4875,6 +4880,9 @@ class PermissionRequest {
Uri origin;
///List of resources the web content wants to access.
///
///**NOTE for iOS**: this list will have only 1 element and will be used by the [PermissionResponse.action]
///as the resource to consider when applying the corresponding action.
List<PermissionResourceType> resources;
///The frame that initiates the request in the web view.
@ -4925,6 +4933,8 @@ class PermissionRequest {
///Class that represents the response used by the [WebView.onPermissionRequest] event.
class PermissionResponse {
///Resources granted to be accessed by origin.
///
///**NOTE for iOS**: not used. The [action] taken is based on the [PermissionRequest.resources].
List<PermissionResourceType> resources;
///Indicate the [PermissionResponseAction] to take in response of a permission request.
@ -4993,6 +5003,11 @@ class NavigationActionPolicy {
///Allow the navigation to continue.
static const ALLOW = const NavigationActionPolicy._internal(1);
///Turn the navigation into a download.
///
///**NOTE**: available only on iOS 14.5+. It will fallback to [CANCEL].
static const DOWNLOAD = const NavigationActionPolicy._internal(2);
bool operator ==(value) => value == _value;
@override
@ -5761,6 +5776,11 @@ class NavigationAction {
///**NOTE**: available only on iOS.
FrameInfo? targetFrame;
///A value indicating whether the web content used a download attribute to indicate that this should be downloaded.
///
///**NOTE**: available only on iOS.
bool? shouldPerformDownload;
NavigationAction(
{required this.request,
required this.isForMainFrame,
@ -5773,7 +5793,8 @@ class NavigationAction {
@Deprecated("Use sourceFrame instead") this.iosSourceFrame,
this.sourceFrame,
@Deprecated("Use targetFrame instead") this.iosTargetFrame,
this.targetFrame}) {
this.targetFrame,
this.shouldPerformDownload}) {
// ignore: deprecated_member_use_from_same_package
this.hasGesture = this.hasGesture ?? this.androidHasGesture;
// ignore: deprecated_member_use_from_same_package
@ -5818,7 +5839,8 @@ class NavigationAction {
// ignore: deprecated_member_use_from_same_package
IOSWKFrameInfo.fromMap(map["targetFrame"]?.cast<String, dynamic>()),
targetFrame:
FrameInfo.fromMap(map["targetFrame"]?.cast<String, dynamic>()));
FrameInfo.fromMap(map["targetFrame"]?.cast<String, dynamic>()),
shouldPerformDownload: map["shouldPerformDownload"]);
}
Map<String, dynamic> toMap() {
@ -5847,6 +5869,7 @@ class NavigationAction {
"iosTargetFrame": targetFrame?.toMap() ?? iosTargetFrame?.toMap(),
// ignore: deprecated_member_use_from_same_package
"targetFrame": targetFrame?.toMap() ?? iosTargetFrame?.toMap(),
"shouldPerformDownload": shouldPerformDownload
};
}
@ -8953,6 +8976,11 @@ class NavigationResponseAction {
///Allow the navigation to continue.
static const ALLOW = const NavigationResponseAction._internal(1);
///Turn the navigation into a download.
///
///**NOTE**: available only on iOS 14.5+. It will fallback to [CANCEL].
static const DOWNLOAD = const NavigationResponseAction._internal(2);
bool operator ==(value) => value == _value;
@override