From a83dca01eb2a1746829933512451fb0778f9a086 Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Mon, 7 Sep 2020 18:10:26 +0200 Subject: [PATCH] Fixed missing clearHistory webview method implementation on Android, Fixed iOS crash when using CookieManager getCookies for an URL and the host URL is null --- CHANGELOG.md | 2 + .../InAppBrowser/InAppBrowserActivity.java | 9 +++ .../InAppWebView/FlutterWebView.java | 8 ++ example/.flutter-plugins-dependencies | 2 +- example/ios/Podfile | 76 ++++--------------- example/lib/in_app_webiew_example.screen.dart | 1 + ios/Classes/MyCookieManager.swift | 60 ++++++++------- 7 files changed, 70 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d074ac9f..5f3ce978 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ - Fixed "window.flutter_inappwebview.callHandler is not a function" [#218](https://github.com/pichillilorenzo/flutter_inappwebview/issues/218) - Fixed "Android ContentBlocker - java.lang.NullPointerException ContentBlockerTrigger resource type" [#506](https://github.com/pichillilorenzo/flutter_inappwebview/issues/506) - Fixed "Android CookieManager throws error caused by websites that are sending back illegal/invalid cookies." [#476](https://github.com/pichillilorenzo/flutter_inappwebview/issues/476) +- Fixed missing `clearHistory` webview method implementation on Android +- Fixed iOS crash when using CookieManager getCookies for an URL and the host URL is `null` ## 4.0.0+4 diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowser/InAppBrowserActivity.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowser/InAppBrowserActivity.java index 81a4fe18..ca32113b 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowser/InAppBrowserActivity.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowser/InAppBrowserActivity.java @@ -407,6 +407,10 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha case "getCertificate": result.success(getCertificate()); break; + case "clearHistory": + clearHistory(); + result.success(true); + break; default: result.notImplemented(); } @@ -975,6 +979,11 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha return null; } + public void clearHistory() { + if (webView != null) + webView.clearHistory(); + } + public void dispose() { channel.setMethodCallHandler(null); activityResultListeners.clear(); diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java index 76b4797c..912afd67 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/FlutterWebView.java @@ -503,6 +503,14 @@ public class FlutterWebView implements PlatformView, MethodCallHandler { result.success(null); } break; + case "clearHistory": + if (webView != null) { + webView.clearHistory(); + result.success(true); + } else { + result.success(false); + } + break; default: result.notImplemented(); } diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies index a79dfeea..6f9ab3d4 100755 --- a/example/.flutter-plugins-dependencies +++ b/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"android":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+7/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[{"name":"url_launcher_web","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.2/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_inappwebview","dependencies":[]},{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-09-07 12:36:26.957070","version":"1.20.3"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"android":[{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.10/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.11/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+7/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+1/","dependencies":[]}],"windows":[],"web":[{"name":"url_launcher_web","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.2/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_inappwebview","dependencies":[]},{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-09-07 18:06:16.830498","version":"1.20.3"} \ No newline at end of file diff --git a/example/ios/Podfile b/example/ios/Podfile index 6697f0a5..1e8c3c90 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -10,78 +10,32 @@ project 'Runner', { 'Release' => :release, } -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" end - generated_key_values = {} - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) do |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - if plugin.length == 2 - podname = plugin[0].strip() - path = plugin[1].strip() - podpath = File.expand_path("#{path}", file_abs_path) - generated_key_values[podname] = podpath - else - puts "Invalid plugin specification: #{line}" - end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches end - generated_key_values + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" end +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + target 'Runner' do use_frameworks! use_modular_headers! - # Flutter Pod - - copied_flutter_dir = File.join(__dir__, 'Flutter') - copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') - copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') - unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) - # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. - # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. - # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. - - generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') - unless File.exist?(generated_xcode_build_settings_path) - raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) - cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; - - unless File.exist?(copied_framework_path) - FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) - end - unless File.exist?(copied_podspec_path) - FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) - end - end - - # Keep pod path relative so it can be checked into Podfile.lock. - pod 'Flutter', :path => 'Flutter' - - # Plugin Pods - - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - system('rm -rf .symlinks') - system('mkdir -p .symlinks/plugins') - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.each do |name, path| - symlink = File.join('.symlinks', 'plugins', name) - File.symlink(path, symlink) - pod name, :path => File.join(symlink, 'ios') - end + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end post_install do |installer| installer.pods_project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['ENABLE_BITCODE'] = 'NO' - end + flutter_additional_ios_build_settings(target) end end diff --git a/example/lib/in_app_webiew_example.screen.dart b/example/lib/in_app_webiew_example.screen.dart index 1dc03d5d..61bf7898 100755 --- a/example/lib/in_app_webiew_example.screen.dart +++ b/example/lib/in_app_webiew_example.screen.dart @@ -123,6 +123,7 @@ class _InAppWebViewExampleScreenState extends State { return ShouldOverrideUrlLoadingAction.ALLOW; }, onLoadStop: (InAppWebViewController controller, String url) async { + print(CookieManager) print("onLoadStop $url"); setState(() { this.url = url; diff --git a/ios/Classes/MyCookieManager.swift b/ios/Classes/MyCookieManager.swift index 912e51e4..917ee1a4 100755 --- a/ios/Classes/MyCookieManager.swift +++ b/ios/Classes/MyCookieManager.swift @@ -142,37 +142,45 @@ class MyCookieManager: NSObject, FlutterPlugin { public static func getCookies(url: String, result: @escaping FlutterResult) { var cookieList: [[String: Any?]] = [] - MyCookieManager.httpCookieStore!.getAllCookies { (cookies) in - for cookie in cookies { - if cookie.domain.contains(URL(string: url)!.host!) { - var sameSite: String? = nil - if #available(iOS 13.0, *) { - if let sameSiteValue = cookie.sameSitePolicy?.rawValue { - sameSite = sameSiteValue.prefix(1).capitalized + sameSiteValue.dropFirst() + + if let urlHost = URL(string: url)?.host { + MyCookieManager.httpCookieStore!.getAllCookies { (cookies) in + for cookie in cookies { + if cookie.domain.contains(urlHost) { + var sameSite: String? = nil + if #available(iOS 13.0, *) { + if let sameSiteValue = cookie.sameSitePolicy?.rawValue { + sameSite = sameSiteValue.prefix(1).capitalized + sameSiteValue.dropFirst() + } } + + var expiresDateTimestamp: Int64 = -1 + if let expiresDate = cookie.expiresDate?.timeIntervalSince1970 { + // convert to milliseconds + expiresDateTimestamp = Int64(expiresDate * 1000) + } + + cookieList.append([ + "name": cookie.name, + "value": cookie.value, + "expiresDate": expiresDateTimestamp != -1 ? expiresDateTimestamp : nil, + "isSessionOnly": cookie.isSessionOnly, + "domain": cookie.domain, + "sameSite": sameSite, + "isSecure": cookie.isSecure, + "isHttpOnly": cookie.isHTTPOnly, + "path": cookie.path, + ]) } - - var expiresDateTimestamp: Int64 = -1 - if let expiresDate = cookie.expiresDate?.timeIntervalSince1970 { - // convert to milliseconds - expiresDateTimestamp = Int64(expiresDate * 1000) - } - - cookieList.append([ - "name": cookie.name, - "value": cookie.value, - "expiresDate": expiresDateTimestamp != -1 ? expiresDateTimestamp : nil, - "isSessionOnly": cookie.isSessionOnly, - "domain": cookie.domain, - "sameSite": sameSite, - "isSecure": cookie.isSecure, - "isHttpOnly": cookie.isHTTPOnly, - "path": cookie.path, - ]) } + result(cookieList) } - result(cookieList) + return + } else { + print("Cannot get WebView cookies. No HOST found for URL: \(url)") } + + result(cookieList) } public static func deleteCookie(url: String, name: String, domain: String, path: String, result: @escaping FlutterResult) {