diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/URLRequest.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/URLRequest.java index dd156a5d..986a96cc 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/URLRequest.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/URLRequest.java @@ -53,6 +53,8 @@ public class URLRequest { urlRequestMap.put("networkServiceType", null); urlRequestMap.put("timeoutInterval", null); urlRequestMap.put("mainDocumentURL", null); + urlRequestMap.put("assumesHTTP3Capable", null); + urlRequestMap.put("attribution", null); return urlRequestMap; } diff --git a/ios/Classes/Types/URLRequest.swift b/ios/Classes/Types/URLRequest.swift index 701a4233..b8e9430b 100644 --- a/ios/Classes/Types/URLRequest.swift +++ b/ios/Classes/Types/URLRequest.swift @@ -26,41 +26,56 @@ extension URLRequest { setValue(value, forHTTPHeaderField: key) } } - if let iosAllowsCellularAccess = fromPluginMap["allowsCellularAccess"] as? Bool { - allowsCellularAccess = iosAllowsCellularAccess + if let _allowsCellularAccess = fromPluginMap["allowsCellularAccess"] as? Bool { + allowsCellularAccess = _allowsCellularAccess } - if #available(iOS 13.0, *), let iosAllowsConstrainedNetworkAccess = fromPluginMap["allowsConstrainedNetworkAccess"] as? Bool { - allowsConstrainedNetworkAccess = iosAllowsConstrainedNetworkAccess + if #available(iOS 13.0, *), let _allowsConstrainedNetworkAccess = fromPluginMap["allowsConstrainedNetworkAccess"] as? Bool { + allowsConstrainedNetworkAccess = _allowsConstrainedNetworkAccess } - if #available(iOS 13.0, *), let iosAllowsExpensiveNetworkAccess = fromPluginMap["allowsExpensiveNetworkAccess"] as? Bool { - allowsExpensiveNetworkAccess = iosAllowsExpensiveNetworkAccess + if #available(iOS 13.0, *), let _allowsExpensiveNetworkAccess = fromPluginMap["allowsExpensiveNetworkAccess"] as? Bool { + allowsExpensiveNetworkAccess = _allowsExpensiveNetworkAccess } - if let iosCachePolicy = fromPluginMap["cachePolicy"] as? Int { - cachePolicy = CachePolicy.init(rawValue: UInt(iosCachePolicy)) ?? .useProtocolCachePolicy + if let _cachePolicy = fromPluginMap["cachePolicy"] as? Int { + cachePolicy = CachePolicy.init(rawValue: UInt(_cachePolicy)) ?? .useProtocolCachePolicy } - if let iosHttpShouldHandleCookies = fromPluginMap["httpShouldHandleCookies"] as? Bool { - httpShouldHandleCookies = iosHttpShouldHandleCookies + if let _httpShouldHandleCookies = fromPluginMap["httpShouldHandleCookies"] as? Bool { + httpShouldHandleCookies = _httpShouldHandleCookies } - if let iosHttpShouldUsePipelining = fromPluginMap["httpShouldUsePipelining"] as? Bool { - httpShouldUsePipelining = iosHttpShouldUsePipelining + if let _httpShouldUsePipelining = fromPluginMap["httpShouldUsePipelining"] as? Bool { + httpShouldUsePipelining = _httpShouldUsePipelining } - if let iosNetworkServiceType = fromPluginMap["networkServiceType"] as? Int { - networkServiceType = NetworkServiceType.init(rawValue: UInt(iosNetworkServiceType)) ?? .default + if let _networkServiceType = fromPluginMap["networkServiceType"] as? Int { + networkServiceType = NetworkServiceType.init(rawValue: UInt(_networkServiceType)) ?? .default } - if let iosTimeoutInterval = fromPluginMap["timeoutInterval"] as? Double { - timeoutInterval = iosTimeoutInterval + if let _timeoutInterval = fromPluginMap["timeoutInterval"] as? Double { + timeoutInterval = _timeoutInterval } - if let iosMainDocumentURL = fromPluginMap["mainDocumentURL"] as? String { - mainDocumentURL = URL(string: iosMainDocumentURL)! + if let _mainDocumentURL = fromPluginMap["mainDocumentURL"] as? String { + mainDocumentURL = URL(string: _mainDocumentURL)! + } + if #available(iOS 14.5, *), let _assumesHTTP3Capable = fromPluginMap["assumesHTTP3Capable"] as? Bool { + assumesHTTP3Capable = _assumesHTTP3Capable + } + if #available(iOS 15.0, *), let attributionRawValue = fromPluginMap["attribution"] as? UInt, + let _attribution = URLRequest.Attribution(rawValue: attributionRawValue) { + attribution = _attribution } } public func toMap () -> [String:Any?] { - var iosAllowsConstrainedNetworkAccess: Bool? = nil - var iosAllowsExpensiveNetworkAccess: Bool? = nil + var _allowsConstrainedNetworkAccess: Bool? = nil + var _allowsExpensiveNetworkAccess: Bool? = nil if #available(iOS 13.0, *) { - iosAllowsConstrainedNetworkAccess = allowsConstrainedNetworkAccess - iosAllowsExpensiveNetworkAccess = allowsExpensiveNetworkAccess + _allowsConstrainedNetworkAccess = allowsConstrainedNetworkAccess + _allowsExpensiveNetworkAccess = allowsExpensiveNetworkAccess + } + var _assumesHTTP3Capable: Bool? = nil + if #available(iOS 14.5, *) { + _assumesHTTP3Capable = assumesHTTP3Capable + } + var _attribution: UInt? = nil + if #available(iOS 15.0, *) { + _attribution = attribution.rawValue } return [ "url": url?.absoluteString, @@ -68,14 +83,16 @@ extension URLRequest { "headers": allHTTPHeaderFields, "body": httpBody.map(FlutterStandardTypedData.init(bytes:)), "allowsCellularAccess": allowsCellularAccess, - "allowsConstrainedNetworkAccess": iosAllowsConstrainedNetworkAccess, - "allowsExpensiveNetworkAccess": iosAllowsExpensiveNetworkAccess, + "allowsConstrainedNetworkAccess": _allowsConstrainedNetworkAccess, + "allowsExpensiveNetworkAccess": _allowsExpensiveNetworkAccess, "cachePolicy": cachePolicy.rawValue, "httpShouldHandleCookies": httpShouldHandleCookies, "httpShouldUsePipelining": httpShouldUsePipelining, "networkServiceType": networkServiceType.rawValue, "timeoutInterval": timeoutInterval, - "mainDocumentURL": mainDocumentURL?.absoluteString + "mainDocumentURL": mainDocumentURL?.absoluteString, + "assumesHTTP3Capable": _assumesHTTP3Capable, + "attribution": _attribution ] } } diff --git a/lib/src/types/main.dart b/lib/src/types/main.dart index ef46d869..0152a459 100644 --- a/lib/src/types/main.dart +++ b/lib/src/types/main.dart @@ -147,4 +147,5 @@ export 'web_resource_error_type.dart'; export 'media_capture_state.dart'; export 'proxy_rule.dart'; export 'proxy_scheme_filter.dart'; -export 'force_dark_strategy.dart'; \ No newline at end of file +export 'force_dark_strategy.dart'; +export 'url_request_attribution.dart'; \ No newline at end of file diff --git a/lib/src/types/url_request.dart b/lib/src/types/url_request.dart index 3d76ea6f..faddbf35 100644 --- a/lib/src/types/url_request.dart +++ b/lib/src/types/url_request.dart @@ -1,4 +1,6 @@ import 'dart:typed_data'; +import 'package:flutter_inappwebview/src/types/url_request_attribution.dart'; + import 'url_request_cache_policy.dart'; import 'url_request_network_service_type.dart'; @@ -100,6 +102,20 @@ class URLRequest { ///**NOTE**: available only on iOS. Uri? mainDocumentURL; + ///`true` if server endpoint is known to support HTTP/3. Enables QUIC racing + ///without HTTP/3 service discovery. Defaults to `false`. + ///The default may be `true` in a future OS update. + /// + ///**NOTE**: available only on iOS 14.5+. + bool? assumesHTTP3Capable; + + ///The entities that can make a network request. + /// + ///If you don’t set a value, the system assumes [URLRequestAttribution.DEVELOPER]. + /// + ///**NOTE**: available only on iOS 15.0+. + URLRequestAttribution? attribution; + URLRequest({ required this.url, this.method, @@ -128,6 +144,8 @@ class URLRequest { this.timeoutInterval, @Deprecated("Use mainDocumentURL instead") this.iosMainDocumentURL, this.mainDocumentURL, + this.assumesHTTP3Capable, + this.attribution }) { this.allowsCellularAccess = // ignore: deprecated_member_use_from_same_package @@ -201,6 +219,8 @@ class URLRequest { mainDocumentURL: map["mainDocumentURL"] != null ? Uri.parse(map["mainDocumentURL"]) : null, + assumesHTTP3Capable: map["assumesHTTP3Capable"], + attribution: URLRequestAttribution.fromValue(map["attribution"]) ); } @@ -258,6 +278,8 @@ class URLRequest { "iosMainDocumentURL": (mainDocumentURL ?? iosMainDocumentURL)?.toString(), // ignore: deprecated_member_use_from_same_package "mainDocumentURL": (mainDocumentURL ?? iosMainDocumentURL)?.toString(), + "assumesHTTP3Capable": assumesHTTP3Capable, + "attribution": attribution?.toValue(), }; } diff --git a/lib/src/types/url_request_attribution.dart b/lib/src/types/url_request_attribution.dart new file mode 100644 index 00000000..bdda7923 --- /dev/null +++ b/lib/src/types/url_request_attribution.dart @@ -0,0 +1,60 @@ +import 'url_request.dart'; + +///Class that represents the constants used to indicate the entities that can make a network request. +class URLRequestAttribution { + final int _value; + + const URLRequestAttribution._internal(this._value); + + ///Set of all values of [URLRequestAttribution]. + static final Set values = [ + URLRequestAttribution.DEVELOPER, + URLRequestAttribution.USER, + ].toSet(); + + ///Gets a possible [URLRequestAttribution] instance from an [int] value. + static URLRequestAttribution? fromValue(int? value) { + if (value != null) { + try { + return URLRequestAttribution.values + .firstWhere((element) => element.toValue() == value); + } catch (e) { + return null; + } + } + return null; + } + + ///Gets [int] value. + int toValue() => _value; + + @override + String toString() { + switch (_value) { + case 1: + return "USER"; + case 0: + default: + return "DEVELOPER"; + } + } + + ///A developer-initiated network request. + /// + ///Use this value for the attribution parameter of a [URLRequest] that your app makes for any purpose other than when the user explicitly accesses a link. + ///This includes requests that your app makes to get user data. This is the default value. + /// + ///For cases where the user enters a URL, like in the navigation bar of a web browser, or taps or clicks a URL to load the content it represents, use the [URLRequestAttribution.USER] value instead. + static const DEVELOPER = + const URLRequestAttribution._internal(0); + + ///Use this value for the attribution parameter of a [URLRequest] that satisfies a user request to access an explicit, unmodified URL. + ///In all other cases, use the [URLRequestAttribution.DEVELOPER] value instead. + static const USER = + const URLRequestAttribution._internal(1); + + bool operator ==(value) => value == _value; + + @override + int get hashCode => _value.hashCode; +} \ No newline at end of file