diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml new file mode 100644 index 00000000..3b0b4626 --- /dev/null +++ b/.idea/libraries/Dart_Packages.xml @@ -0,0 +1,420 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Flutter_Plugins.xml b/.idea/libraries/Flutter_Plugins.xml index 65bb3679..31799730 100755 --- a/.idea/libraries/Flutter_Plugins.xml +++ b/.idea/libraries/Flutter_Plugins.xml @@ -1,8 +1,6 @@ - - - + diff --git a/CHANGELOG.md b/CHANGELOG.md index ad592cf1..40f8c6b1 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 5.3.1 + +- Added support of `allowingReadAccessTo` iOS-specific WebView option for the WebView `initialData` parameter +- Added `iosAllowingReadAccessTo` iOS-specific parameter to the `loadData` WebView method +- Fixed "iOS webview showing blank page in specific URL" [#776](https://github.com/pichillilorenzo/flutter_inappwebview/issues/776) +- Fixed "unable to access ApplicationDocumentsDirectory in real Ios devices" [#748](https://github.com/pichillilorenzo/flutter_inappwebview/issues/748) + ## 5.3.0+1 - Fixed "Android - Pull to refresh triggered when scrolling container inside a website" [#765](https://github.com/pichillilorenzo/flutter_inappwebview/issues/765) diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies index ede4340f..3280573a 100644 --- 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_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-03-28 04:12:52.120913","version":"2.1.0-10.0.pre"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-04-02 15:03:21.968100","version":"2.1.0-10.0.pre"} \ No newline at end of file diff --git a/example/ios/Flutter/Flutter.podspec b/example/ios/Flutter/Flutter.podspec deleted file mode 100644 index 2c4421cf..00000000 --- a/example/ios/Flutter/Flutter.podspec +++ /dev/null @@ -1,18 +0,0 @@ -# -# NOTE: This podspec is NOT to be published. It is only used as a local source! -# This is a generated file; do not edit or check into version control. -# - -Pod::Spec.new do |s| - s.name = 'Flutter' - s.version = '1.0.0' - s.summary = 'High-performance, high-fidelity mobile apps.' - s.homepage = 'https://flutter.io' - s.license = { :type => 'MIT' } - s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } - s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } - s.ios.deployment_target = '8.0' - # Framework linking is handled by Flutter tooling, not CocoaPods. - # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs. - s.vendored_frameworks = 'path/to/nothing' -end diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index ff713474..c4b5f834 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -2,13 +2,12 @@ # This is a generated file; do not edit or check into version control. export "FLUTTER_ROOT=/Users/lorenzopichilli/fvm/versions/2.1.0-10.0.pre" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example" -export "FLUTTER_TARGET=integration_test/webview_flutter_test.dart" +export "FLUTTER_TARGET=lib/main.dart" export "FLUTTER_BUILD_DIR=build" export "SYMROOT=${SOURCE_ROOT}/../build/ios" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" -export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==" export "DART_OBFUSCATION=false" -export "TRACK_WIDGET_CREATION=true" +export "TRACK_WIDGET_CREATION=false" export "TREE_SHAKE_ICONS=false" -export "PACKAGE_CONFIG=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/.dart_tool/package_config.json" +export "PACKAGE_CONFIG=.packages" diff --git a/flutter_inappwebview.iml b/flutter_inappwebview.iml index 0adae5aa..4cb39159 100755 --- a/flutter_inappwebview.iml +++ b/flutter_inappwebview.iml @@ -80,5 +80,6 @@ + \ No newline at end of file diff --git a/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift b/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift index 21589f01..f806105d 100755 --- a/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift +++ b/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift @@ -157,7 +157,15 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega } } else if let initialData = initialData { - webView.loadData(data: initialData, mimeType: initialMimeType!, encoding: initialEncoding!, baseUrl: initialBaseUrl!) + let baseUrl = URL(string: initialBaseUrl!)! + var allowingReadAccessToURL: URL? = nil + if let allowingReadAccessTo = webView?.options?.allowingReadAccessTo, baseUrl.scheme == "file" { + allowingReadAccessToURL = URL(string: allowingReadAccessTo) + if allowingReadAccessToURL?.scheme != "file" { + allowingReadAccessToURL = nil + } + } + webView.loadData(data: initialData, mimeType: initialMimeType!, encoding: initialEncoding!, baseUrl: baseUrl, allowingReadAccessTo: allowingReadAccessToURL) } else if let initialUrlRequest = initialUrlRequest { var allowingReadAccessToURL: URL? = nil diff --git a/ios/Classes/InAppWebView/FlutterWebViewController.swift b/ios/Classes/InAppWebView/FlutterWebViewController.swift index c2a3dd0b..8f883d2b 100755 --- a/ios/Classes/InAppWebView/FlutterWebViewController.swift +++ b/ios/Classes/InAppWebView/FlutterWebViewController.swift @@ -139,8 +139,15 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView { let data = initialData["data"]! let mimeType = initialData["mimeType"]! let encoding = initialData["encoding"]! - let baseUrl = initialData["baseUrl"]! - webView?.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl) + let baseUrl = URL(string: initialData["baseUrl"]!)! + var allowingReadAccessToURL: URL? = nil + if let allowingReadAccessTo = webView?.options?.allowingReadAccessTo, baseUrl.scheme == "file" { + allowingReadAccessToURL = URL(string: allowingReadAccessTo) + if allowingReadAccessToURL?.scheme != "file" { + allowingReadAccessToURL = nil + } + } + webView?.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl, allowingReadAccessTo: allowingReadAccessToURL) } else if let initialUrlRequest = initialUrlRequest { let urlRequest = URLRequest.init(fromPluginMap: initialUrlRequest) diff --git a/ios/Classes/InAppWebView/InAppWebView.swift b/ios/Classes/InAppWebView/InAppWebView.swift index d28a8904..39ba0cb7 100755 --- a/ios/Classes/InAppWebView/InAppWebView.swift +++ b/ios/Classes/InAppWebView/InAppWebView.swift @@ -769,12 +769,15 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi load(request) } - public func loadData(data: String, mimeType: String, encoding: String, baseUrl: String) { - let url = URL(string: baseUrl)! + public func loadData(data: String, mimeType: String, encoding: String, baseUrl: URL, allowingReadAccessTo: URL?) { + if #available(iOS 9.0, *), let allowingReadAccessTo = allowingReadAccessTo, baseUrl.scheme == "file", allowingReadAccessTo.scheme == "file" { + loadFileURL(baseUrl, allowingReadAccessTo: allowingReadAccessTo) + } + if #available(iOS 9.0, *) { - load(data.data(using: .utf8)!, mimeType: mimeType, characterEncodingName: encoding, baseURL: url) + load(data.data(using: .utf8)!, mimeType: mimeType, characterEncodingName: encoding, baseURL: baseUrl) } else { - loadHTMLString(data, baseURL: url) + loadHTMLString(data, baseURL: baseUrl) } } diff --git a/ios/Classes/InAppWebViewMethodHandler.swift b/ios/Classes/InAppWebViewMethodHandler.swift index ae3d0b60..58092f63 100644 --- a/ios/Classes/InAppWebViewMethodHandler.swift +++ b/ios/Classes/InAppWebViewMethodHandler.swift @@ -51,8 +51,13 @@ public class InAppWebViewMethodHandler: FlutterMethodCallDelegate { let data = arguments!["data"] as! String let mimeType = arguments!["mimeType"] as! String let encoding = arguments!["encoding"] as! String - let baseUrl = arguments!["baseUrl"] as! String - webView?.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl) + let baseUrl = URL(string: arguments!["baseUrl"] as! String)! + let allowingReadAccessTo = arguments!["allowingReadAccessTo"] as? String + var allowingReadAccessToURL: URL? = nil + if let allowingReadAccessTo = allowingReadAccessTo { + allowingReadAccessToURL = URL(string: allowingReadAccessTo) + } + webView?.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl, allowingReadAccessTo: allowingReadAccessToURL) result(true) break case "loadFile": diff --git a/ios/Classes/PluginScriptsJS/ConsoleLogJS.swift b/ios/Classes/PluginScriptsJS/ConsoleLogJS.swift index 9288c188..69a92953 100644 --- a/ios/Classes/PluginScriptsJS/ConsoleLogJS.swift +++ b/ios/Classes/PluginScriptsJS/ConsoleLogJS.swift @@ -32,19 +32,25 @@ let CONSOLE_LOG_JS_SOURCE = """ for (var k in oldLogs) { (function(oldLog) { console[oldLog.replace('console', '').toLowerCase()] = function() { - var message = ''; - for (var i in arguments) { - if (message == '') { - message += arguments[i]; - } - else { - message += ' ' + arguments[i]; - } - } - - var _windowId = \(WINDOW_ID_VARIABLE_JS_SOURCE); - window.webkit.messageHandlers[oldLog].postMessage({'message': message, '_windowId': _windowId}); oldLogs[oldLog].apply(null, arguments); + var args = arguments; + + // on iOS, for some reason, accessing the arguments object synchronously can throw some errors, such as "TypeError" + // see https://github.com/pichillilorenzo/flutter_inappwebview/issues/776 + setTimeout(function() { + var message = ''; + for (var i in args) { + if (message == '') { + message += args[i]; + } + else { + message += ' ' + args[i]; + } + } + + var _windowId = \(WINDOW_ID_VARIABLE_JS_SOURCE); + window.webkit.messageHandlers[oldLog].postMessage({'message': message, '_windowId': _windowId}); + }); } })(k); } diff --git a/lib/src/in_app_webview/in_app_webview_controller.dart b/lib/src/in_app_webview/in_app_webview_controller.dart index 910881ec..4db0084e 100644 --- a/lib/src/in_app_webview/in_app_webview_controller.dart +++ b/lib/src/in_app_webview/in_app_webview_controller.dart @@ -1142,7 +1142,7 @@ class InAppWebViewController { Map args = {}; args.putIfAbsent('urlRequest', () => urlRequest.toMap()); args.putIfAbsent( - 'allowingReadAccessTo', () => iosAllowingReadAccessTo.toString()); + 'allowingReadAccessTo', () => iosAllowingReadAccessTo?.toString()); await _channel.invokeMethod('loadUrl', args); } @@ -1165,11 +1165,14 @@ class InAppWebViewController { ///Loads the given [data] into this WebView, using [baseUrl] as the base URL for the content. /// - ///The [mimeType] parameter specifies the format of the data. The default value is `"text/html"`. - /// - ///The [encoding] parameter specifies the encoding of the data. The default value is `"utf8"`. - /// - ///The [androidHistoryUrl] parameter is the URL to use as the history entry. The default value is `about:blank`. If non-null, this must be a valid URL. This parameter is used only on Android. + ///- [mimeType] parameter specifies the format of the data. The default value is `"text/html"`. + ///- [encoding] parameter specifies the encoding of the data. The default value is `"utf8"`. + ///- [androidHistoryUrl] parameter is the URL to use as the history entry. The default value is `about:blank`. If non-null, this must be a valid URL. This parameter is used only on Android. + ///- [iosAllowingReadAccessTo], used in combination with [baseUrl] (using the `file://` scheme), + ///is an iOS-specific argument that represents the URL from which to read the web content. + ///This [baseUrl] must be a file-based URL (using the `file://` scheme). + ///Specify the same value as the [baseUrl] parameter to prevent WebView from reading any other content. + ///Specify a directory to give WebView permission to read additional files in the specified directory. /// ///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#loadDataWithBaseURL(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String) /// @@ -1181,7 +1184,11 @@ class InAppWebViewController { String mimeType = "text/html", String encoding = "utf8", Uri? baseUrl, - Uri? androidHistoryUrl}) async { + Uri? androidHistoryUrl, + Uri? iosAllowingReadAccessTo}) async { + assert(iosAllowingReadAccessTo == null || + iosAllowingReadAccessTo.isScheme("file")); + Map args = {}; args.putIfAbsent('data', () => data); args.putIfAbsent('mimeType', () => mimeType); @@ -1189,6 +1196,8 @@ class InAppWebViewController { args.putIfAbsent('baseUrl', () => baseUrl?.toString() ?? "about:blank"); args.putIfAbsent( 'historyUrl', () => androidHistoryUrl?.toString() ?? "about:blank"); + args.putIfAbsent( + 'allowingReadAccessTo', () => iosAllowingReadAccessTo?.toString()); await _channel.invokeMethod('loadData', args); } diff --git a/lib/src/in_app_webview/ios/in_app_webview_options.dart b/lib/src/in_app_webview/ios/in_app_webview_options.dart index 74b8c86d..740a2269 100755 --- a/lib/src/in_app_webview/ios/in_app_webview_options.dart +++ b/lib/src/in_app_webview/ios/in_app_webview_options.dart @@ -211,9 +211,10 @@ class IOSInAppWebViewOptions ///**NOTE**: available on iOS 13.0+. bool applePayAPIEnabled; - ///Used in combination with [WebView.initialUrlRequest] (using the `file://` scheme), it represents the URL from which to read the web content. + ///Used in combination with [WebView.initialUrlRequest] or [WebView.initialData] (using the `file://` scheme), it represents the URL from which to read the web content. ///This URL must be a file-based URL (using the `file://` scheme). - ///Specify the same value as the [WebView.initialUrlRequest] parameter to prevent WebView from reading any other content. + ///Specify the same value as the [URLRequest.url] if you are using it with the [WebView.initialUrlRequest] parameter or + ///the [InAppWebViewInitialData.baseUrl] if you are using it with the [WebView.initialData] parameter to prevent WebView from reading any other content. ///Specify a directory to give WebView permission to read additional files in the specified directory. Uri? allowingReadAccessTo; diff --git a/pubspec.yaml b/pubspec.yaml index 16379212..a5ba6c14 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_inappwebview description: A Flutter plugin that allows you to add an inline webview, to use an headless webview, and to open an in-app browser window. -version: 5.3.0+1 +version: 5.3.1 homepage: https://github.com/pichillilorenzo/flutter_inappwebview environment: