diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ad84d35..8dca95b3 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,10 @@ - Merged "Add directoryIndex and documentRoot to InAppLocalhostServer option" [#1319](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1319) (thanks to [fa0311](https://github.com/fa0311)) - Merged "fix(ios): invoke onBrowserCreated when viewDidLoad is called with win…" [#1344](https://github.com/pichillilorenzo/flutter_inappwebview/pull/1344) (thanks to [perffecto](https://github.com/perffecto)) +### BREAKING CHANGES + +- `CookieManager.getCookie`, `CookieManager.deleteCookie` and `CookieManager.deleteCookies` have the `domain` argument optional and without a default value + ## 5.4.4+3 - Removed Android unsafe trust manager diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java index a6ba6d9e..64765db0 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java @@ -171,13 +171,16 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler { }); cookieManager.flush(); } - else { + else if (plugin != null) { CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(plugin.applicationContext); cookieSyncMngr.startSync(); cookieManager.setCookie(url, cookieValue); result.success(true); cookieSyncMngr.stopSync(); cookieSyncMngr.sync(); + } else { + cookieManager.setCookie(url, cookieValue); + result.success(true); } } @@ -218,7 +221,12 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler { cookieManager = getCookieManager(); if (cookieManager == null) return; - String cookieValue = name + "=; Path=" + path + "; Domain=" + domain + "; Max-Age=-1;"; + String cookieValue = name + "=; Path=" + path + "; Max-Age=-1"; + + if (domain != null) + cookieValue += "; Domain=" + domain; + + cookieValue += ";"; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { cookieManager.setCookie(url, cookieValue, new ValueCallback() { @@ -229,13 +237,16 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler { }); cookieManager.flush(); } - else { + else if (plugin != null) { CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(plugin.applicationContext); cookieSyncMngr.startSync(); cookieManager.setCookie(url, cookieValue); result.success(true); cookieSyncMngr.stopSync(); cookieSyncMngr.sync(); + } else { + cookieManager.setCookie(url, cookieValue); + result.success(true); } } @@ -248,7 +259,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler { String cookiesString = cookieManager.getCookie(url); if (cookiesString != null) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && plugin != null) { cookieSyncMngr = CookieSyncManager.createInstance(plugin.applicationContext); cookieSyncMngr.startSync(); } @@ -257,7 +268,14 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler { for (String cookie : cookies) { String[] nameValue = cookie.split("=", 2); String name = nameValue[0].trim(); - String cookieValue = name + "=; Path=" + path + "; Domain=" + domain + "; Max-Age=-1;"; + + String cookieValue = name + "=; Path=" + path + "; Max-Age=-1"; + + if (domain != null) + cookieValue += "; Domain=" + domain; + + cookieValue += ";"; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) cookieManager.setCookie(url, cookieValue, null); else @@ -286,13 +304,16 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler { }); cookieManager.flush(); } - else { + else if (plugin != null) { CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(plugin.applicationContext); cookieSyncMngr.startSync(); cookieManager.removeAllCookie(); result.success(true); cookieSyncMngr.stopSync(); cookieSyncMngr.sync(); + } else { + cookieManager.removeAllCookie(); + result.success(true); } } diff --git a/example/integration_test/webview_flutter_test.dart b/example/integration_test/webview_flutter_test.dart index e73e1397..8494c2db 100644 --- a/example/integration_test/webview_flutter_test.dart +++ b/example/integration_test/webview_flutter_test.dart @@ -5578,7 +5578,7 @@ setTimeout(function() { cookie = await cookieManager.getCookie(url: url, name: "myCookie"); expect(cookie, isNull); - await cookieManager.deleteCookies(url: url); + await cookieManager.deleteCookies(url: url, domain: ".flutter.dev"); cookies = await cookieManager.getCookies(url: url); expect(cookies, isEmpty); }); diff --git a/example/lib/in_app_webiew_example.screen.dart b/example/lib/in_app_webiew_example.screen.dart index a42b9b45..12929e1f 100755 --- a/example/lib/in_app_webiew_example.screen.dart +++ b/example/lib/in_app_webiew_example.screen.dart @@ -118,7 +118,7 @@ class _InAppWebViewExampleScreenState extends State { key: webViewKey, // contextMenu: contextMenu, initialUrlRequest: - URLRequest(url: Uri.parse("https://github.com/flutter")), + URLRequest(url: Uri.parse("https://flutter.dev/")), // initialFile: "assets/index.html", initialUserScripts: UnmodifiableListView([]), initialOptions: options, @@ -169,6 +169,26 @@ class _InAppWebViewExampleScreenState extends State { this.url = url.toString(); urlController.text = this.url; }); + + CookieManager cookieManager = CookieManager.instance(); + + await cookieManager.setCookie( + url: url!, name: "myCookie", value: "myValue"); + List cookies = await cookieManager.getCookies(url: url); + print(cookies); + + Cookie? cookie = + await cookieManager.getCookie(url: url, name: "myCookie"); + print(cookie); + + await cookieManager.deleteCookie(url: url, name: "myCookie", domain: ".flutter.dev"); + cookie = await cookieManager.getCookie(url: url, name: "myCookie"); + print(cookie); + + await cookieManager.deleteCookies(url: url, domain: ".flutter.dev"); + await Future.delayed(Duration(seconds: 1)); + cookies = await cookieManager.getCookies(url: url); + print(cookies); }, onLoadError: (controller, url, code, message) { pullToRefreshController.endRefreshing(); diff --git a/ios/Classes/MyCookieManager.swift b/ios/Classes/MyCookieManager.swift index 1e13d88f..fe777c6d 100755 --- a/ios/Classes/MyCookieManager.swift +++ b/ios/Classes/MyCookieManager.swift @@ -70,15 +70,15 @@ class MyCookieManager: NSObject, FlutterPlugin { case "deleteCookie": let url = arguments!["url"] as! String let name = arguments!["name"] as! String - let domain = arguments!["domain"] as! String let path = arguments!["path"] as! String - MyCookieManager.deleteCookie(url: url, name: name, domain: domain, path: path, result: result) + let domain = arguments!["domain"] as? String + MyCookieManager.deleteCookie(url: url, name: name, path: path, domain: domain, result: result) break; case "deleteCookies": let url = arguments!["url"] as! String - let domain = arguments!["domain"] as! String let path = arguments!["path"] as! String - MyCookieManager.deleteCookies(url: url, domain: domain, path: path, result: result) + let domain = arguments!["domain"] as? String + MyCookieManager.deleteCookies(url: url, path: path, domain: domain, result: result) break; case "deleteAllCookies": MyCookieManager.deleteAllCookies(result: result) @@ -239,25 +239,30 @@ class MyCookieManager: NSObject, FlutterPlugin { } } - public static func deleteCookie(url: String, name: String, domain: String, path: String, result: @escaping FlutterResult) { + public static func deleteCookie(url: String, name: String, path: String, domain: String?, result: @escaping FlutterResult) { guard let httpCookieStore = MyCookieManager.httpCookieStore else { result(false) return } - + + var domain = domain httpCookieStore.getAllCookies { (cookies) in for cookie in cookies { - var originURL = "" + var originURL = url if cookie.properties![.originURL] is String { originURL = cookie.properties![.originURL] as! String } else if cookie.properties![.originURL] is URL { originURL = (cookie.properties![.originURL] as! URL).absoluteString } - if (!originURL.isEmpty && originURL != url) { - continue + if domain == nil, let domainUrl = URL(string: originURL) { + if #available(iOS 16.0, *) { + domain = domainUrl.host() + } else { + domain = domainUrl.host + } } - if (cookie.domain == domain || cookie.domain == ".\(domain)" || ".\(cookie.domain)" == domain) && cookie.name == name && cookie.path == path { + if let domain = domain, cookie.domain == domain, cookie.name == name, cookie.path == path { httpCookieStore.delete(cookie, completionHandler: { result(true) }) @@ -268,25 +273,30 @@ class MyCookieManager: NSObject, FlutterPlugin { } } - public static func deleteCookies(url: String, domain: String, path: String, result: @escaping FlutterResult) { + public static func deleteCookies(url: String, path: String, domain: String?, result: @escaping FlutterResult) { guard let httpCookieStore = MyCookieManager.httpCookieStore else { result(false) return } + var domain = domain httpCookieStore.getAllCookies { (cookies) in for cookie in cookies { - var originURL = "" + var originURL = url if cookie.properties![.originURL] is String { originURL = cookie.properties![.originURL] as! String } - else if cookie.properties![.originURL] is URL{ + else if cookie.properties![.originURL] is URL { originURL = (cookie.properties![.originURL] as! URL).absoluteString } - if (!originURL.isEmpty && originURL != url) { - continue + if domain == nil, let domainUrl = URL(string: originURL) { + if #available(iOS 16.0, *) { + domain = domainUrl.host() + } else { + domain = domainUrl.host + } } - if (cookie.domain == domain || cookie.domain == ".\(domain)" || ".\(cookie.domain)" == domain) && cookie.path == path { + if let domain = domain, cookie.domain == domain, cookie.path == path { httpCookieStore.delete(cookie, completionHandler: nil) } } diff --git a/lib/src/cookie_manager.dart b/lib/src/cookie_manager.dart index b53aee74..2d5c9536 100755 --- a/lib/src/cookie_manager.dart +++ b/lib/src/cookie_manager.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; @@ -300,7 +299,6 @@ class CookieManager { ///Removes a cookie by its [name] for the given [url], [domain] and [path]. /// ///The default value of [path] is `"/"`. - ///If [domain] is empty, its default value will be the domain name of [url]. /// ///[iosBelow11WebViewController] 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. JavaScript must be enabled in order to work. @@ -311,10 +309,9 @@ class CookieManager { Future deleteCookie( {required Uri url, required String name, - String domain = "", String path = "/", + String? domain, InAppWebViewController? iosBelow11WebViewController}) async { - if (domain.isEmpty) domain = _getDomainName(url); assert(url.toString().isNotEmpty); assert(name.isNotEmpty); @@ -346,7 +343,6 @@ class CookieManager { ///Removes all cookies for the given [url], [domain] and [path]. /// ///The default value of [path] is `"/"`. - ///If [domain] is empty, its default value will be the domain name of [url]. /// ///[iosBelow11WebViewController] 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. JavaScript must be enabled in order to work. @@ -356,10 +352,9 @@ class CookieManager { ///to delete the cookies (session-only cookies and cookies with `isHttpOnly` enabled won't be deleted!). Future deleteCookies( {required Uri url, - String domain = "", String path = "/", + String? domain, InAppWebViewController? iosBelow11WebViewController}) async { - if (domain.isEmpty) domain = _getDomainName(url); assert(url.toString().isNotEmpty); @@ -398,11 +393,6 @@ class CookieManager { await _channel.invokeMethod('deleteAllCookies', args); } - String _getDomainName(Uri url) { - String domain = url.host; - return domain.startsWith("www.") ? domain.substring(4) : domain; - } - Future _getCookieExpirationDate(int expiresDate) async { var platformUtil = PlatformUtil(); var dateTime = DateTime.fromMillisecondsSinceEpoch(expiresDate).toUtc();