2019-11-02 03:16:47 +00:00
import ' dart:async ' ;
2021-03-08 09:22:13 +00:00
import ' package:flutter/foundation.dart ' ;
2019-10-26 02:42:50 +00:00
import ' package:flutter/services.dart ' ;
2021-02-22 11:16:23 +00:00
import ' in_app_webview/in_app_webview_controller.dart ' ;
2022-04-19 23:31:14 +00:00
import ' in_app_webview/in_app_webview_settings.dart ' ;
2021-02-22 11:16:23 +00:00
import ' in_app_webview/headless_in_app_webview.dart ' ;
2021-03-01 02:21:07 +00:00
import ' platform_util.dart ' ;
2021-02-22 11:16:23 +00:00
2022-04-26 23:03:42 +00:00
import ' types/main.dart ' ;
2019-11-25 00:42:27 +00:00
2020-05-11 00:48:41 +00:00
///Class that implements a singleton object (shared instance) which manages the cookies used by WebView instances.
2020-05-29 12:51:26 +00:00
///On Android, it is implemented using [CookieManager](https://developer.android.com/reference/android/webkit/CookieManager).
///On iOS, it is implemented using [WKHTTPCookieStore](https://developer.apple.com/documentation/webkit/wkhttpcookiestore).
2019-10-26 02:42:50 +00:00
///
2022-04-19 23:31:14 +00:00
///**NOTE for iOS below 11.0 (LIMITED SUPPORT!)**: in this case, almost all of the methods ([CookieManager.deleteAllCookies] and [CookieManager.getAllCookies] are not supported!)
2021-01-30 13:53:32 +00:00
///has been implemented using JavaScript because there is no other way to work with them on iOS below 11.0.
///See https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies for JavaScript restrictions.
2022-04-25 20:36:21 +00:00
///
///**NOTE for Web (LIMITED SUPPORT!)**: in this case, almost all of the methods ([CookieManager.deleteAllCookies] and [CookieManager.getAllCookies] are not supported!)
///has been implemented using JavaScript, so all methods will have effect only if the iframe has the same origin.
///See https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies for JavaScript restrictions.
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS
///- Web
2019-10-26 02:42:50 +00:00
class CookieManager {
2021-01-28 16:10:15 +00:00
static CookieManager ? _instance ;
2019-12-01 11:55:06 +00:00
static const MethodChannel _channel = const MethodChannel (
' com.pichillilorenzo/flutter_inappwebview_cookiemanager ' ) ;
2019-10-26 02:42:50 +00:00
2021-01-31 21:08:20 +00:00
///Contains only iOS-specific methods of [CookieManager].
2022-04-19 23:31:14 +00:00
///Use [CookieManager] instead.
@ Deprecated ( " Use CookieManager instead " )
2021-01-31 21:08:20 +00:00
late IOSCookieManager ios ;
///Gets the [CookieManager] shared instance.
2019-10-31 02:20:07 +00:00
static CookieManager instance ( ) {
2021-01-28 16:10:15 +00:00
return ( _instance ! = null ) ? _instance ! : _init ( ) ;
2019-10-26 02:42:50 +00:00
}
2019-10-31 02:20:07 +00:00
static CookieManager _init ( ) {
_channel . setMethodCallHandler ( _handleMethod ) ;
2020-05-29 17:56:03 +00:00
_instance = CookieManager ( ) ;
2022-04-19 23:31:14 +00:00
// ignore: deprecated_member_use_from_same_package
2021-01-31 21:08:20 +00:00
_instance ! . ios = IOSCookieManager . instance ( ) ;
2021-01-28 16:10:15 +00:00
return _instance ! ;
2019-10-31 02:20:07 +00:00
}
2019-12-01 11:55:06 +00:00
static Future < dynamic > _handleMethod ( MethodCall call ) async { }
2019-10-26 02:42:50 +00:00
2021-01-30 13:53:32 +00:00
///Sets a cookie for the given [url]. Any existing cookie with the same [host], [path] and [name] will be replaced with the new cookie.
///The cookie being set will be ignored if it is expired.
2019-10-26 02:42:50 +00:00
///
///The default value of [path] is `"/"`.
///If [domain] is `null`, its default value will be the domain name of [url].
2021-01-30 13:53:32 +00:00
///
2022-04-25 20:36:21 +00:00
///[webViewController] could be used if you need to set a session-only cookie using JavaScript (so [isHttpOnly] cannot be set, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
///on the current URL of the [WebView] managed by that controller when you need to target iOS below 11 and Web platform. In this case the [url] parameter is ignored.
///
///**NOTE for iOS below 11.0**: If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
///to set the cookie (session-only cookie won't work! In that case, you should set also [expiresDate] or [maxAge]).
2021-01-30 13:53:32 +00:00
///
2022-04-25 20:36:21 +00:00
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
///If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
2021-01-30 13:53:32 +00:00
///to set the cookie (session-only cookie won't work! In that case, you should set also [expiresDate] or [maxAge]).
2022-04-19 23:31:14 +00:00
///
///**Supported Platforms/Implementations**:
///- Android native WebView ([Official API - CookieManager.setCookie](https://developer.android.com/reference/android/webkit/CookieManager#setCookie(java.lang.String,%20java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.Boolean%3E)))
///- iOS ([Official API - WKHTTPCookieStore.setCookie](https://developer.apple.com/documentation/webkit/wkhttpcookiestore/2882007-setcookie))
2022-04-25 20:36:21 +00:00
///- Web
2019-12-01 11:55:06 +00:00
Future < void > setCookie (
2021-02-22 11:16:23 +00:00
{ required Uri url ,
2021-01-28 16:10:15 +00:00
required String name ,
required String value ,
String ? domain ,
2019-12-01 11:55:06 +00:00
String path = " / " ,
2021-01-28 16:10:15 +00:00
int ? expiresDate ,
int ? maxAge ,
bool ? isSecure ,
bool ? isHttpOnly ,
2021-01-30 13:53:32 +00:00
HTTPCookieSameSitePolicy ? sameSite ,
2022-04-25 21:21:26 +00:00
@ Deprecated ( " Use webViewController instead " )
InAppWebViewController ? iosBelow11WebViewController ,
2022-04-25 20:36:21 +00:00
InAppWebViewController ? webViewController } ) async {
2020-06-13 01:50:19 +00:00
if ( domain = = null ) domain = _getDomainName ( url ) ;
2019-10-26 02:42:50 +00:00
2022-04-25 20:36:21 +00:00
webViewController = webViewController ? ? iosBelow11WebViewController ;
2021-02-22 11:16:23 +00:00
assert ( url . toString ( ) . isNotEmpty ) ;
2021-01-28 16:10:15 +00:00
assert ( name . isNotEmpty ) ;
assert ( value . isNotEmpty ) ;
assert ( domain . isNotEmpty ) ;
assert ( path . isNotEmpty ) ;
2019-10-26 02:42:50 +00:00
2022-04-25 20:36:21 +00:00
if ( defaultTargetPlatform = = TargetPlatform . iOS | | kIsWeb ) {
var shouldUseJavascript = kIsWeb ;
if ( defaultTargetPlatform = = TargetPlatform . iOS & & ! kIsWeb ) {
var platformUtil = PlatformUtil . instance ( ) ;
var version = double . tryParse ( await platformUtil . getSystemVersion ( ) ) ;
shouldUseJavascript = version ! = null & & version < 11.0 ;
}
if ( shouldUseJavascript ) {
2021-02-22 22:54:09 +00:00
await _setCookieWithJavaScript (
url: url ,
name: name ,
value: value ,
domain: domain ,
path: path ,
expiresDate: expiresDate ,
maxAge: maxAge ,
isSecure: isSecure ,
sameSite: sameSite ,
2022-04-25 20:36:21 +00:00
webViewController: webViewController ) ;
2021-01-30 13:53:32 +00:00
return ;
}
}
2019-10-26 02:42:50 +00:00
Map < String , dynamic > args = < String , dynamic > { } ;
2021-02-22 11:16:23 +00:00
args . putIfAbsent ( ' url ' , ( ) = > url . toString ( ) ) ;
2019-10-26 02:42:50 +00:00
args . putIfAbsent ( ' name ' , ( ) = > name ) ;
args . putIfAbsent ( ' value ' , ( ) = > value ) ;
args . putIfAbsent ( ' domain ' , ( ) = > domain ) ;
args . putIfAbsent ( ' path ' , ( ) = > path ) ;
args . putIfAbsent ( ' expiresDate ' , ( ) = > expiresDate ? . toString ( ) ) ;
args . putIfAbsent ( ' maxAge ' , ( ) = > maxAge ) ;
args . putIfAbsent ( ' isSecure ' , ( ) = > isSecure ) ;
2020-06-13 01:50:19 +00:00
args . putIfAbsent ( ' isHttpOnly ' , ( ) = > isHttpOnly ) ;
args . putIfAbsent ( ' sameSite ' , ( ) = > sameSite ? . toValue ( ) ) ;
2019-10-26 02:42:50 +00:00
await _channel . invokeMethod ( ' setCookie ' , args ) ;
}
2021-02-01 14:55:27 +00:00
Future < void > _setCookieWithJavaScript (
2021-02-22 11:16:23 +00:00
{ required Uri url ,
2021-02-22 22:54:09 +00:00
required String name ,
required String value ,
required String domain ,
String path = " / " ,
int ? expiresDate ,
int ? maxAge ,
bool ? isSecure ,
HTTPCookieSameSitePolicy ? sameSite ,
InAppWebViewController ? webViewController } ) async {
var cookieValue =
name + " = " + value + " ; Domain= " + domain + " ; Path= " + path ;
2021-02-01 14:55:27 +00:00
if ( expiresDate ! = null )
2021-03-01 02:21:07 +00:00
cookieValue + = " ; Expires= " + await _getCookieExpirationDate ( expiresDate ) ;
2021-02-01 14:55:27 +00:00
2021-02-22 22:54:09 +00:00
if ( maxAge ! = null ) cookieValue + = " ; Max-Age= " + maxAge . toString ( ) ;
2021-02-01 14:55:27 +00:00
2021-02-22 22:54:09 +00:00
if ( isSecure ! = null & & isSecure ) cookieValue + = " ; Secure " ;
2021-02-01 14:55:27 +00:00
2021-02-22 22:54:09 +00:00
if ( sameSite ! = null ) cookieValue + = " ; SameSite= " + sameSite . toValue ( ) ;
2021-02-01 14:55:27 +00:00
cookieValue + = " ; " ;
if ( webViewController ! = null ) {
2022-04-19 23:31:14 +00:00
InAppWebViewSettings ? settings = await webViewController . getSettings ( ) ;
if ( settings ! = null & & settings . javaScriptEnabled ) {
2021-02-01 14:55:27 +00:00
await webViewController . evaluateJavascript (
source : ' document.cookie=" $ cookieValue " ' ) ;
return ;
}
}
var setCookieCompleter = Completer < void > ( ) ;
var headlessWebView = new HeadlessInAppWebView (
2021-02-22 11:16:23 +00:00
initialUrlRequest: URLRequest ( url: url ) ,
2021-02-01 14:55:27 +00:00
onLoadStop: ( controller , url ) async {
await controller . evaluateJavascript (
source : ' document.cookie=" $ cookieValue " ' ) ;
setCookieCompleter . complete ( ) ;
} ,
) ;
await headlessWebView . run ( ) ;
await setCookieCompleter . future ;
await headlessWebView . dispose ( ) ;
}
2019-10-26 02:42:50 +00:00
///Gets all the cookies for the given [url].
2021-01-30 13:53:32 +00:00
///
2022-04-25 20:36:21 +00:00
///[webViewController] is used for getting the cookies (also session-only cookies) using JavaScript (cookies with `isHttpOnly` enabled cannot be found, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
///from the current context of the [WebView] managed by that controller when you need to target iOS below 11 and Web platform. JavaScript must be enabled in order to work.
2021-01-30 13:53:32 +00:00
///In this case the [url] parameter is ignored.
///
///**NOTE for iOS below 11.0**: All the cookies returned this way will have all the properties to `null` except for [Cookie.name] and [Cookie.value].
2022-04-25 20:36:21 +00:00
///If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
///to get the cookies (session-only cookies and cookies with `isHttpOnly` enabled won't be found!).
///
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
///If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
2021-01-30 13:53:32 +00:00
///to get the cookies (session-only cookies and cookies with `isHttpOnly` enabled won't be found!).
2022-04-19 23:31:14 +00:00
///
///**Supported Platforms/Implementations**:
///- Android native WebView ([Official API - CookieManager.getCookie](https://developer.android.com/reference/android/webkit/CookieManager#getCookie(java.lang.String)))
///- iOS ([Official API - WKHTTPCookieStore.getAllCookies](https://developer.apple.com/documentation/webkit/wkhttpcookiestore/2882005-getallcookies))
2022-04-25 20:36:21 +00:00
///- Web
2021-02-22 22:54:09 +00:00
Future < List < Cookie > > getCookies (
{ required Uri url ,
2022-04-25 21:21:26 +00:00
@ Deprecated ( " Use webViewController instead " )
InAppWebViewController ? iosBelow11WebViewController ,
2022-04-25 20:36:21 +00:00
InAppWebViewController ? webViewController } ) async {
2021-02-22 11:16:23 +00:00
assert ( url . toString ( ) . isNotEmpty ) ;
2019-10-26 02:42:50 +00:00
2022-04-25 20:36:21 +00:00
webViewController = webViewController ? ? iosBelow11WebViewController ;
if ( defaultTargetPlatform = = TargetPlatform . iOS | | kIsWeb ) {
var shouldUseJavascript = kIsWeb ;
if ( defaultTargetPlatform = = TargetPlatform . iOS & & ! kIsWeb ) {
var platformUtil = PlatformUtil . instance ( ) ;
var version = double . tryParse ( await platformUtil . getSystemVersion ( ) ) ;
shouldUseJavascript = version ! = null & & version < 11.0 ;
}
if ( shouldUseJavascript ) {
2021-02-22 22:54:09 +00:00
return await _getCookiesWithJavaScript (
2022-04-25 20:36:21 +00:00
url: url , webViewController: webViewController ) ;
2021-01-30 13:53:32 +00:00
}
}
2021-02-01 14:55:27 +00:00
List < Cookie > cookies = [ ] ;
2019-10-26 02:42:50 +00:00
Map < String , dynamic > args = < String , dynamic > { } ;
2021-02-22 11:16:23 +00:00
args . putIfAbsent ( ' url ' , ( ) = > url . toString ( ) ) ;
2019-12-01 11:55:06 +00:00
List < dynamic > cookieListMap =
await _channel . invokeMethod ( ' getCookies ' , args ) ;
2019-11-25 00:42:27 +00:00
cookieListMap = cookieListMap . cast < Map < dynamic , dynamic > > ( ) ;
2020-06-13 01:50:19 +00:00
2021-01-30 13:53:32 +00:00
cookieListMap . forEach ( ( cookieMap ) {
2019-12-01 11:55:06 +00:00
cookies . add ( Cookie (
2021-01-30 13:53:32 +00:00
name: cookieMap [ " name " ] ,
value: cookieMap [ " value " ] ,
expiresDate: cookieMap [ " expiresDate " ] ,
isSessionOnly: cookieMap [ " isSessionOnly " ] ,
domain: cookieMap [ " domain " ] ,
2021-02-22 22:54:09 +00:00
sameSite: HTTPCookieSameSitePolicy . fromValue ( cookieMap [ " sameSite " ] ) ,
2021-01-30 13:53:32 +00:00
isSecure: cookieMap [ " isSecure " ] ,
isHttpOnly: cookieMap [ " isHttpOnly " ] ,
path: cookieMap [ " path " ] ) ) ;
} ) ;
2019-10-26 02:42:50 +00:00
return cookies ;
}
2021-02-22 22:54:09 +00:00
Future < List < Cookie > > _getCookiesWithJavaScript (
{ required Uri url , InAppWebViewController ? webViewController } ) async {
2021-02-22 11:16:23 +00:00
assert ( url . toString ( ) . isNotEmpty ) ;
2021-02-01 14:55:27 +00:00
List < Cookie > cookies = [ ] ;
if ( webViewController ! = null ) {
2022-04-19 23:31:14 +00:00
InAppWebViewSettings ? settings = await webViewController . getSettings ( ) ;
if ( settings ! = null & & settings . javaScriptEnabled ) {
2021-02-22 22:54:09 +00:00
List < String > documentCookies = ( await webViewController
. evaluateJavascript ( source : ' document.cookie ' ) as String )
. split ( ' ; ' )
. map ( ( documentCookie ) = > documentCookie . trim ( ) )
. toList ( ) ;
2021-02-01 14:55:27 +00:00
documentCookies . forEach ( ( documentCookie ) {
List < String > cookie = documentCookie . split ( ' = ' ) ;
2022-04-25 20:36:21 +00:00
if ( cookie . length > 1 ) {
cookies . add ( Cookie (
name: cookie [ 0 ] ,
value: cookie [ 1 ] ,
) ) ;
}
2021-02-01 14:55:27 +00:00
} ) ;
return cookies ;
}
}
var pageLoaded = Completer < void > ( ) ;
var headlessWebView = new HeadlessInAppWebView (
2021-02-22 11:16:23 +00:00
initialUrlRequest: URLRequest ( url: url ) ,
2021-02-01 14:55:27 +00:00
onLoadStop: ( controller , url ) async {
pageLoaded . complete ( ) ;
} ,
) ;
await headlessWebView . run ( ) ;
await pageLoaded . future ;
2021-02-22 22:54:09 +00:00
List < String > documentCookies = ( await headlessWebView . webViewController
. evaluateJavascript ( source : ' document.cookie ' ) as String )
. split ( ' ; ' )
. map ( ( documentCookie ) = > documentCookie . trim ( ) )
. toList ( ) ;
2021-02-01 14:55:27 +00:00
documentCookies . forEach ( ( documentCookie ) {
List < String > cookie = documentCookie . split ( ' = ' ) ;
2022-04-25 20:36:21 +00:00
if ( cookie . length > 1 ) {
cookies . add ( Cookie (
name: cookie [ 0 ] ,
value: cookie [ 1 ] ,
) ) ;
}
2021-02-01 14:55:27 +00:00
} ) ;
await headlessWebView . dispose ( ) ;
return cookies ;
}
2019-10-26 02:42:50 +00:00
///Gets a cookie by its [name] for the given [url].
2021-01-30 13:53:32 +00:00
///
2022-04-25 20:36:21 +00:00
///[webViewController] is used for getting the cookie (also session-only cookie) using JavaScript (cookie with `isHttpOnly` enabled cannot be found, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
///from the current context of the [WebView] managed by that controller when you need to target iOS below 11 and Web platform. JavaScript must be enabled in order to work.
2021-01-30 13:53:32 +00:00
///In this case the [url] parameter is ignored.
///
///**NOTE for iOS below 11.0**: All the cookies returned this way will have all the properties to `null` except for [Cookie.name] and [Cookie.value].
2022-04-25 20:36:21 +00:00
///If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
///to get the cookie (session-only cookie and cookie with `isHttpOnly` enabled won't be found!).
///
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
///If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
2021-01-30 13:53:32 +00:00
///to get the cookie (session-only cookie and cookie with `isHttpOnly` enabled won't be found!).
2022-04-19 23:31:14 +00:00
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS
2022-04-25 20:36:21 +00:00
///- Web
2021-01-28 16:10:15 +00:00
Future < Cookie ? > getCookie (
2021-02-22 22:54:09 +00:00
{ required Uri url ,
required String name ,
2022-04-25 21:21:26 +00:00
@ Deprecated ( " Use webViewController instead " )
InAppWebViewController ? iosBelow11WebViewController ,
2022-04-25 20:36:21 +00:00
InAppWebViewController ? webViewController } ) async {
2021-02-22 11:16:23 +00:00
assert ( url . toString ( ) . isNotEmpty ) ;
2021-01-28 16:10:15 +00:00
assert ( name . isNotEmpty ) ;
2019-10-26 02:42:50 +00:00
2022-04-25 20:36:21 +00:00
webViewController = webViewController ? ? iosBelow11WebViewController ;
if ( defaultTargetPlatform = = TargetPlatform . iOS | | kIsWeb ) {
var shouldUseJavascript = kIsWeb ;
if ( defaultTargetPlatform = = TargetPlatform . iOS & & ! kIsWeb ) {
var platformUtil = PlatformUtil . instance ( ) ;
var version = double . tryParse ( await platformUtil . getSystemVersion ( ) ) ;
shouldUseJavascript = version ! = null & & version < 11.0 ;
}
if ( shouldUseJavascript ) {
2021-02-22 22:54:09 +00:00
List < Cookie > cookies = await _getCookiesWithJavaScript (
2022-04-25 20:36:21 +00:00
url: url , webViewController: webViewController ) ;
2021-02-22 22:54:09 +00:00
return cookies
. cast < Cookie ? > ( )
. firstWhere ( ( cookie ) = > cookie ! . name = = name , orElse: ( ) = > null ) ;
2021-01-30 13:53:32 +00:00
}
}
2019-10-26 02:42:50 +00:00
Map < String , dynamic > args = < String , dynamic > { } ;
2021-02-22 11:16:23 +00:00
args . putIfAbsent ( ' url ' , ( ) = > url . toString ( ) ) ;
2019-10-26 02:42:50 +00:00
List < dynamic > cookies = await _channel . invokeMethod ( ' getCookies ' , args ) ;
cookies = cookies . cast < Map < dynamic , dynamic > > ( ) ;
2019-12-01 11:55:06 +00:00
for ( var i = 0 ; i < cookies . length ; i + + ) {
2019-10-26 02:42:50 +00:00
cookies [ i ] = cookies [ i ] . cast < String , dynamic > ( ) ;
if ( cookies [ i ] [ " name " ] = = name )
2020-06-13 01:50:19 +00:00
return Cookie (
name: cookies [ i ] [ " name " ] ,
value: cookies [ i ] [ " value " ] ,
expiresDate: cookies [ i ] [ " expiresDate " ] ,
isSessionOnly: cookies [ i ] [ " isSessionOnly " ] ,
domain: cookies [ i ] [ " domain " ] ,
2020-06-21 22:09:35 +00:00
sameSite:
HTTPCookieSameSitePolicy . fromValue ( cookies [ i ] [ " sameSite " ] ) ,
2020-06-13 01:50:19 +00:00
isSecure: cookies [ i ] [ " isSecure " ] ,
isHttpOnly: cookies [ i ] [ " isHttpOnly " ] ,
path: cookies [ i ] [ " path " ] ) ;
2019-10-26 02:42:50 +00:00
}
return null ;
}
///Removes a cookie by its [name] for the given [url], [domain] and [path].
///
///The default value of [path] is `"/"`.
2021-01-30 13:53:32 +00:00
///If [domain] is empty, its default value will be the domain name of [url].
///
2022-04-25 20:36:21 +00:00
///[webViewController] is used for deleting the cookie (also session-only cookie) using JavaScript (cookie with `isHttpOnly` enabled cannot be deleted, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
///from the current context of the [WebView] managed by that controller when you need to target iOS below 11 and Web platform. JavaScript must be enabled in order to work.
2021-01-30 13:53:32 +00:00
///In this case the [url] parameter is ignored.
///
2022-04-25 20:36:21 +00:00
///**NOTE for iOS below 11.0**: If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
///to delete the cookie (session-only cookie and cookie with `isHttpOnly` enabled won't be deleted!).
///
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
///If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
2021-01-30 13:53:32 +00:00
///to delete the cookie (session-only cookie and cookie with `isHttpOnly` enabled won't be deleted!).
2022-04-19 23:31:14 +00:00
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS ([Official API - WKHTTPCookieStore.delete](https://developer.apple.com/documentation/webkit/wkhttpcookiestore/2882009-delete)
2022-04-25 20:36:21 +00:00
///- Web
2019-12-01 11:55:06 +00:00
Future < void > deleteCookie (
2021-02-22 11:16:23 +00:00
{ required Uri url ,
2021-01-28 16:10:15 +00:00
required String name ,
2019-12-01 11:55:06 +00:00
String domain = " " ,
2021-01-30 13:53:32 +00:00
String path = " / " ,
2022-04-25 21:21:26 +00:00
@ Deprecated ( " Use webViewController instead " )
InAppWebViewController ? iosBelow11WebViewController ,
2022-04-25 20:36:21 +00:00
InAppWebViewController ? webViewController } ) async {
2021-01-28 16:10:15 +00:00
if ( domain . isEmpty ) domain = _getDomainName ( url ) ;
2019-10-26 02:42:50 +00:00
2021-02-22 11:16:23 +00:00
assert ( url . toString ( ) . isNotEmpty ) ;
2021-01-28 16:10:15 +00:00
assert ( name . isNotEmpty ) ;
2021-01-30 13:53:32 +00:00
2022-04-25 20:36:21 +00:00
webViewController = webViewController ? ? iosBelow11WebViewController ;
if ( defaultTargetPlatform = = TargetPlatform . iOS | | kIsWeb ) {
var shouldUseJavascript = kIsWeb ;
if ( defaultTargetPlatform = = TargetPlatform . iOS & & ! kIsWeb ) {
var platformUtil = PlatformUtil . instance ( ) ;
var version = double . tryParse ( await platformUtil . getSystemVersion ( ) ) ;
shouldUseJavascript = version ! = null & & version < 11.0 ;
}
if ( shouldUseJavascript ) {
2021-02-22 22:54:09 +00:00
await _setCookieWithJavaScript (
url: url ,
name: name ,
value: " " ,
path: path ,
domain: domain ,
maxAge: - 1 ,
2022-04-25 20:36:21 +00:00
webViewController: webViewController ) ;
2021-01-30 13:53:32 +00:00
return ;
}
}
2019-10-26 02:42:50 +00:00
Map < String , dynamic > args = < String , dynamic > { } ;
2021-02-22 11:16:23 +00:00
args . putIfAbsent ( ' url ' , ( ) = > url . toString ( ) ) ;
2019-10-26 02:42:50 +00:00
args . putIfAbsent ( ' name ' , ( ) = > name ) ;
args . putIfAbsent ( ' domain ' , ( ) = > domain ) ;
args . putIfAbsent ( ' path ' , ( ) = > path ) ;
await _channel . invokeMethod ( ' deleteCookie ' , args ) ;
}
///Removes all cookies for the given [url], [domain] and [path].
///
///The default value of [path] is `"/"`.
2021-01-30 13:53:32 +00:00
///If [domain] is empty, its default value will be the domain name of [url].
///
2022-04-25 20:36:21 +00:00
///[webViewController] is used for deleting the cookies (also session-only cookies) using JavaScript (cookies with `isHttpOnly` enabled cannot be deleted, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
///from the current context of the [WebView] managed by that controller when you need to target iOS below 11 and Web platform. JavaScript must be enabled in order to work.
2021-01-30 13:53:32 +00:00
///In this case the [url] parameter is ignored.
///
2022-04-25 20:36:21 +00:00
///**NOTE for iOS below 11.0**: If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
///to delete the cookies (session-only cookies and cookies with `isHttpOnly` enabled won't be deleted!).
///
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
///If [webViewController] is `null` or JavaScript is disabled for it, it will try to use a [HeadlessInAppWebView]
2021-01-30 13:53:32 +00:00
///to delete the cookies (session-only cookies and cookies with `isHttpOnly` enabled won't be deleted!).
2022-04-19 23:31:14 +00:00
///
///**Supported Platforms/Implementations**:
///- Android native WebView
///- iOS
2022-04-25 20:36:21 +00:00
///- Web
2019-12-01 11:55:06 +00:00
Future < void > deleteCookies (
2021-02-22 22:54:09 +00:00
{ required Uri url ,
String domain = " " ,
String path = " / " ,
2022-04-25 21:21:26 +00:00
@ Deprecated ( " Use webViewController instead " )
InAppWebViewController ? iosBelow11WebViewController ,
2022-04-25 20:36:21 +00:00
InAppWebViewController ? webViewController } ) async {
2021-01-28 16:10:15 +00:00
if ( domain . isEmpty ) domain = _getDomainName ( url ) ;
2019-10-26 02:42:50 +00:00
2021-02-22 11:16:23 +00:00
assert ( url . toString ( ) . isNotEmpty ) ;
2021-01-30 13:53:32 +00:00
2022-04-25 20:36:21 +00:00
webViewController = webViewController ? ? iosBelow11WebViewController ;
if ( defaultTargetPlatform = = TargetPlatform . iOS | | kIsWeb ) {
var shouldUseJavascript = kIsWeb ;
if ( defaultTargetPlatform = = TargetPlatform . iOS & & ! kIsWeb ) {
var platformUtil = PlatformUtil . instance ( ) ;
var version = double . tryParse ( await platformUtil . getSystemVersion ( ) ) ;
shouldUseJavascript = version ! = null & & version < 11.0 ;
}
if ( shouldUseJavascript ) {
2021-02-22 22:54:09 +00:00
List < Cookie > cookies = await _getCookiesWithJavaScript (
2022-04-25 20:36:21 +00:00
url: url , webViewController: webViewController ) ;
2021-01-30 13:53:32 +00:00
for ( var i = 0 ; i < cookies . length ; i + + ) {
2021-02-22 22:54:09 +00:00
await _setCookieWithJavaScript (
url: url ,
name: cookies [ i ] . name ,
value: " " ,
path: path ,
domain: domain ,
maxAge: - 1 ,
2022-04-25 20:36:21 +00:00
webViewController: webViewController ) ;
2021-01-30 13:53:32 +00:00
}
return ;
}
}
2019-10-26 02:42:50 +00:00
Map < String , dynamic > args = < String , dynamic > { } ;
2021-02-22 11:16:23 +00:00
args . putIfAbsent ( ' url ' , ( ) = > url . toString ( ) ) ;
2019-10-26 02:42:50 +00:00
args . putIfAbsent ( ' domain ' , ( ) = > domain ) ;
args . putIfAbsent ( ' path ' , ( ) = > path ) ;
await _channel . invokeMethod ( ' deleteCookies ' , args ) ;
}
///Removes all cookies.
2021-01-30 13:53:32 +00:00
///
///**NOTE for iOS**: available from iOS 11.0+.
2022-04-19 23:31:14 +00:00
///
///**Supported Platforms/Implementations**:
///- Android native WebView ([Official API - CookieManager.removeAllCookies](https://developer.android.com/reference/android/webkit/CookieManager#removeAllCookies(android.webkit.ValueCallback%3Cjava.lang.Boolean%3E)))
///- iOS ([Official API - WKWebsiteDataStore.removeData](https://developer.apple.com/documentation/webkit/wkwebsitedatastore/1532938-removedata))
2019-10-31 02:20:07 +00:00
Future < void > deleteAllCookies ( ) async {
2019-10-26 02:42:50 +00:00
Map < String , dynamic > args = < String , dynamic > { } ;
await _channel . invokeMethod ( ' deleteAllCookies ' , args ) ;
}
2022-04-19 23:31:14 +00:00
///Fetches all stored cookies.
///
///**NOTE**: available on iOS 11.0+.
///
///**Supported Platforms/Implementations**:
///- iOS ([Official API - WKHTTPCookieStore.getAllCookies](https://developer.apple.com/documentation/webkit/wkhttpcookiestore/2882005-getallcookies))
Future < List < Cookie > > getAllCookies ( ) async {
List < Cookie > cookies = [ ] ;
Map < String , dynamic > args = < String , dynamic > { } ;
List < dynamic > cookieListMap =
2022-04-20 01:05:46 +00:00
await CookieManager . _channel . invokeMethod ( ' getAllCookies ' , args ) ;
2022-04-19 23:31:14 +00:00
cookieListMap = cookieListMap . cast < Map < dynamic , dynamic > > ( ) ;
cookieListMap . forEach ( ( cookieMap ) {
cookies . add ( Cookie (
name: cookieMap [ " name " ] ,
value: cookieMap [ " value " ] ,
expiresDate: cookieMap [ " expiresDate " ] ,
isSessionOnly: cookieMap [ " isSessionOnly " ] ,
domain: cookieMap [ " domain " ] ,
sameSite: HTTPCookieSameSitePolicy . fromValue ( cookieMap [ " sameSite " ] ) ,
isSecure: cookieMap [ " isSecure " ] ,
isHttpOnly: cookieMap [ " isHttpOnly " ] ,
path: cookieMap [ " path " ] ) ) ;
} ) ;
return cookies ;
}
2021-02-22 11:16:23 +00:00
String _getDomainName ( Uri url ) {
String domain = url . host ;
2019-10-26 02:42:50 +00:00
return domain . startsWith ( " www. " ) ? domain . substring ( 4 ) : domain ;
}
2021-01-30 13:53:32 +00:00
2021-03-01 02:21:07 +00:00
Future < String > _getCookieExpirationDate ( int expiresDate ) async {
2022-04-25 20:36:21 +00:00
var platformUtil = PlatformUtil . instance ( ) ;
2021-01-30 13:53:32 +00:00
var dateTime = DateTime . fromMillisecondsSinceEpoch ( expiresDate ) . toUtc ( ) ;
2022-04-25 21:21:26 +00:00
return ! kIsWeb
? await platformUtil . formatDate (
date: dateTime ,
format: ' EEE, dd MMM yyyy hh:mm:ss z ' ,
locale: ' en_US ' ,
timezone: ' GMT ' )
: await platformUtil . getWebCookieExpirationDate ( date: dateTime ) ;
2021-01-30 13:53:32 +00:00
}
2019-12-01 11:55:06 +00:00
}
2021-01-31 21:08:20 +00:00
///Class that contains only iOS-specific methods of [CookieManager].
2022-04-19 23:31:14 +00:00
///Use [CookieManager] instead.
@ Deprecated ( " Use CookieManager instead " )
2021-01-31 21:08:20 +00:00
class IOSCookieManager {
static IOSCookieManager ? _instance ;
///Gets the [IOSCookieManager] shared instance.
static IOSCookieManager instance ( ) {
return ( _instance ! = null ) ? _instance ! : _init ( ) ;
}
static IOSCookieManager _init ( ) {
_instance = IOSCookieManager ( ) ;
return _instance ! ;
}
///Fetches all stored cookies.
///
///**NOTE**: available on iOS 11.0+.
///
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkhttpcookiestore/2882005-getallcookies
Future < List < Cookie > > getAllCookies ( ) async {
List < Cookie > cookies = [ ] ;
Map < String , dynamic > args = < String , dynamic > { } ;
List < dynamic > cookieListMap =
2021-02-22 22:54:09 +00:00
await CookieManager . _channel . invokeMethod ( ' getAllCookies ' , args ) ;
2021-01-31 21:08:20 +00:00
cookieListMap = cookieListMap . cast < Map < dynamic , dynamic > > ( ) ;
cookieListMap . forEach ( ( cookieMap ) {
cookies . add ( Cookie (
name: cookieMap [ " name " ] ,
value: cookieMap [ " value " ] ,
expiresDate: cookieMap [ " expiresDate " ] ,
isSessionOnly: cookieMap [ " isSessionOnly " ] ,
domain: cookieMap [ " domain " ] ,
2021-02-22 22:54:09 +00:00
sameSite: HTTPCookieSameSitePolicy . fromValue ( cookieMap [ " sameSite " ] ) ,
2021-01-31 21:08:20 +00:00
isSecure: cookieMap [ " isSecure " ] ,
isHttpOnly: cookieMap [ " isHttpOnly " ] ,
path: cookieMap [ " path " ] ) ) ;
} ) ;
return cookies ;
}
2021-02-22 22:54:09 +00:00
}