fix #225, merged #228, updated ios options naming, updated default value for databaseEnabled android option, added new methods and events

This commit is contained in:
Lorenzo Pichilli 2019-12-16 23:58:10 +01:00
parent 5e272c460f
commit b9fb01f177
58 changed files with 2022 additions and 1019 deletions

View File

@ -16,61 +16,120 @@
</component>
<component name="ChangeListManager">
<list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment="">
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyWebStorage.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyWebStorage.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/FlutterMethodCallDelegate.swift" afterDir="false" />
<change afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/LeakAvoider.swift" afterDir="false" />
<change afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/MyWebStorageManager.swift" afterDir="false" />
<change afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/TestWebView.swift" afterDir="false" />
<change afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/web_storage_manager.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/ios/Classes/FlutterMethodCallDelegate.swift" afterDir="false" />
<change afterPath="$PROJECT_DIR$/ios/Classes/LeakAvoider.swift" afterDir="false" />
<change afterPath="$PROJECT_DIR$/ios/Classes/MyWebStorageManager.swift" afterDir="false" />
<change afterPath="$PROJECT_DIR$/ios/Classes/TestWebView.swift" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/src/web_storage_manager.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CHANGELOG.md" beforeDir="false" afterPath="$PROJECT_DIR$/CHANGELOG.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabaseHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabaseHandler.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/FlutterWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/FlutterWebView.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/FlutterWebViewFactory.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/FlutterWebViewFactory.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowser.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowser.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowserActivity.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowserActivity.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewChromeClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewChromeClient.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewOptions.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewOptions.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewFlutterPlugin.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewFlutterPlugin.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewStatic.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewStatic.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Shared.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Shared.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Util.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Util.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/android/app/src/main/AndroidManifest.xml" beforeDir="false" afterPath="$PROJECT_DIR$/example/android/app/src/main/AndroidManifest.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/assets/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/example/assets/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/CHANGELOG.md" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/CHANGELOG.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabaseHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/CredentialDatabaseHandler.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/FlutterWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/FlutterWebView.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/FlutterWebViewFactory.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/FlutterWebViewFactory.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowser.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowser.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowserActivity.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppBrowserActivity.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebView.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewChromeClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewChromeClient.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewOptions.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewOptions.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewFlutterPlugin.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewFlutterPlugin.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewStatic.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewStatic.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/JavaScriptBridgeInterface.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/MyCookieManager.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Shared.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Shared.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Util.java" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Util.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/assets/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/assets/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/lib/main.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/lib/main.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/app_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/app_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/lib/chrome_safari_browser_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/lib/chrome_safari_browser_example.screen.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/lib/in_app_browser_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/lib/in_app_browser_example.screen.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/lib/in_app_webiew_example.screen.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_ajax_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_ajax_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_content_blocker_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_content_blocker_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_cookie_manager_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_cookie_manager_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_fetch_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_fetch_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_http_auth_credential_database_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_http_auth_credential_database_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_initial_data_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_initial_data_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_initial_file_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_initial_file_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_initial_url_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_initial_url_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_javascript_handler_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_javascript_handler_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_console_message_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_console_message_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_create_window_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_create_window_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_download_start_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_download_start_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_find_result_received_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_find_result_received_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_js_dialog_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_js_dialog_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_load_error_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_load_error_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_load_http_error_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_load_http_error_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_load_resource_custom_scheme_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_load_resource_custom_scheme_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_load_resource_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_load_resource_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_navigation_state_change_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_navigation_state_change_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_progress_changed_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_progress_changed_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_received_http_auth_request_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_received_http_auth_request_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_safe_browsing_hit_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_safe_browsing_hit_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_scroll_changed_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_on_scroll_changed_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_should_override_url_loading_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_should_override_url_loading_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_ssl_request_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/test_driver/in_app_webview_ssl_request_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/flutter_inappwebview.iml" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/flutter_inappwebview.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/FlutterWebViewController.swift" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/FlutterWebViewController.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/InAppBrowserWebViewController.swift" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/InAppBrowserWebViewController.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/InAppWebView.swift" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/InAppWebView.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/InAppWebViewOptions.swift" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/InAppWebViewOptions.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/SwiftFlutterPlugin.swift" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/ios/Classes/SwiftFlutterPlugin.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/flutter_inappwebview.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/flutter_inappwebview.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/chrome_safari_browser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/chrome_safari_browser.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/in_app_browser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/in_app_browser.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/in_app_webview.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/in_app_webview.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/types.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/types.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/webview_options.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/lib/src/webview_options.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/nodejs_server_test_auth_basic_and_ssl/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/nodejs_server_test_auth_basic_and_ssl/index.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/nodejs_server_test_auth_basic_and_ssl/public/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/nodejs_server_test_auth_basic_and_ssl/public/test-index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/pubspec.yaml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/test.sh" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/test.sh" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/lib/main.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/main.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/app_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/app_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/lib/chrome_safari_browser_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/chrome_safari_browser_example.screen.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/lib/in_app_browser_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/in_app_browser_example.screen.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_ajax_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_ajax_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_content_blocker_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_content_blocker_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_cookie_manager_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_cookie_manager_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_fetch_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_fetch_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_http_auth_credential_database_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_http_auth_credential_database_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_initial_data_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_initial_data_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_initial_file_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_initial_file_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_initial_url_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_initial_url_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_javascript_handler_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_javascript_handler_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_console_message_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_console_message_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_create_window_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_create_window_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_download_start_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_download_start_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_find_result_received_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_find_result_received_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_js_dialog_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_js_dialog_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_error_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_error_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_http_error_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_http_error_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_resource_custom_scheme_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_resource_custom_scheme_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_resource_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_resource_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_navigation_state_change_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_navigation_state_change_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_progress_changed_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_progress_changed_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_received_http_auth_request_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_received_http_auth_request_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_safe_browsing_hit_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_safe_browsing_hit_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_scroll_changed_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_on_scroll_changed_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_should_override_url_loading_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_should_override_url_loading_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/test_driver/in_app_webview_ssl_request_test.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/test_driver/in_app_webview_ssl_request_test.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/flutter_inappwebview.iml" beforeDir="false" afterPath="$PROJECT_DIR$/flutter_inappwebview.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/FlutterWebViewController.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/FlutterWebViewController.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppWebViewOptions.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppWebViewOptions.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/flutter_inappwebview.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/flutter_inappwebview.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/src/chrome_safari_browser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/chrome_safari_browser.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/src/in_app_browser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/in_app_browser.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/src/in_app_webview.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/in_app_webview.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/src/types.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/types.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/src/webview_options.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/webview_options.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/public/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/public/test-index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pubspec.yaml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/test.sh" beforeDir="false" afterPath="$PROJECT_DIR$/test.sh" afterDir="false" />
</list>
<ignored path="$PROJECT_DIR$/.dart_tool/" />
<ignored path="$PROJECT_DIR$/.idea/" />
@ -91,43 +150,10 @@
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<entry file="file://$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="445">
<caret line="78" column="1" selection-start-line="78" selection-start-column="1" selection-end-line="78" selection-end-column="1" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="212">
<caret line="23" column="17" lean-forward="true" selection-start-line="23" selection-start-column="17" selection-end-line="23" selection-end-column="17" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="211">
<caret line="440" selection-start-line="440" selection-end-line="440" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_received_http_auth_request_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="399">
<caret line="54" column="29" selection-start-line="54" selection-start-column="29" selection-end-line="54" selection-end-column="29" />
<state relative-caret-position="90">
<caret line="72" column="25" lean-forward="true" selection-start-line="72" selection-start-column="25" selection-end-line="95" selection-end-column="25" />
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
@ -136,10 +162,34 @@
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/test_driver/main_test.dart">
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="264">
<caret line="48" column="91" selection-start-line="48" selection-start-column="91" selection-end-line="48" selection-end-column="91" />
<state relative-caret-position="304">
<caret line="621" column="48" selection-start-line="621" selection-start-column="7" selection-end-line="621" selection-end-column="48" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="356">
<caret line="1860" column="69" lean-forward="true" selection-start-line="1860" selection-start-column="5" selection-end-line="1860" selection-end-column="69" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/web_storage_manager.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="454">
<caret line="138" column="93" lean-forward="true" selection-start-line="138" selection-start-column="5" selection-end-line="138" selection-end-column="93" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
@ -148,19 +198,48 @@
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/test_driver/app_test.dart">
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="554">
<caret line="360" column="33" selection-start-line="360" selection-start-column="33" selection-end-line="360" selection-end-column="33" />
<state relative-caret-position="299">
<caret line="73" column="29" selection-start-line="73" selection-start-column="26" selection-end-line="73" selection-end-column="29" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_ssl_request_test.dart">
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="367">
<caret line="52" column="22" selection-start-line="50" selection-start-column="20" selection-end-line="52" selection-end-column="22" />
<state relative-caret-position="577">
<caret line="2097" column="3" selection-start-line="2097" selection-start-column="3" selection-end-line="2097" selection-end-column="3" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="224">
<caret line="15" column="68" selection-start-line="15" selection-start-column="53" selection-end-line="15" selection-end-column="68" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="397" column="110" selection-start-line="397" selection-start-column="110" selection-end-line="397" selection-end-column="110" />
<folding>
<element signature="e#0#20#0" expanded="true" />
<element signature="e#0#39#0" expanded="true" />
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
@ -177,36 +256,36 @@
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>Events</find>
<find>OnCreateWindow</find>
<find>onGeolocationPermissions</find>
<find>androidOn</find>
<find>ios</find>
<find>iosWl</find>
<find>onPrint</find>
<find>ontARGET</find>
<find>onCreateWindow</find>
<find>javaScriptHandlerForbiddenNames</find>
<find>ajaxRequest</find>
<find>onTarget</find>
<find>AjaxR</find>
<find>print</find>
<find>shouldOver</find>
<find>ShouldOverrideUrlLoadingAction</find>
<find>headers</find>
<find>domStorageEnabled</find>
<find>fromValue</find>
<find>shouldOv</find>
<find>shouldOverrideUrlLoading</find>
<find>supportMultipleWindows</find>
<find>ThreadedInputConnection</find>
<find>ThreadedInputConnecti</find>
<find>InputAwareWebView</find>
<find>\n</find>
<find>debuggingEnabled</find>
<find>_inappweb</find>
<find>\n&quot; +</find>
<find>This workaround is applied as soon as the web page fires the `DOMContentLoaded` JavaScript event.</find>
<find>dispose</find>
<find>InAppWebViewOnCreateWindowTest</find>
<find>InAppWebViewOnTarget</find>
<find>InAppWebViewOnReceivedHttpAuthRequestTest</find>
<find>dropDownWorkaroundEnabled</find>
<find>mContext</find>
<find>androidhistor</find>
<find>InAppWebViewWidgetOptions</find>
<find>allowsInlineMediaPlayback</find>
<find>onnav</find>
<find>onUpdateVisitedhi</find>
<find>NavigationStateChange</find>
<find>getUrl</find>
<find>databaseA</find>
<find>AndroidInAppWebViewController</find>
<find>Ios</find>
<find>**NOTE</find>
<find>available on ios</find>
<find>final String _value;</find>
<find>&quot;WKWebsiteDataTypeIndexedDBDatabases&quot;</find>
<find>CookieMan</find>
<find>CookieManager</find>
<find>IOS</find>
<find>automaticallyAdjustsScrollIndicatorInsets</find>
<find>assert</find>
<find>Android-specific methods</find>
<find>getScale</find>
<find>onUpdateVisitedHistory</find>
</findStrings>
<replaceStrings>
<replace>activity.getPreferences(0)</replace>
@ -230,8 +309,6 @@
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_console_message_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_download_start_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_find_result_received_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_js_dialog_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_http_error_test.dart" />
@ -239,7 +316,6 @@
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_resource_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_navigation_state_change_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_progress_changed_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_safe_browsing_hit_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_scroll_changed_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_target_blank_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_ssl_request_test.dart" />
@ -260,31 +336,34 @@
<option value="$PROJECT_DIR$/android/src/main/res/values/styles.xml" />
<option value="$PROJECT_DIR$/example/assets/css/style.css" />
<option value="$PROJECT_DIR$/example/test_assets/in_app_webview_on_create_window_test.html" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_create_window_test.dart" />
<option value="$PROJECT_DIR$/example/assets/js/main.js" />
<option value="$PROJECT_DIR$/lib/src/types.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_should_override_url_loading_test.dart" />
<option value="$PROJECT_DIR$/example/lib/in_app_browser_example.screen.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
<option value="$PROJECT_DIR$/example/pubspec.yaml" />
<option value="$PROJECT_DIR$/example/android/app/src/main/AndroidManifest.xml" />
<option value="$PROJECT_DIR$/pubspec.yaml" />
<option value="$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart" />
<option value="$PROJECT_DIR$/README.md" />
<option value="$PROJECT_DIR$/CHANGELOG.md" />
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
<option value="$PROJECT_DIR$/test.sh" />
<option value="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_received_http_auth_request_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/main_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/app_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_safe_browsing_hit_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_create_window_test.dart" />
<option value="$PROJECT_DIR$/example/lib/main.dart" />
<option value="$PROJECT_DIR$/example/assets/index.html" />
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
<option value="$PROJECT_DIR$/lib/flutter_inappwebview.dart" />
<option value="$PROJECT_DIR$/lib/src/types.dart" />
<option value="$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart" />
<option value="$PROJECT_DIR$/CHANGELOG.md" />
<option value="$PROJECT_DIR$/lib/src/web_storage_manager.dart" />
<option value="$PROJECT_DIR$/README.md" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<component name="ProjectFrameBounds">
<option name="x" value="-1" />
<option name="y" value="23" />
<option name="width" value="1920" />
@ -297,17 +376,6 @@
</navigator>
<panes>
<pane id="PackagesPane" />
<pane id="Scope">
<subPane subId="Project Files">
<expand>
<path>
<item name="Root" type="cbb8eebc:String" user="Root" />
<item name="flutter_inappbrowser" type="cbb8eebc:String" user="flutter_inappbrowser" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="ProjectPane">
<subPane>
<expand>
@ -318,20 +386,14 @@
<path>
<item name="flutter_inappwebview" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappwebview" type="462c0819:PsiDirectoryNode" />
<item name="example" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappwebview" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappwebview" type="462c0819:PsiDirectoryNode" />
<item name="example" type="462c0819:PsiDirectoryNode" />
<item name="assets" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappwebview" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappwebview" type="462c0819:PsiDirectoryNode" />
<item name="example" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappwebview" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappwebview" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
@ -365,6 +427,17 @@
<select />
</subPane>
</pane>
<pane id="Scope">
<subPane subId="Project Files">
<expand>
<path>
<item name="Root" type="cbb8eebc:String" user="Root" />
<item name="flutter_inappbrowser" type="cbb8eebc:String" user="flutter_inappbrowser" />
</path>
</expand>
<select />
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
@ -517,7 +590,7 @@
<frame x="-1" y="23" width="1920" height="1057" extended-state="6" />
<editor active="true" />
<layout>
<window_info active="true" content_ui="combo" id="Project" order="0" sideWeight="0.6177474" visible="true" weight="0.22523962" />
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.6177474" visible="true" weight="0.22523962" />
<window_info id="Structure" order="1" sideWeight="0.38225257" side_tool="true" weight="0.2087327" />
<window_info id="Designer" order="2" />
<window_info id="Build Variants" order="3" side_tool="true" />
@ -528,18 +601,18 @@
<window_info id="Resources Explorer" order="8" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" weight="0.32642487" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49478307" weight="0.38445595" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49478307" weight="0.3388601" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.34196892" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" weight="0.3284974" />
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.50532484" side_tool="true" weight="0.35751295" />
<window_info anchor="bottom" id="Version Control" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" sideWeight="0.4946752" weight="0.32435232" />
<window_info anchor="bottom" id="Version Control" order="9" weight="0.32953367" />
<window_info active="true" anchor="bottom" id="Terminal" order="10" sideWeight="0.4946752" visible="true" weight="0.32435232" />
<window_info anchor="bottom" id="Messages" order="11" sideWeight="0.4968051" weight="0.33782384" />
<window_info anchor="bottom" id="Dependency Viewer" order="12" weight="0.32800853" />
<window_info anchor="bottom" id="Logcat" order="13" visible="true" weight="0.41968912" />
<window_info anchor="bottom" id="Logcat" order="13" weight="0.41968912" />
<window_info anchor="bottom" id="Dart Analysis" order="14" weight="0.3253886" />
<window_info anchor="bottom" id="Flutter Performance" order="15" side_tool="true" />
<window_info anchor="bottom" id="Build" order="16" />
@ -567,43 +640,6 @@
</ignored-roots>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/.git/description">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/.git/config">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="13" lean-forward="true" selection-start-line="13" selection-end-line="13" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_error_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="357">
<caret line="27" column="33" selection-start-line="27" selection-start-column="33" selection-end-line="27" selection-end-column="33" />
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.5+6/lib/connectivity.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="75">
<caret line="11" column="5" selection-start-line="11" selection-start-column="5" selection-end-line="11" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_initial_file_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="96">
<caret line="28" column="85" selection-start-line="28" selection-start-column="20" selection-end-line="28" selection-end-column="85" />
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/channel_manager.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
@ -614,16 +650,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/flutter_inappwebview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="21" column="29" lean-forward="true" selection-start-line="21" selection-start-column="29" selection-end-line="21" selection-end-column="29" />
<folding>
<element signature="e#0#1252#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/README.md">
<provider selected="true" editor-type-id="text-editor" />
</entry>
@ -634,16 +660,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_localhost_server.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="13" column="2" selection-start-line="13" selection-start-column="2" selection-end-line="13" selection-end-column="2" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/public/css/style.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
@ -693,15 +709,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/chrome_safari_browser_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/android/src/main/res/layout/chrome_custom_tabs_layout.xml">
<provider selected="true" editor-type-id="text-editor" />
</entry>
@ -715,16 +722,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/cookie_manager.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="203">
<caret line="38" column="10" selection-start-line="38" selection-start-column="10" selection-end-line="38" selection-end-column="10" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/assets/css/style.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="215">
@ -798,66 +795,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/in_app_browser_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="465">
<caret line="36" column="3" selection-start-line="36" selection-start-column="3" selection-end-line="36" selection-end-column="3" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="15">
<caret line="35" column="14" selection-start-line="35" selection-start-column="14" selection-end-line="112" selection-end-column="16" />
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="491">
<caret line="2026" column="38" selection-start-line="2026" selection-start-column="38" selection-end-line="2026" selection-end-column="38" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-3314">
<caret line="315" column="50" selection-start-line="315" selection-start-column="50" selection-end-line="315" selection-end-column="50" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_create_window_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="160">
<caret line="15" column="54" selection-start-line="15" selection-start-column="24" selection-end-line="15" selection-end-column="54" />
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="330">
<caret line="552" column="81" selection-start-line="552" selection-start-column="81" selection-end-line="552" selection-end-column="81" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/test.sh">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45">
@ -872,34 +809,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/main_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="264">
<caret line="48" column="91" selection-start-line="48" selection-start-column="91" selection-end-line="48" selection-end-column="91" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="165">
<caret line="11" column="73" selection-start-line="11" selection-start-column="73" selection-end-line="11" selection-end-column="73" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="149">
<caret line="413" column="267" selection-start-line="413" selection-start-column="267" selection-end-line="413" selection-end-column="267" />
<folding>
<element signature="e#0#39#0" expanded="true" />
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/app_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="554">
@ -914,16 +823,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="211">
<caret line="440" selection-start-line="440" selection-end-line="440" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="531">
@ -931,6 +830,16 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/main_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="264">
<caret line="48" column="91" selection-start-line="48" selection-start-column="91" selection-end-line="48" selection-end-column="91" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_received_http_auth_request_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="399">
@ -941,9 +850,68 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_safe_browsing_hit_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="630">
<caret line="42" column="26" lean-forward="true" selection-start-line="42" selection-start-column="26" selection-end-line="42" selection-end-column="26" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/in_app_browser_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-155">
<caret line="36" column="3" selection-start-line="36" selection-start-column="3" selection-end-line="36" selection-end-column="3" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/chrome_safari_browser_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/ios/ServiceDefinitions.json">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_create_window_test.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="285">
<caret line="46" column="44" lean-forward="true" selection-start-line="46" selection-start-column="44" selection-end-line="46" selection-end-column="44" />
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_localhost_server.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="135">
<caret line="13" column="2" selection-start-line="13" selection-start-column="2" selection-end-line="13" selection-end-column="2" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_assets/in_app_webview_on_navigation_state_change_test.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="345">
<caret line="23" column="17" selection-start-line="11" selection-start-column="8" selection-end-line="23" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="445">
<state relative-caret-position="1065">
<caret line="78" column="1" selection-start-line="78" selection-start-column="1" selection-end-line="78" selection-end-column="1" />
<folding>
<element signature="e#0#20#0" expanded="true" />
@ -951,10 +919,116 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/cookie_manager.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="375">
<caret line="25" selection-end-line="153" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="212">
<caret line="23" column="17" lean-forward="true" selection-start-line="23" selection-start-column="17" selection-end-line="23" selection-end-column="17" />
<state relative-caret-position="585">
<caret line="39" column="38" selection-start-line="39" selection-start-column="38" selection-end-line="39" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/flutter_inappwebview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="510">
<caret line="34" column="36" selection-start-line="34" selection-start-column="36" selection-end-line="34" selection-end-column="36" />
<folding>
<element signature="e#0#1252#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/flutter/bin/cache/pkg/sky_engine/lib/core/date_time.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="313">
<caret line="715" column="19" selection-start-line="715" selection-start-column="19" selection-end-line="715" selection-end-column="19" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="577">
<caret line="2097" column="3" selection-start-line="2097" selection-start-column="3" selection-end-line="2097" selection-end-column="3" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="299">
<caret line="73" column="29" selection-start-line="73" selection-start-column="26" selection-end-line="73" selection-end-column="29" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="304">
<caret line="621" column="48" selection-start-line="621" selection-start-column="7" selection-end-line="621" selection-end-column="48" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90">
<caret line="72" column="25" lean-forward="true" selection-start-line="72" selection-start-column="25" selection-end-line="95" selection-end-column="25" />
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/web_storage_manager.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="454">
<caret line="138" column="93" lean-forward="true" selection-start-line="138" selection-start-column="5" selection-end-line="138" selection-end-column="93" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="356">
<caret line="1860" column="69" lean-forward="true" selection-start-line="1860" selection-start-column="5" selection-end-line="1860" selection-end-column="69" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="224">
<caret line="15" column="68" selection-start-line="15" selection-start-column="53" selection-end-line="15" selection-end-column="68" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="397" column="110" selection-start-line="397" selection-start-column="110" selection-end-line="397" selection-end-column="110" />
<folding>
<element signature="e#0#20#0" expanded="true" />
<element signature="e#0#39#0" expanded="true" />
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>

View File

@ -1,18 +1,24 @@
## 3.0.0
- Updated for Flutter 1.12 new Java Embedding API (Android)
- Updated `clearCache` for Android
- Added `Promise` javascript [polyfill](https://github.com/taylorhakes/promise-polyfill/blob/master/src/index.js) for webviews that doesn't support it for `window.flutter_inappwebview.callHandler`
- Added `getDefaultUserAgent` static method to `InAppWebViewController`
- Added `printCurrentPage` method to `InAppWebViewController`
- Added `onPrint` event
- Added `onUpdateVisitedHistory`, `onPrint` event
- Added `onGeolocationPermissionsHidePrompt` event for Android
- Added `supportMultipleWindows` webview option for Android
- Added `regexToCancelSubFramesLoading` webview option for Android to cancel subframe requests on `shouldOverrideUrlLoading` event based on a Regular Expression
- Updated default value for `domStorageEnabled` option to `true` for Android
- Fix for Android `InAppBrowser` for some controller methods not exposed.
- Added `getContentHeight`, `zoomBy`, `printCurrentPage`, `getScale` methods
- Added `getOriginalUrl` webview method for Android
- Added `reloadFromOrigin` webview method for iOS
- Added `automaticallyAdjustsScrollIndicatorInsets` webview options for iOS
- Added `WebStorageManager` class which manages the web storage used by WebView instances
- Updated for Flutter 1.12 new Java Embedding API (Android)
- Updated `clearCache` for Android
- Updated default value for `domStorageEnabled` and `databaseEnabled` options to `true` for Android
- Merge "Fixes null error when calling getOptions for InAppBrowser class" [#214](https://github.com/pichillilorenzo/flutter_inappwebview/pull/214) (thanks to [panndoraBoo](https://github.com/panndoraBoo))
- Added `dropDownWorkaroundEnabled` webview option for Android to enable a temporary workaround for html dropdowns (issue [#182](https://github.com/pichillilorenzo/flutter_inappwebview/issues/182))
- Merge "Fixes crash onConsoleMessage iOS forced unwrapping" [#228](https://github.com/pichillilorenzo/flutter_inappwebview/pull/228) (thanks to [tokonu](https://github.com/tokonu))
- Fix for Android and iOS `InAppBrowser` for some controller methods not exposed.
- Fixed "App Crashes after clicking on dropdown (Using inappwebview)" [#182](https://github.com/pichillilorenzo/flutter_inappwebview/issues/182)
- Fixed "webview can not be released when in ios" [#225](https://github.com/pichillilorenzo/flutter_inappwebview/issues/225). Now the iOS WebView is released from memory when it is disposed from Flutter.
### BREAKING CHANGES
@ -21,6 +27,14 @@
- it has a return type `ShouldOverrideUrlLoadingAction` to allow or cancel navigation instead of cancel every time the request
- Renamed `onTargetBlank` to `onCreateWindow`
- Deleted `useOnTargetBlank` webview option
- Making methods available only for the specific platform more explicit: moved all the webview's controller methods for Android inside `controller.android` and all the webview's controller methods for iOS inside `controller.ios`
- Making events available only for the specific platform more explicit:
- Renamed `onSafeBrowsingHit` to `androidOnSafeBrowsingHit`
- Renamed `onGeolocationPermissionsShowPrompt` to `androidOnGeolocationPermissionsShowPrompt`
- Renamed `onPermissionRequest` to `androidOnPermissionRequest`
- Updated attribute names for `InAppWebViewWidgetOptions`, `InAppBrowserClassOptions` and `ChromeSafariBrowserClassOptions` classes
- Renamed and updated `onNavigationStateChange` to `onUpdateVisitedHistory`
- Renamed all iOS options prefix from `Ios` to `IOS`
## 2.1.0+1

View File

@ -73,6 +73,7 @@ Classes:
- [InAppLocalhostServer](#inapplocalhostserver-class): This class allows you to create a simple server on `http://localhost:[port]/`. The default `port` value is `8080`.
- [CookieManager](#cookiemanager-class): This class implements a singleton object (shared instance) which manages the cookies used by WebView instances. **NOTE for iOS**: available from iOS 11.0+.
- [HttpAuthCredentialDatabase](#httpauthcredentialdatabase-class): This class implements a singleton object (shared instance) which manages the shared HTTP auth credentials cache.
- [WebStorageManager](#webstoragemanager-class): This class implements a singleton object (shared instance) which manages the web storage used by WebView instances.
## API Reference
@ -176,7 +177,7 @@ class _MyAppState extends State<MyApp> {
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
)
),
@ -248,6 +249,8 @@ Screenshots:
#### `InAppWebViewController` Methods
##### `InAppWebViewController` Cross-platform methods
* `getUrl`: Gets the URL for the current page.
* `getTitle`: Gets the title for the current page.
* `getProgress`: Gets the progress for the current page. The progress value is between 0 and 100.
@ -255,7 +258,7 @@ Screenshots:
* `getFavicons`: Gets the list of all favicons for the current page.
* `loadUrl({@required String url, Map<String, String> headers = const {}})`: Loads the given url with optional headers specified as a map from name to value.
* `postUrl({@required String url, @required Uint8List postData})`: Loads the given url with postData using `POST` method into this WebView.
* `loadData({@required String data, String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", String historyUrl = "about:blank"})`: Loads the given data into this WebView.
* `loadData({@required String data, String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", String androidHistoryUrl = "about:blank"})`: Loads the given data into this WebView.
* `loadFile({@required String assetFilePath, Map<String, String> headers = const {}})`: Loads the given `assetFilePath` with optional headers specified as a map from name to value.
* `reload`: Reloads the WebView.
* `goBack`: Goes back in the history of the WebView.
@ -279,12 +282,7 @@ Screenshots:
* `setOptions({@required InAppWebViewWidgetOptions options})`: Sets the WebView options with the new options and evaluates them.
* `getOptions`: Gets the current WebView options. Returns the options with `null` value if they are not set yet.
* `getCopyBackForwardList`: Gets the `WebHistory` for this WebView. This contains the back/forward list for use in querying each item in the history stack.
* `startSafeBrowsing`: Starts Safe Browsing initialization (available only on Android).
* `setSafeBrowsingWhitelist({@required List<String> hosts})`: Sets the list of hosts (domain names/IP addresses) that are exempt from SafeBrowsing checks. The list is global for all the WebViews (available only on Android).
* `getSafeBrowsingPrivacyPolicyUrl`: Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`.
* `clearCache`: Clears all the webview's cache.
* `clearSslPreferences`: Clears the SSL preferences table stored in response to proceeding with SSL certificate errors (available only on Android).
* `clearClientCertPreferences`: Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests (available only on Android).
* `findAllAsync({@required String find})`: Finds all instances of find on the page and highlights them. Notifies `onFindResultReceived` listener.
* `findNext({@required bool forward})`: Highlights and scrolls to the next match found by `findAllAsync()`. Notifies `onFindResultReceived` listener.
* `clearMatches`: Clears the highlighting surrounding text matches created by `findAllAsync()`.
@ -292,9 +290,31 @@ Screenshots:
* `getTRexRunnerCss`: Gets the css of the Chromium's t-rex runner game. Used in combination with `getTRexRunnerHtml()`.
* `scrollTo({@required int x, @required int y})`: Scrolls the WebView to the position.
* `scrollBy({@required int x, @required int y})`: Moves the scrolled position of the WebView.
* `pauseTimers`: On Android, it pauses all layout, parsing, and JavaScript timers for all WebViews. This is a global requests, not restricted to just this WebView. This can be useful if the application has been paused. On iOS, it is restricted to just this WebView.
* `resumeTimers`: On Android, it resumes all layout, parsing, and JavaScript timers for all WebViews. This will resume dispatching all timers. On iOS, it resumes all layout, parsing, and JavaScript timers to just this WebView.
* `printCurrentPage`: Prints the current page.
* `getScale`: Gets the current scale of this WebView.
* `static getDefaultUserAgent`: Gets the default user agent.
##### `InAppWebViewController` Android-specific methods
Android-specific methods can be called using the `InAppWebViewController.android` attribute.
* `startSafeBrowsing`: Starts Safe Browsing initialization.
* `setSafeBrowsingWhitelist({@required List<String> hosts})`: Sets the list of hosts (domain names/IP addresses) that are exempt from SafeBrowsing checks. The list is global for all the WebViews.
* `getSafeBrowsingPrivacyPolicyUrl`: Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`.
* `clearSslPreferences`: Clears the SSL preferences table stored in response to proceeding with SSL certificate errors.
* `clearClientCertPreferences`: Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests.
* `pause`: Does a best-effort attempt to pause any processing that can be paused safely, such as animations and geolocation. Note that this call does not pause JavaScript.
* `resume`: Resumes a WebView after a previous call to `pause()`.
* `getOriginalUrl`: Gets the URL that was originally requested for the current page.
##### `InAppWebViewController` iOS-specific methods
iOS-specific methods can be called using the `InAppWebViewController.ios` attribute.
* `reloadFromOrigin`: Reloads the current page, performing end-to-end revalidation using cache-validating conditionals if possible.
##### About the JavaScript handler
The Android implementation uses [addJavascriptInterface](https://developer.android.com/reference/android/webkit/WebView#addJavascriptInterface(java.lang.Object,%20java.lang.String)).
@ -375,7 +395,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `builtInZoomControls`: Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `false`.
* `displayZoomControls`: Set to `true` if the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. The default value is `false`.
* `supportZoom`: Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`.
* `databaseEnabled`: Set to `true` if you want the database storage API is enabled. The default value is `false`.
* `databaseEnabled`: Set to `true` if you want the database storage API is enabled. The default value is `true`.
* `domStorageEnabled`: Set to `true` if you want the DOM storage API is enabled. The default value is `true`.
* `useWideViewPort`: Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport.
* `safeBrowsingEnabled`: Sets whether Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links.
@ -431,6 +451,8 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
#### `InAppWebView` Events
Event names that starts with `android` or `ios` are events platform-specific.
* `onWebViewCreated`: Event fired when the InAppWebView is created.
* `onLoadStart`: Event fired when the InAppWebView starts to load an url.
* `onLoadStop`: Event fired when the InAppWebView finishes loading an url.
@ -439,17 +461,15 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `onProgressChanged`: Event fired when the current progress of loading a page is changed.
* `onConsoleMessage`: Event fired when the InAppWebView receives a ConsoleMessage.
* `shouldOverrideUrlLoading`: Give the host application a chance to take control when a URL is about to be loaded in the current WebView (to use this event, the `useShouldOverrideUrlLoading` option must be `true`). This event is not called on the initial load of the WebView.
* `onNavigationStateChange`: Event fired when the navigation state of the InAppWebView changes, for example through the usage of the javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions.
* `onUpdateVisitedHistory`: Event fired when the host application updates its visited links database. This event is also fired when the navigation state of the InAppWebView changes, for example through the usage of the javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions.
* `onLoadResource`: Event fired when the InAppWebView loads a resource (to use this event, the `useOnLoadResource` option must be `true`).
* `onScrollChanged`: Event fired when the InAppWebView scrolls.
* `onDownloadStart`: Event fired when InAppWebView recognizes and starts a downloadable file (to use this event, the `useOnDownloadStart` option must be `true`).
* `onLoadResourceCustomScheme`: Event fired when the InAppWebView finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a CustomSchemeResponse to load a specific resource encoded to `base64`.
* `onCreateWindow`: Event fired when the InAppWebView requests the host application to create a new window, for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
* `onGeolocationPermissionsShowPrompt`: Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin (available only on Android).
* `onJsAlert`: Event fired when javascript calls the `alert()` method to display an alert dialog.
* `onJsConfirm`: Event fired when javascript calls the `confirm()` method to display a confirm dialog.
* `onJsPrompt`: Event fired when javascript calls the `prompt()` method to display a prompt dialog.
* `onSafeBrowsingHit`: Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing (available only on Android).
* `onReceivedHttpAuthRequest`: Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
* `onReceivedServerTrustAuthRequest`: Event fired when the WebView need to perform server trust authentication (certificate validation).
* `onReceivedClientCertRequest`: Notify the host application to handle an SSL client certificate request.
@ -458,8 +478,11 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `onAjaxReadyStateChange`: Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes (to use this event, the `useShouldInterceptAjaxRequest` option must be `true`).
* `onAjaxProgress`: Event fired as an `XMLHttpRequest` progress (to use this event, the `useShouldInterceptAjaxRequest` option must be `true`).
* `shouldInterceptFetchRequest`: Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API) (to use this event, the `useShouldInterceptFetchRequest` option must be `true`).
* `onPermissionRequest`: Event fired when the webview is requesting permission to access the specified resources and the permission currently isn't granted or denied (available only on Android).
* `onPrint`: Event fired when `window.print()` is called from JavaScript side.
* `androidOnSafeBrowsingHit`: Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing (available only on Android).
* `androidOnPermissionRequest`: Event fired when the webview is requesting permission to access the specified resources and the permission currently isn't granted or denied (available only on Android).
* `androidOnGeolocationPermissionsShowPrompt`: Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin (available only on Android).
* `androidOnGeolocationPermissionsHidePrompt`: Notify the host application that a request for Geolocation permissions, made with a previous call to `androidOnGeolocationPermissionsShowPrompt` has been canceled. (available only on Android).
### `InAppBrowser` class
@ -556,7 +579,7 @@ class _MyAppState extends State<MyApp> {
assetFilePath: "assets/index.html",
options: InAppBrowserClassOptions(
inAppWebViewWidgetOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
useOnLoadResource: true,
))));
@ -714,8 +737,8 @@ class _MyAppState extends State<MyApp> {
await widget.browser.open(
url: "https://flutter.dev/",
options: ChromeSafariBrowserClassOptions(
androidChromeCustomTabsOptions: AndroidChromeCustomTabsOptions(addShareButton: false),
iosSafariOptions: IosSafariOptions(barCollapsingEnabled: true)));
android: AndroidChromeCustomTabsOptions(addShareButton: false),
ios: IosSafariOptions(barCollapsingEnabled: true)));
},
child: Text("Open Chrome Safari Browser")),
),
@ -860,3 +883,38 @@ On Android, this class has a custom implementation using `android.database.sqlit
* `removeHttpAuthCredential({@required ProtectionSpace protectionSpace, @required HttpAuthCredential credential})`: Removes an HTTP auth `credential` for that `protectionSpace`.
* `removeHttpAuthCredentials({@required ProtectionSpace protectionSpace})`: Removes all the HTTP auth credentials saved for that `protectionSpace`.
* `clearAllAuthCredentials()`: Removes all the HTTP auth credentials saved in the database.
### `WebStorageManager` class
This class implements a singleton object (shared instance) which manages the web storage used by WebView instances.
On Android, it is implemented using [WebStorage](https://developer.android.com/reference/android/webkit/WebStorage.html).
On iOS, it is implemented using [WKWebsiteDataStore.default()](https://developer.apple.com/documentation/webkit/wkwebsitedatastore)
**NOTE for iOS**: available from iOS 9.0+.
#### `WebStorageManager` methods
* `instance`: Gets the WebStorage manager shared instance.
#### `WebStorageManager` Android-specific methods
Android-specific methods can be called using the `WebStorageManager.instance().android` attribute.
`AndroidWebStorageManager` class is used to manage the JavaScript storage APIs provided by the WebView. It manages the Application Cache API, the Web SQL Database API and the HTML5 Web Storage API.
* `getOrigins`: Gets the origins currently using either the Application Cache or Web SQL Database APIs.
* `deleteAllData`: Clears all storage currently being used by the JavaScript storage APIs.
* `deleteOrigin({@required String origin})`: Clears the storage currently being used by both the Application Cache and Web SQL Database APIs by the given `origin`.
* `getQuotaForOrigin({@required String origin})`: Gets the storage quota for the Web SQL Database API for the given `origin`.
* `getUsageForOrigin({@required String origin})`: Gets the amount of storage currently being used by both the Application Cache and Web SQL Database APIs by the given `origin`.
#### `WebStorageManager` iOS-specific methods
iOS-specific methods can be called using the `WebStorageManager.instance().ios` attribute.
`IOSWebStorageManager` class represents various types of data that a website might make use of. This includes cookies, disk and memory caches, and persistent data such as WebSQL, IndexedDB databases, and local storage.
* `fetchDataRecords({@required Set<IOSWKWebsiteDataType> dataTypes})`: Fetches data records containing the given website data types.
* `removeDataFor({@required Set<IOSWKWebsiteDataType> dataTypes, @required List<IOSWKWebsiteDataRecord> dataRecords})`: Removes website data of the given types for the given data records.
* `removeDataModifiedSince({@required Set<IOSWKWebsiteDataType> dataTypes, @required DateTime date})`: Removes all website data of the given types that has been modified since the given date.

View File

@ -354,6 +354,24 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
result.success(false);
}
break;
case "getContentHeight":
result.success((webView != null) ? webView.getContentHeight() : null);
break;
case "zoomBy":
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Float zoomFactor = (Float) call.argument("zoomFactor");
webView.zoomBy(zoomFactor);
result.success(true);
} else {
result.success(false);
}
break;
case "getOriginalUrl":
result.success((webView != null) ? webView.getOriginalUrl() : null);
break;
case "getScale":
result.success((webView != null) ? webView.getUpdatedScale() : null);
break;
default:
result.notImplemented();
}

View File

@ -22,6 +22,7 @@
package com.pichillilorenzo.flutter_inappwebview;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@ -133,7 +134,7 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse(url));
activity.startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
} catch (ActivityNotFoundException e) {
Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
}
}
@ -348,6 +349,22 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
}
result.success(true);
break;
case "getContentHeight":
result.success(getContentHeight(uuid));
break;
case "zoomBy":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Float zoomFactor = (Float) call.argument("zoomFactor");
zoomBy(uuid, zoomFactor);
}
result.success(true);
break;
case "getOriginalUrl":
result.success(getOriginalUrl(uuid));
break;
case "getScale":
result.success(getScale(uuid));
break;
default:
result.notImplemented();
}
@ -814,6 +831,34 @@ public class InAppBrowser implements MethodChannel.MethodCallHandler {
inAppBrowserActivity.printCurrentPage();
}
public Integer getContentHeight(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
return inAppBrowserActivity.getContentHeight();
return null;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void zoomBy(String uuid, Float zoomFactor) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.zoomBy(zoomFactor);
}
public String getOriginalUrl(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
return inAppBrowserActivity.getOriginalUrl();
return null;
}
public Float getScale(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
return inAppBrowserActivity.getScale();
return null;
}
public void dispose() {
channel.setMethodCallHandler(null);
for ( InAppBrowserActivity activity : webViewActivities.values()) {

View File

@ -575,4 +575,27 @@ public class InAppBrowserActivity extends AppCompatActivity {
webView.printCurrentPage();
}
public Integer getContentHeight() {
if (webView != null)
return webView.getContentHeight();
return null;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void zoomBy(Float zoomFactor) {
if (webView != null)
webView.zoomBy(zoomFactor);
}
public String getOriginalUrl() {
if (webView != null)
return webView.getOriginalUrl();
return null;
}
public Float getScale() {
if (webView != null)
return webView.getUpdatedScale();
return null;
}
}

View File

@ -1342,69 +1342,8 @@ final public class InAppWebView extends InputAwareWebView {
new PrintAttributes.Builder().build());
}
public void showDropDownWorkaround(final List<Integer> selectedValues, final List<List<String>> values, final boolean isMultiSelect, final DropDownWorkaroundCallback callback) {
FrameLayout layout = new FrameLayout(Shared.activity);
final List<String> listViewValues = new ArrayList<String>();
for(List<String> value : values) {
listViewValues.add(value.get(0));
}
ListView listView = new ListView(Shared.activity);
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(Shared.activity, (!isMultiSelect) ? android.R.layout.simple_list_item_1 : android.R.layout.simple_list_item_multiple_choice, listViewValues);
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_list_item_multiple_choice);
listView.setAdapter(spinnerArrayAdapter);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(Shared.activity, R.style.Theme_AppCompat_Dialog_Alert);
final AlertDialog alertDialog = alertDialogBuilder.create();
final List<String> result = new ArrayList<>();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String value = values.get(position).get(1);
if (!isMultiSelect) {
result.add(value);
alertDialog.dismiss();
} else {
if (!result.contains(value)) {
result.add(value);
} else {
result.remove(value);
}
}
}
});
if (isMultiSelect) {
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setItemsCanFocus(false);
for(Integer selectedValueIndex : selectedValues) {
listView.setItemChecked(selectedValueIndex, true);
String value = values.get(selectedValueIndex).get(1);
result.add(value);
}
}
alertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
callback.result(result);
}
});
layout.addView(listView);
alertDialog.setView(layout);
alertDialog.show();
}
public static class DropDownWorkaroundCallback {
public void result(List<String> value) {
}
public Float getUpdatedScale() {
return scale;
}
@Override

View File

@ -411,10 +411,13 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
}
@Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean userGesture, final Message resultMsg) {
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, final Message resultMsg) {
final Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("androidIsDialog", isDialog);
obj.put("androidIsUserGesture", isUserGesture);
obj.put("iosWKNavigationType", null);
WebView.HitTestResult result = view.getHitTestResult();
String data = result.getExtra();
@ -478,6 +481,14 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
});
}
@Override
public void onGeolocationPermissionsHidePrompt() {
Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
getChannel().invokeMethod("onGeolocationPermissionsHidePrompt", obj);
}
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Map<String, Object> obj = new HashMap<>();

View File

@ -17,6 +17,7 @@ import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebViewClient;
@ -54,7 +55,6 @@ public class InAppWebViewClient extends WebViewClient {
private InAppBrowserActivity inAppBrowserActivity;
private static int previousAuthRequestFailureCount = 0;
private static List<Credential> credentialsProposed = null;
private String onPageStartedURL = "";
public InAppWebViewClient(Object obj) {
super();
@ -188,7 +188,6 @@ public class InAppWebViewClient extends WebViewClient {
webView.loadUrl("javascript:" + js);
}
onPageStartedURL = url;
super.onPageStarted(view, url, favicon);
webView.isLoading = true;
@ -241,16 +240,14 @@ public class InAppWebViewClient extends WebViewClient {
@Override
public void doUpdateVisitedHistory (WebView view, String url, boolean isReload) {
super.doUpdateVisitedHistory(view, url, isReload);
Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
obj.put("androidIsReload", isReload);
getChannel().invokeMethod("onUpdateVisitedHistory", obj);
if (!isReload && !url.equals(onPageStartedURL)) {
onPageStartedURL = "";
Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", url);
getChannel().invokeMethod("onNavigationStateChange", obj);
}
super.doUpdateVisitedHistory(view, url, isReload);
}
@Override

View File

@ -23,6 +23,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
public static InAppWebViewStatic inAppWebViewStatic;
public static MyCookieManager myCookieManager;
public static CredentialDatabaseHandler credentialDatabaseHandler;
public static MyWebStorage myWebStorage;
public static ValueCallback<Uri[]> uploadMessageArray;
public InAppWebViewFlutterPlugin() {}
@ -52,6 +53,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(messenger, flutterView));
inAppWebViewStatic = new InAppWebViewStatic(messenger);
myCookieManager = new MyCookieManager(messenger);
myWebStorage = new MyWebStorage(messenger);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
credentialDatabaseHandler = new CredentialDatabaseHandler(messenger);
}
@ -67,6 +69,10 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
myCookieManager.dispose();
myCookieManager = null;
}
if (myWebStorage != null) {
myWebStorage.dispose();
myWebStorage = null;
}
if (credentialDatabaseHandler != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
credentialDatabaseHandler.dispose();
credentialDatabaseHandler = null;

View File

@ -273,51 +273,6 @@ public class JavaScriptBridgeInterface {
@Override
public void run() {
// workaround for https://github.com/pichillilorenzo/flutter_inappwebview/issues/182
if (handlerName.equals("flutterInAppWebViewDropDownWorkaround")) {
try {
JSONArray jsonArray = new JSONArray(args);
List<Integer> selectedValues = new ArrayList<>();
JSONArray jsonSelectedValues = jsonArray.getJSONArray(0);
for(int i = 0; i < jsonSelectedValues.length(); i++) {
Integer selectedValue = jsonSelectedValues.getInt(i);
selectedValues.add(selectedValue);
}
boolean isMultiSelect = jsonArray.getBoolean(1);
List<List<String>> values = new ArrayList<>();
JSONArray options = jsonArray.getJSONArray(2);
for(int i = 0; i < options.length(); i++) {
JSONObject option = options.getJSONObject(i);
List<String> value = new ArrayList<>();
value.add(option.getString("key"));
value.add(option.getString("value"));
values.add(value);
}
webView.showDropDownWorkaround(selectedValues, values, isMultiSelect, new InAppWebView.DropDownWorkaroundCallback() {
@Override
public void result(List<String> values) {
String value = "{values: " + (new JSONArray(values)) + "}";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript("if(window." + name + "[" + _callHandlerID + "] != null) {window." + name + "[" + _callHandlerID + "](" + value + "); delete window." + name + "[" + _callHandlerID + "];}", (ValueCallback<String>) null);
}
else {
webView.loadUrl("javascript:if(window." + name + "[" + _callHandlerID + "] != null) {window." + name + "[" + _callHandlerID + "](" + value + "); delete window." + name + "[" + _callHandlerID + "];}");
}
}
});
} catch (JSONException e) {
e.printStackTrace();
}
return;
}
if (handlerName.equals("onPrint") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webView.printCurrentPage();
}

View File

@ -0,0 +1,104 @@
package com.pichillilorenzo.flutter_inappwebview;
import android.util.Log;
import android.webkit.ValueCallback;
import android.webkit.WebStorage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class MyWebStorage implements MethodChannel.MethodCallHandler {
static final String LOG_TAG = "MyWebStorage";
public static MethodChannel channel;
public static WebStorage webStorageManager;
public MyWebStorage(BinaryMessenger messenger) {
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_webstoragemanager");
channel.setMethodCallHandler(this);
webStorageManager = WebStorage.getInstance();
}
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
switch (call.method) {
case "getOrigins":
getOrigins(result);
break;
case "deleteAllData":
webStorageManager.deleteAllData();
result.success(true);
break;
case "deleteOrigin":
{
String origin = (String) call.argument("origin");
webStorageManager.deleteOrigin(origin);
}
result.success(true);
break;
case "getQuotaForOrigin":
{
String origin = (String) call.argument("origin");
getQuotaForOrigin(origin, result);
}
break;
case "getUsageForOrigin":
{
String origin = (String) call.argument("origin");
getUsageForOrigin(origin, result);
}
break;
default:
result.notImplemented();
}
}
public void getOrigins(final MethodChannel.Result result) {
webStorageManager.getOrigins(new ValueCallback<Map>() {
@Override
public void onReceiveValue(Map value) {
List<Map<String, Object>> origins = new ArrayList<>();
for(Object key : value.keySet()) {
WebStorage.Origin originObj = (WebStorage.Origin) value.get(key);
Map<String, Object> originInfo = new HashMap<>();
originInfo.put("origin", originObj.getOrigin());
originInfo.put("quota", originObj.getQuota());
originInfo.put("usage", originObj.getUsage());
origins.add(originInfo);
}
result.success(origins);
}
});
}
public void getQuotaForOrigin(String origin, final MethodChannel.Result result) {
webStorageManager.getQuotaForOrigin(origin, new ValueCallback<Long>() {
@Override
public void onReceiveValue(Long value) {
result.success(value);
}
});
}
public void getUsageForOrigin(String origin, final MethodChannel.Result result) {
webStorageManager.getUsageForOrigin(origin, new ValueCallback<Long>() {
@Override
public void onReceiveValue(Long value) {
result.success(value);
}
});
}
public void dispose() {
channel.setMethodCallHandler(null);
}
}

View File

@ -0,0 +1,18 @@
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
#
Pod::Spec.new do |s|
s.name = 'Flutter'
s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.'
s.description = <<-DESC
Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
DESC
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'
s.vendored_frameworks = 'Flutter.framework'
end

View File

@ -52,8 +52,8 @@ class _ChromeSafariBrowserExampleScreenState
await widget.browser.open(
url: "https://flutter.dev/",
options: ChromeSafariBrowserClassOptions(
androidChromeCustomTabsOptions: AndroidChromeCustomTabsOptions(addShareButton: false),
iosSafariOptions: IosSafariOptions(barCollapsingEnabled: true)));
android: AndroidChromeCustomTabsOptions(addShareButton: false),
ios: IOSSafariOptions(barCollapsingEnabled: true)));
},
child: Text("Open Chrome Safari Browser")),
));

View File

@ -92,7 +92,7 @@ class _InAppBrowserExampleScreenState extends State<InAppBrowserExampleScreen> {
assetFilePath: "assets/index.html",
options: InAppBrowserClassOptions(
inAppWebViewWidgetOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
useOnLoadResource: true,
))));

View File

@ -50,9 +50,10 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: InAppWebView(
initialUrl: "https://flutter.dev/",
//initialFile: "assets/index.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
)
),
@ -60,25 +61,51 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
print("onLoadStart $url");
setState(() {
this.url = url;
});
},
onLoadStop: (InAppWebViewController controller, String url) async {
print("onLoadStop $url");
setState(() {
this.url = url;
});
},
onNavigationStateChange: (InAppWebViewController controller, String url) async {
setState(() {
this.url = url;
});
/*var origins = await WebStorageManager.instance().android.getOrigins();
for (var origin in origins) {
print(origin);
print(await WebStorageManager.instance().android.getQuotaForOrigin(origin: origin.origin));
print(await WebStorageManager.instance().android.getUsageForOrigin(origin: origin.origin));
}
await WebStorageManager.instance().android.deleteAllData();
print("\n\nDELETED\n\n");
origins = await WebStorageManager.instance().android.getOrigins();
for (var origin in origins) {
print(origin);
await WebStorageManager.instance().android.deleteOrigin(origin: origin.origin);
}*/
/*var records = await WebStorageManager.instance().ios.fetchDataRecords(dataTypes: IOSWKWebsiteDataType.ALL);
for(var record in records) {
print(record);
}
await WebStorageManager.instance().ios.removeDataModifiedSince(dataTypes: IOSWKWebsiteDataType.ALL, date: DateTime(0));
print("\n\nDELETED\n\n");
records = await WebStorageManager.instance().ios.fetchDataRecords(dataTypes: IOSWKWebsiteDataType.ALL);
for(var record in records) {
print(record);
}*/
},
onProgressChanged: (InAppWebViewController controller, int progress) {
setState(() {
this.progress = progress / 100;
});
},
onUpdateVisitedHistory: (InAppWebViewController controller, String url, bool androidIsReload) {
print("onUpdateVisitedHistory $url");
setState(() {
this.url = url;
});
},
),
),
),

View File

@ -57,7 +57,7 @@ class InAppWebViewAjaxTestState extends WidgetTestState {
"""),
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
useShouldInterceptAjaxRequest: true,

View File

@ -30,7 +30,7 @@ class InAppWebViewContentBlockerTestState extends WidgetTestState {
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
contentBlockers: [

View File

@ -31,7 +31,7 @@ class InAppWebViewCookieManagerTestState extends WidgetTestState {
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -75,7 +75,7 @@ class InAppWebViewFetchTestState extends WidgetTestState {
"""),
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
useShouldInterceptFetchRequest: true,

View File

@ -38,7 +38,7 @@ class InAppWebViewHttpAuthCredentialDatabaseTestState extends WidgetTestState {
initialUrl: "http://${environment["NODE_SERVER_IP"]}:8081/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -66,7 +66,7 @@ class InAppWebViewInitialDataTestState extends WidgetTestState {
"""),
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -29,7 +29,7 @@ class InAppWebViewInitialFileTestState extends WidgetTestState {
initialFile: "test_assets/in_app_webview_initial_file_test.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -30,7 +30,7 @@ class InAppWebViewInitialUrlTestState extends WidgetTestState {
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -44,7 +44,7 @@ class InAppWebViewJavaScriptHandlerTestState extends WidgetTestState {
initialFile: "test_assets/in_app_webview_javascript_handler_test.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -29,7 +29,7 @@ class InAppWebViewOnConsoleMessageTestState extends WidgetTestState {
initialFile: "test_assets/in_app_webview_on_console_message_test.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -29,7 +29,7 @@ class InAppWebViewOnCreateWindowTestState extends WidgetTestState {
initialFile: "test_assets/in_app_webview_on_create_window_test.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
javaScriptCanOpenWindowsAutomatically: true,
@ -48,8 +48,8 @@ class InAppWebViewOnCreateWindowTestState extends WidgetTestState {
});
}
},
onCreateWindow: (InAppWebViewController controller, String url) {
controller.loadUrl(url: url);
onCreateWindow: (InAppWebViewController controller, OnCreateWindowRequest onCreateWindowRequest) {
controller.loadUrl(url: onCreateWindowRequest.url);
},
),
),

View File

@ -49,7 +49,7 @@ class InAppWebViewOnDownloadStartTestState extends WidgetTestState {
"""),
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
useOnDownloadStart: true

View File

@ -29,7 +29,7 @@ class InAppWebViewOnFindResultReceivedTestState extends WidgetTestState {
initialFile: "test_assets/in_app_webview_initial_file_test.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -37,7 +37,7 @@ class InAppWebViewOnJsDialogTestState extends WidgetTestState {
initialFile: "test_assets/in_app_webview_on_js_dialog_test.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -30,7 +30,7 @@ class InAppWebViewOnLoadErrorTestState extends WidgetTestState {
initialUrl: "https://not-existing-domain.org/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -30,7 +30,7 @@ class InAppWebViewOnLoadHttpErrorTestState extends WidgetTestState {
initialUrl: "https://google.com/404",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -30,7 +30,7 @@ class InAppWebViewOnLoadResourceCustomSchemeTestState extends WidgetTestState {
initialFile: "test_assets/in_app_webview_on_load_resource_custom_scheme_test.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
resourceCustomSchemes: ["my-special-custom-scheme"]

View File

@ -35,7 +35,7 @@ class InAppWebViewOnLoadResourceTestState extends WidgetTestState {
initialFile: "test_assets/in_app_webview_on_load_resource_test.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
useOnLoadResource: true

View File

@ -29,7 +29,7 @@ class InAppWebViewOnNavigationStateChangeTestState extends WidgetTestState {
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -30,7 +30,7 @@ class InAppWebViewOnProgressChangedTestState extends WidgetTestState {
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -31,7 +31,7 @@ class InAppWebViewOnReceivedHttpAuthRequestTestState extends WidgetTestState {
initialUrl: "http://${environment["NODE_SERVER_IP"]}:8081/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -32,20 +32,20 @@ class InAppWebViewOnSafeBrowsingHitTestState extends WidgetTestState {
initialUrl: (Platform.isAndroid) ? "chrome://safe-browsing/match?type=malware" : "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
// if I set javaScriptEnabled to true, it will crash!
javaScriptEnabled: false,
clearCache: true,
debuggingEnabled: true
),
androidInAppWebViewOptions: AndroidInAppWebViewOptions(
android: AndroidInAppWebViewOptions(
safeBrowsingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
if(Platform.isAndroid)
controller.startSafeBrowsing();
controller.android.startSafeBrowsing();
},
onLoadStart: (InAppWebViewController controller, String url) {
@ -55,7 +55,7 @@ class InAppWebViewOnSafeBrowsingHitTestState extends WidgetTestState {
appBarTitle = url;
});
},
onSafeBrowsingHit: (InAppWebViewController controller, String url, SafeBrowsingThreat threatType) async {
androidOnSafeBrowsingHit: (InAppWebViewController controller, String url, SafeBrowsingThreat threatType) async {
return SafeBrowsingResponse(report: true, action: SafeBrowsingResponseAction.PROCEED);
},
),

View File

@ -31,7 +31,7 @@ class InAppWebViewOnScrollChangedTestState extends WidgetTestState {
initialUrl: "https://flutter.dev/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -29,7 +29,7 @@ class InAppWebViewShouldOverrideUrlLoadingTestState extends WidgetTestState {
initialFile: "test_assets/in_app_webview_initial_file_test.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true,
useShouldOverrideUrlLoading: true

View File

@ -31,7 +31,7 @@ class InAppWebViewSslRequestTestState extends WidgetTestState {
initialUrl: "https://${environment["NODE_SERVER_IP"]}:4433/",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true,
debuggingEnabled: true
)

View File

@ -26,6 +26,7 @@
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_inappwebview/example/ios/Flutter/App.framework/flutter_assets/packages" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/Flutter/App.framework/flutter_assets/packages" />
<excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/flutter_inappbrowser_tests/.pub" />

View File

@ -0,0 +1,18 @@
//
// FlutterMethodCallDelegate.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 15/12/2019.
//
import Foundation
public class FlutterMethodCallDelegate: NSObject {
public override init() {
super.init()
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
}
}

View File

@ -8,12 +8,13 @@
import Foundation
import WebKit
public class FlutterWebViewController: NSObject, FlutterPlatformView {
public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatformView {
private weak var registrar: FlutterPluginRegistrar?
var webView: InAppWebView?
var viewId: Int64 = 0
var channel: FlutterMethodChannel?
var myView: UIView?
init(registrar: FlutterPluginRegistrar, withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: NSDictionary) {
super.init()
@ -21,24 +22,29 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
self.registrar = registrar
self.viewId = viewId
myView = UIView(frame: frame)
let channelName = "com.pichillilorenzo/flutter_inappwebview_" + String(viewId)
self.channel = FlutterMethodChannel(name: channelName, binaryMessenger: registrar.messenger())
self.channel?.setMethodCallHandler(LeakAvoider(delegate: self).handle)
let initialUrl = (args["initialUrl"] as? String)!
let initialFile = args["initialFile"] as? String
let initialData = args["initialData"] as? [String: String]
let initialHeaders = (args["initialHeaders"] as? [String: String])!
let initialOptions = (args["initialOptions"] as? [String: Any])!
let options = InAppWebViewOptions()
options.parse(options: initialOptions)
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: options)
webView = InAppWebView(frame: frame, configuration: preWebviewConfiguration, IABController: nil, IAWController: self)
let channelName = "com.pichillilorenzo/flutter_inappwebview_" + String(viewId)
self.channel = FlutterMethodChannel(name: channelName, binaryMessenger: registrar.messenger())
self.channel?.setMethodCallHandler(self.handle)
webView = InAppWebView(frame: myView!.bounds, configuration: preWebviewConfiguration, IABController: nil, channel: self.channel)
webView!.autoresizingMask = [.flexibleWidth, .flexibleHeight]
myView!.addSubview(webView!)
webView!.options = options
webView!.prepare()
if #available(iOS 11.0, *) {
self.webView!.configuration.userContentController.removeAllContentRuleLists()
if let contentBlockers = webView!.options?.contentBlockers, contentBlockers.count > 0 {
@ -48,15 +54,15 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
WKContentRuleListStore.default().compileContentRuleList(
forIdentifier: "ContentBlockingRules",
encodedContentRuleList: blockRules) { (contentRuleList, error) in
if let error = error {
print(error.localizedDescription)
return
}
let configuration = self.webView!.configuration
configuration.userContentController.add(contentRuleList!)
self.load(initialUrl: initialUrl, initialFile: initialFile, initialData: initialData, initialHeaders: initialHeaders)
}
return
@ -68,8 +74,16 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
load(initialUrl: initialUrl, initialFile: initialFile, initialData: initialData, initialHeaders: initialHeaders)
}
deinit {
print("FlutterWebViewController - dealloc")
self.channel?.setMethodCallHandler(nil)
webView!.dispose()
webView = nil
myView = nil
}
public func view() -> UIView {
return webView!
return myView!
}
public func load(initialUrl: String, initialFile: String?, initialData: [String: String]?, initialHeaders: [String: String]) {
@ -95,7 +109,7 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
}
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "getUrl":
@ -344,10 +358,18 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
result(false)
}
break
case "removeFromSuperview":
webView!.removeFromSuperview()
case "getContentHeight":
result( (webView != nil) ? webView!.getContentHeight() : nil )
break
case "reloadFromOrigin":
if webView != nil {
webView!.reloadFromOrigin()
}
result(true)
break
case "getScale":
result( (webView != nil) ? webView!.getScale() : nil )
break
default:
result(FlutterMethodNotImplemented)
break

View File

@ -65,7 +65,7 @@ typealias NewerClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, B
class InAppWebView_IBWrapper: InAppWebView {
required init(coder: NSCoder) {
let config = WKWebViewConfiguration()
super.init(frame: .zero, configuration: config, IABController: nil, IAWController: nil)
super.init(frame: .zero, configuration: config, IABController: nil, channel: nil)
self.translatesAutoresizingMaskIntoConstraints = false
}
}
@ -114,7 +114,7 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
override func viewWillAppear(_ animated: Bool) {
if !viewPrepared {
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: webViewOptions)
self.webView = InAppWebView(frame: .zero, configuration: preWebviewConfiguration, IABController: self, IAWController: nil)
self.webView = InAppWebView(frame: .zero, configuration: preWebviewConfiguration, IABController: self, channel: nil)
self.containerWebView.addSubview(self.webView)
prepareConstraints()
prepareWebView()
@ -194,12 +194,21 @@ class InAppBrowserWebViewController: UIViewController, UIScrollViewDelegate, WKU
// Prevent crashes on closing windows
deinit {
webView.removeObserver(self, forKeyPath: "estimatedProgress")
webView.uiDelegate = nil
print("InAppBrowserWebViewController - dealloc")
}
override func viewWillDisappear (_ animated: Bool) {
super.viewWillDisappear(animated)
webView.dispose()
navigationDelegate = nil
transitioningDelegate = nil
urlField.delegate = nil
closeButton.removeTarget(self, action: #selector(self.close), for: .touchUpInside)
forwardButton.target = nil
forwardButton.target = nil
backButton.target = nil
reloadButton.target = nil
shareButton.target = nil
}
func prepareConstraints () {

View File

@ -873,39 +873,10 @@ let interceptFetchRequestsJS = """
})(window.fetch);
"""
let interceptNavigationStateChangeJS = """
(function(window, document, history) {
history.pushState = (function(f) {
return function pushState(){
var ret = f.apply(this, arguments);
window.dispatchEvent(new Event('pushstate'));
window.dispatchEvent(new Event('_flutter_inappwebview_locationchange'));
return ret;
};
})(history.pushState);
history.replaceState = ( function(f) {
return function replaceState(){
var ret = f.apply(this, arguments);
window.dispatchEvent(new Event('replacestate'));
window.dispatchEvent(new Event('_flutter_inappwebview_locationchange'));
return ret;
};
})(history.replaceState);
window.addEventListener('popstate',function() {
window.dispatchEvent(new Event('_flutter_inappwebview_locationchange'));
});
window.addEventListener('_flutter_inappwebview_locationchange', function() {
window.webkit.messageHandlers["onNavigationStateChange"].postMessage(JSON.stringify({
url: document.location.href
}));
});
})(window, window.document, window.history);
"""
public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler {
var IABController: InAppBrowserWebViewController?
var IAWController: FlutterWebViewController?
var channel: FlutterMethodChannel?
var options: InAppWebViewOptions?
var currentURL: URL?
var startPageTime: Int64 = 0
@ -914,37 +885,18 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
var lastScrollY: CGFloat = 0
var isPausedTimers = false
var isPausedTimersCompletionHandler: (() -> Void)?
var webViewForUserAgent: WKWebView?
var defaultUserAgent: String?
// This flag is used to block the "shouldOverrideUrlLoading" event when the WKWebView is loading the first time,
// in order to have the same behavior as Android
var activateShouldOverrideUrlLoading = false
init(frame: CGRect, configuration: WKWebViewConfiguration, IABController: InAppBrowserWebViewController?, IAWController: FlutterWebViewController?) {
init(frame: CGRect, configuration: WKWebViewConfiguration, IABController: InAppBrowserWebViewController?, channel: FlutterMethodChannel?) {
super.init(frame: frame, configuration: configuration)
self.channel = channel
self.IABController = IABController
self.IAWController = IAWController
uiDelegate = self
navigationDelegate = self
scrollView.delegate = self
webViewForUserAgent = WKWebView()
webViewForUserAgent?.evaluateJavaScript("navigator.userAgent") { (result, error) in
if error != nil {
print("Error occured to get userAgent")
self.webViewForUserAgent = nil
return
}
if let unwrappedUserAgent = result as? String {
self.defaultUserAgent = unwrappedUserAgent
} else {
print("Failed to get userAgent")
}
self.webViewForUserAgent = nil
}
}
required public init(coder aDecoder: NSCoder) {
@ -958,6 +910,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
options: .new,
context: nil)
addObserver(self,
forKeyPath: #keyPath(WKWebView.url),
options: [.new, .old],
context: nil)
configuration.userContentController = WKUserContentController()
configuration.preferences = WKPreferences()
@ -1018,11 +975,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
configuration.userContentController.addUserScript(findTextHighlightJSScript)
configuration.userContentController.add(self, name: "onFindResultReceived")
let interceptNavigationStateChangeJSScript = WKUserScript(source: interceptNavigationStateChangeJS, injectionTime: .atDocumentStart, forMainFrameOnly: false)
configuration.userContentController.addUserScript(interceptNavigationStateChangeJSScript)
configuration.userContentController.add(self, name: "onNavigationStateChange")
if (options?.useShouldInterceptAjaxRequest)! {
let interceptAjaxRequestsJSScript = WKUserScript(source: interceptAjaxRequestsJS, injectionTime: .atDocumentStart, forMainFrameOnly: false)
configuration.userContentController.addUserScript(interceptAjaxRequestsJSScript)
@ -1093,6 +1045,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
if options?.preferredContentMode != nil {
configuration.defaultWebpagePreferences.preferredContentMode = WKWebpagePreferences.ContentMode(rawValue: (options?.preferredContentMode)!)!
}
scrollView.automaticallyAdjustsScrollIndicatorInsets = (options?.automaticallyAdjustsScrollIndicatorInsets)!
} else {
// Fallback on earlier versions
}
@ -1169,6 +1122,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
if keyPath == #keyPath(WKWebView.estimatedProgress) {
let progress = Int(estimatedProgress * 100)
onProgressChanged(progress: progress)
} else if keyPath == #keyPath(WKWebView.url) && change?[NSKeyValueChangeKey.newKey] is URL {
let newUrl = change?[NSKeyValueChangeKey.newKey] as? URL
onUpdateVisitedHistory(url: newUrl!.absoluteString)
}
}
@ -1383,9 +1339,18 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
// Fallback on earlier versions
}
scrollView
if #available(iOS 13.0, *) {
configuration.preferences.isFraudulentWebsiteWarningEnabled = (options?.isFraudulentWebsiteWarningEnabled)!
configuration.defaultWebpagePreferences.preferredContentMode = WKWebpagePreferences.ContentMode(rawValue: (options?.preferredContentMode)!)!
if newOptionsMap["isFraudulentWebsiteWarningEnabled"] != nil && options?.isFraudulentWebsiteWarningEnabled != newOptions.isFraudulentWebsiteWarningEnabled {
configuration.preferences.isFraudulentWebsiteWarningEnabled = newOptions.isFraudulentWebsiteWarningEnabled
}
if newOptionsMap["preferredContentMode"] != nil && options?.preferredContentMode != newOptions.preferredContentMode {
configuration.defaultWebpagePreferences.preferredContentMode = WKWebpagePreferences.ContentMode(rawValue: newOptions.preferredContentMode)!
}
if newOptionsMap["automaticallyAdjustsScrollIndicatorInsets"] != nil && options?.automaticallyAdjustsScrollIndicatorInsets != newOptions.automaticallyAdjustsScrollIndicatorInsets {
scrollView.automaticallyAdjustsScrollIndicatorInsets = newOptions.automaticallyAdjustsScrollIndicatorInsets
}
} else {
// Fallback on earlier versions
}
@ -1490,7 +1455,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
if error != nil {
let userInfo = (error! as NSError).userInfo
self.onConsoleMessage(message: userInfo["WKJavaScriptExceptionMessage"] as! String, messageLevel: 3)
self.onConsoleMessage(message: userInfo["WKJavaScriptExceptionMessage"] as? String ?? "", messageLevel: 3)
}
if value == nil {
@ -1651,7 +1616,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
InAppWebView.credentialsProposed = []
evaluateJavaScript(platformReadyJS, completionHandler: nil)
onLoadStop(url: (currentURL?.absoluteString)!)
if IABController != nil {
IABController!.updateUrlTextField(url: (currentURL?.absoluteString)!)
IABController!.backButton.isEnabled = canGoBack
@ -2111,7 +2076,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
createWebViewWith configuration: WKWebViewConfiguration,
for navigationAction: WKNavigationAction,
windowFeatures: WKWindowFeatures) -> WKWebView? {
onCreateWindow(url: navigationAction.request.url!)
onCreateWindow(url: navigationAction.request.url!, navigationType: navigationAction.navigationType)
return nil
}
@ -2171,6 +2136,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
"numberOfMatches": numberOfMatches,
"isDoneCounting": isDoneCounting
]
if IABController != nil {
arguments["uuid"] = IABController!.uuid
}
@ -2179,18 +2145,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
}
}
public func onNavigationStateChange(url: String) {
var arguments: [String : Any] = [
"url": url
]
if IABController != nil {
arguments["uuid"] = IABController!.uuid
}
if let channel = getChannel() {
channel.invokeMethod("onNavigationStateChange", arguments: arguments)
}
}
public func onScrollChanged(x: Int, y: Int) {
var arguments: [String: Any] = ["x": x, "y": y]
if IABController != nil {
@ -2239,8 +2193,13 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
}
}
public func onCreateWindow(url: URL) {
var arguments: [String: Any] = ["url": url.absoluteString]
public func onCreateWindow(url: URL, navigationType: WKNavigationType) {
var arguments: [String: Any?] = [
"url": url.absoluteString,
"androidIsDialog": nil,
"androidIsUserGesture": nil,
"iosWKNavigationType": navigationType.rawValue
]
if IABController != nil {
arguments["uuid"] = IABController!.uuid
}
@ -2348,6 +2307,19 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
}
}
public func onUpdateVisitedHistory(url: String) {
var arguments: [String: Any?] = [
"url": url,
"androidIsReload": nil
]
if IABController != nil {
arguments["uuid"] = IABController!.uuid
}
if let channel = getChannel() {
channel.invokeMethod("onUpdateVisitedHistory", arguments: arguments)
}
}
public func onCallJsHandler(handlerName: String, _callHandlerID: Int64, args: String) {
var arguments: [String: Any] = ["handlerName": handlerName, "args": args]
if IABController != nil {
@ -2414,18 +2386,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
self.onFindResultReceived(activeMatchOrdinal: activeMatchOrdinal, numberOfMatches: numberOfMatches, isDoneCounting: isDoneCounting)
}
} else if message.name == "onNavigationStateChange" {
if let resource = convertToDictionary(text: message.body as! String) {
let url = resource["url"] as! String
self.onNavigationStateChange(url: url)
}
}
}
private func getChannel() -> FlutterMethodChannel? {
return (IABController != nil) ? SwiftFlutterPlugin.instance!.channel! : ((IAWController != nil) ? IAWController!.channel! : nil);
return (IABController != nil) ? SwiftFlutterPlugin.instance!.channel! : ((channel != nil) ? channel! : nil);
}
public func findAllAsync(find: String?, completionHandler: ((Any?, Error?) -> Void)?) {
@ -2487,7 +2452,21 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
printController.present(animated: true, completionHandler: completionHandler)
}
public override func removeFromSuperview() {
public func getContentHeight() -> Int64 {
return Int64(scrollView.contentSize.height)
}
public func zoomBy(zoomFactor: Float) {
let currentZoomScale = scrollView.zoomScale
scrollView.setZoomScale(currentZoomScale * CGFloat(zoomFactor), animated: false)
}
public func getScale() -> Float {
return Float(scrollView.zoomScale)
}
public func dispose() {
stopLoading()
configuration.userContentController.removeScriptMessageHandler(forName: "consoleLog")
configuration.userContentController.removeScriptMessageHandler(forName: "consoleDebug")
configuration.userContentController.removeScriptMessageHandler(forName: "consoleError")
@ -2495,16 +2474,21 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
configuration.userContentController.removeScriptMessageHandler(forName: "consoleWarn")
configuration.userContentController.removeScriptMessageHandler(forName: "callHandler")
configuration.userContentController.removeScriptMessageHandler(forName: "onFindResultReceived")
configuration.userContentController.removeScriptMessageHandler(forName: "onNavigationStateChange")
configuration.userContentController.removeAllUserScripts()
removeObserver(self, forKeyPath: "estimatedProgress")
super.removeFromSuperview()
removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress))
removeObserver(self, forKeyPath: #keyPath(WKWebView.url))
if #available(iOS 11.0, *) {
configuration.userContentController.removeAllContentRuleLists()
}
uiDelegate = nil
navigationDelegate = nil
scrollView.delegate = nil
IAWController?.channel?.setMethodCallHandler(nil)
IABController?.webView = nil
IAWController?.webView = nil
isPausedTimersCompletionHandler = nil
super.removeFromSuperview()
}
deinit {
print("InAppWebView - dealloc")
}
}

View File

@ -48,6 +48,7 @@ public class InAppWebViewOptions: Options {
var dataDetectorTypes: [String] = ["NONE"] // WKDataDetectorTypeNone
var preferredContentMode = 0
var sharedCookiesEnabled = false
var automaticallyAdjustsScrollIndicatorInsets = false
override init(){
super.init()

View File

@ -0,0 +1,25 @@
//
// LeakAvoider.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 15/12/2019.
//
import Foundation
public class LeakAvoider: NSObject {
weak var delegate : FlutterMethodCallDelegate?
init(delegate: FlutterMethodCallDelegate) {
self.delegate = delegate
super.init()
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
self.delegate?.handle(call, result: result)
}
deinit {
print("LeakAvoider - dealloc")
}
}

View File

@ -0,0 +1,93 @@
//
// MyWebStorageManager.swift
// connectivity
//
// Created by Lorenzo Pichilli on 16/12/2019.
//
import Foundation
import WebKit
@available(iOS 9.0, *)
class MyWebStorageManager: NSObject, FlutterPlugin {
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static var websiteDataStore: WKWebsiteDataStore?
static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
MyWebStorageManager.registrar = registrar
MyWebStorageManager.websiteDataStore = WKWebsiteDataStore.default()
MyWebStorageManager.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappwebview_webstoragemanager", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: MyWebStorageManager.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "fetchDataRecords":
let dataTypes = Set(arguments!["dataTypes"] as! [String])
MyWebStorageManager.fetchDataRecords(dataTypes: dataTypes, result: result)
break
case "removeDataFor":
let dataTypes = Set(arguments!["dataTypes"] as! [String])
let recordList = arguments!["recordList"] as! [[String: Any?]]
MyWebStorageManager.removeDataFor(dataTypes: dataTypes, recordList: recordList, result: result)
break
case "removeDataModifiedSince":
let dataTypes = Set(arguments!["dataTypes"] as! [String])
let timestamp = arguments!["timestamp"] as! Int64
MyWebStorageManager.removeDataModifiedSince(dataTypes: dataTypes, timestamp: timestamp, result: result)
break
default:
result(FlutterMethodNotImplemented)
break
}
}
public static func fetchDataRecords(dataTypes: Set<String>, result: @escaping FlutterResult) {
var recordList: [[String: Any?]] = []
MyWebStorageManager.websiteDataStore!.fetchDataRecords(ofTypes: dataTypes) { (data) in
for record in data {
recordList.append([
"displayName": record.displayName,
"dataTypes": record.dataTypes.map({ (dataType) -> String in
return dataType
})
])
}
result(recordList)
}
}
public static func removeDataFor(dataTypes: Set<String>, recordList: [[String: Any?]], result: @escaping FlutterResult) {
var records: [WKWebsiteDataRecord] = []
MyWebStorageManager.websiteDataStore!.fetchDataRecords(ofTypes: dataTypes) { (data) in
for record in data {
for r in recordList {
let displayName = r["displayName"] as! String
if (record.displayName == displayName) {
records.append(record)
break
}
}
}
MyWebStorageManager.websiteDataStore!.removeData(ofTypes: dataTypes, for: records) {
result(true)
}
}
}
public static func removeDataModifiedSince(dataTypes: Set<String>, timestamp: Int64, result: @escaping FlutterResult) {
let date = NSDate(timeIntervalSince1970: TimeInterval(timestamp))
MyWebStorageManager.websiteDataStore!.removeData(ofTypes: dataTypes, modifiedSince: date as Date) {
result(true)
}
}
}

View File

@ -61,6 +61,9 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
if #available(iOS 11.0, *) {
MyCookieManager(registrar: registrar)
}
if #available(iOS 9.0, *) {
MyWebStorageManager(registrar: registrar)
}
CredentialDatabase(registrar: registrar)
}
@ -254,6 +257,39 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
self.clearCache(uuid: uuid)
result(true)
break
case "scrollTo":
let x = arguments!["x"] as! Int
let y = arguments!["y"] as! Int
self.scrollTo(uuid: uuid, x: x, y: y)
result(true)
break
case "scrollBy":
let x = arguments!["x"] as! Int
let y = arguments!["y"] as! Int
self.scrollTo(uuid: uuid, x: x, y: y)
result(true)
break
case "pauseTimers":
self.pauseTimers(uuid: uuid)
result(true)
break
case "resumeTimers":
self.resumeTimers(uuid: uuid)
result(true)
break
case "printCurrentPage":
self.printCurrentPage(uuid: uuid, result: result)
break
case "getContentHeight":
result(self.getContentHeight(uuid: uuid))
break
case "reloadFromOrigin":
self.reloadFromOrigin(uuid: uuid)
result(true)
break
case "getScale":
result(self.getScale(uuid: uuid))
break
default:
result(FlutterMethodNotImplemented)
break
@ -690,33 +726,33 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
func onBrowserCreated(uuid: String, webView: WKWebView) {
public func onBrowserCreated(uuid: String, webView: WKWebView) {
if let webViewController = self.webViewControllers[uuid] {
self.channel!.invokeMethod("onBrowserCreated", arguments: ["uuid": uuid])
}
}
func onExit(uuid: String) {
public func onExit(uuid: String) {
self.channel!.invokeMethod("onExit", arguments: ["uuid": uuid])
}
func onChromeSafariBrowserOpened(uuid: String) {
public func onChromeSafariBrowserOpened(uuid: String) {
if self.safariViewControllers[uuid] != nil {
self.channel!.invokeMethod("onChromeSafariBrowserOpened", arguments: ["uuid": uuid])
}
}
func onChromeSafariBrowserLoaded(uuid: String) {
public func onChromeSafariBrowserLoaded(uuid: String) {
if self.safariViewControllers[uuid] != nil {
self.channel!.invokeMethod("onChromeSafariBrowserLoaded", arguments: ["uuid": uuid])
}
}
func onChromeSafariBrowserClosed(uuid: String) {
public func onChromeSafariBrowserClosed(uuid: String) {
self.channel!.invokeMethod("onChromeSafariBrowserClosed", arguments: ["uuid": uuid])
}
func safariExit(uuid: String) {
public func safariExit(uuid: String) {
if let safariViewController = self.safariViewControllers[uuid] {
if #available(iOS 9.0, *) {
(safariViewController as! SafariViewController).statusDelegate = nil
@ -727,7 +763,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
func browserExit(uuid: String) {
public func browserExit(uuid: String) {
if let webViewController = self.webViewControllers[uuid] {
// Set navigationDelegate to nil to ensure no callbacks are received from it.
webViewController?.navigationDelegate = nil
@ -743,33 +779,33 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
func setOptions(uuid: String, options: InAppBrowserOptions, optionsMap: [String: Any]) {
public func setOptions(uuid: String, options: InAppBrowserOptions, optionsMap: [String: Any]) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.setOptions(newOptions: options, newOptionsMap: optionsMap)
}
}
func getOptions(uuid: String) -> [String: Any]? {
public func getOptions(uuid: String) -> [String: Any]? {
if let webViewController = self.webViewControllers[uuid] {
return webViewController!.getOptions()
}
return nil
}
func getCopyBackForwardList(uuid: String) -> [String: Any]? {
public func getCopyBackForwardList(uuid: String) -> [String: Any]? {
if let webViewController = self.webViewControllers[uuid] {
return webViewController!.webView.getCopyBackForwardList()
}
return nil
}
func findAllAsync(uuid: String, find: String) {
public func findAllAsync(uuid: String, find: String) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.findAllAsync(find: find, completionHandler: nil)
}
}
func findNext(uuid: String, forward: Bool, result: @escaping FlutterResult) {
public func findNext(uuid: String, forward: Bool, result: @escaping FlutterResult) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.findNext(forward: forward, completionHandler: {(value, error) in
if error != nil {
@ -783,7 +819,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
func clearMatches(uuid: String, result: @escaping FlutterResult) {
public func clearMatches(uuid: String, result: @escaping FlutterResult) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.clearMatches(completionHandler: {(value, error) in
if error != nil {
@ -797,12 +833,69 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
func clearCache(uuid: String) {
public func clearCache(uuid: String) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.clearCache()
}
}
public func scrollTo(uuid: String, x: Int, y: Int) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.scrollTo(x: x, y: y)
}
}
public func scrollBy(uuid: String, x: Int, y: Int) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.scrollBy(x: x, y: y)
}
}
public func pauseTimers(uuid: String) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.pauseTimers()
}
}
public func resumeTimers(uuid: String) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.resumeTimers()
}
}
public func printCurrentPage(uuid: String, result: @escaping FlutterResult) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.printCurrentPage(printCompletionHandler: {(completed, error) in
if !completed, let e = error {
result(false)
return
}
result(true)
})
} else {
result(false)
}
}
public func getContentHeight(uuid: String) -> Int64? {
if let webViewController = self.webViewControllers[uuid] {
return webViewController!.webView.getContentHeight()
}
return nil
}
public func reloadFromOrigin(uuid: String) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.reloadFromOrigin()
}
}
public func getScale(uuid: String) -> Float? {
if let webViewController = self.webViewControllers[uuid] {
return webViewController!.webView.getScale()
}
return nil
}
}
// Helper function inserted by Swift 4.2 migrator.

View File

@ -0,0 +1,30 @@
//
// TestWebView.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 14/12/2019.
//
import Flutter
import Foundation
import WebKit
public class TestWebView: WKWebView {
override init(frame: CGRect, configuration: WKWebViewConfiguration) {
super.init(frame: frame, configuration: configuration)
}
required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
public override func removeFromSuperview() {
configuration.userContentController.removeAllUserScripts()
super.removeFromSuperview()
print("\n\n DISPOSE \n\n")
}
deinit {
print("dealloc") // never called
}
}

View File

@ -32,3 +32,4 @@ export 'src/in_app_localhost_server.dart';
export 'src/webview_options.dart';
export 'src/content_blocker.dart';
export 'src/http_auth_credentials_database.dart';
export 'src/web_storage_manager.dart';

View File

@ -63,30 +63,30 @@ class ChromeSafariBrowser {
Map<String, dynamic> optionsMap = {};
if (Platform.isAndroid)
optionsMap.addAll(options.androidChromeCustomTabsOptions?.toMap() ?? {});
optionsMap.addAll(options.android?.toMap() ?? {});
else if (Platform.isIOS)
optionsMap.addAll(options.iosSafariOptions?.toMap() ?? {});
optionsMap.addAll(options.ios?.toMap() ?? {});
Map<String, dynamic> optionsFallbackMap = {};
if (optionsFallback != null) {
optionsFallbackMap
.addAll(optionsFallback.inAppBrowserOptions?.toMap() ?? {});
.addAll(optionsFallback.crossPlatform?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback
.inAppWebViewWidgetOptions?.inAppWebViewOptions
.inAppWebViewWidgetOptions?.crossPlatform
?.toMap() ??
{});
if (Platform.isAndroid) {
optionsFallbackMap
.addAll(optionsFallback.androidInAppBrowserOptions?.toMap() ?? {});
.addAll(optionsFallback.android?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
.inAppWebViewWidgetOptions?.android
?.toMap() ??
{});
} else if (Platform.isIOS) {
optionsFallbackMap
.addAll(optionsFallback.iosInAppBrowserOptions?.toMap() ?? {});
.addAll(optionsFallback.ios?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback
.inAppWebViewWidgetOptions?.iosInAppWebViewOptions
.inAppWebViewWidgetOptions?.ios
?.toMap() ??
{});
}

View File

@ -62,19 +62,19 @@ class InAppBrowser {
Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.crossPlatform?.toMap() ?? {});
optionsMap.addAll(
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
options.inAppWebViewWidgetOptions?.crossPlatform?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.android?.toMap() ?? {});
optionsMap.addAll(options
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
.inAppWebViewWidgetOptions?.android
?.toMap() ??
{});
} else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.ios?.toMap() ?? {});
optionsMap.addAll(
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
options.inAppWebViewWidgetOptions?.ios?.toMap() ??
{});
}
@ -132,19 +132,19 @@ class InAppBrowser {
Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.crossPlatform?.toMap() ?? {});
optionsMap.addAll(
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
options.inAppWebViewWidgetOptions?.crossPlatform?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.android?.toMap() ?? {});
optionsMap.addAll(options
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
.inAppWebViewWidgetOptions?.android
?.toMap() ??
{});
} else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.ios?.toMap() ?? {});
optionsMap.addAll(
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
options.inAppWebViewWidgetOptions?.ios?.toMap() ??
{});
}
@ -166,7 +166,7 @@ class InAppBrowser {
///
///The [encoding] parameter specifies the encoding of the data. The default value is `"utf8"`.
///
///The [historyUrl] 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.
///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.
///
///The [options] parameter specifies the options for the [InAppBrowser].
Future<void> openData(
@ -174,25 +174,25 @@ class InAppBrowser {
String mimeType = "text/html",
String encoding = "utf8",
String baseUrl = "about:blank",
String historyUrl = "about:blank",
String androidHistoryUrl = "about:blank",
InAppBrowserClassOptions options}) async {
assert(data != null);
Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.crossPlatform?.toMap() ?? {});
optionsMap.addAll(
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
options.inAppWebViewWidgetOptions?.crossPlatform?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.android?.toMap() ?? {});
optionsMap.addAll(options
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
.inAppWebViewWidgetOptions?.android
?.toMap() ??
{});
} else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.ios?.toMap() ?? {});
optionsMap.addAll(
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
options.inAppWebViewWidgetOptions?.ios?.toMap() ??
{});
}
@ -263,19 +263,19 @@ class InAppBrowser {
Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.crossPlatform?.toMap() ?? {});
optionsMap.addAll(
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
options.inAppWebViewWidgetOptions?.crossPlatform?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.android?.toMap() ?? {});
optionsMap.addAll(options
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
.inAppWebViewWidgetOptions?.android
?.toMap() ??
{});
} else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.ios?.toMap() ?? {});
optionsMap.addAll(
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
options.inAppWebViewWidgetOptions?.ios?.toMap() ??
{});
}
@ -299,22 +299,22 @@ class InAppBrowser {
await ChannelManager.channel.invokeMethod('getOptions', args);
if (options != null) {
options = options.cast<String, dynamic>();
inAppBrowserClassOptions.inAppBrowserOptions =
inAppBrowserClassOptions.crossPlatform =
InAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions = InAppWebViewWidgetOptions();
inAppBrowserClassOptions.inAppWebViewWidgetOptions.inAppWebViewOptions =
inAppBrowserClassOptions.inAppWebViewWidgetOptions.crossPlatform =
InAppWebViewOptions.fromMap(options);
if (Platform.isAndroid) {
inAppBrowserClassOptions.androidInAppBrowserOptions =
inAppBrowserClassOptions.android =
AndroidInAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions
.inAppWebViewWidgetOptions.androidInAppWebViewOptions =
.inAppWebViewWidgetOptions.android =
AndroidInAppWebViewOptions.fromMap(options);
} else if (Platform.isIOS) {
inAppBrowserClassOptions.iosInAppBrowserOptions =
IosInAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.ios =
IOSInAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions
.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options);
.ios = IOSInAppWebViewOptions.fromMap(options);
}
}
@ -403,21 +403,10 @@ class InAppBrowser {
///Event fired when the [InAppBrowser] webview requests the host application to create a new window,
///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
///
///[url] represents the url of the request.
///[onCreateWindowRequest] represents the request.
///
///**NOTE**: on Android you need to set [AndroidInAppWebViewOptions.supportMultipleWindows] option to `true`.
void onCreateWindow(String url) {}
///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin.
///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https.
///On non-secure origins geolocation requests are automatically denied.
///
///[origin] represents the origin of the web content attempting to use the Geolocation API.
///
///**NOTE**: available only on Android.
// ignore: missing_return
Future<GeolocationPermissionShowPromptResponse>
onGeolocationPermissionsShowPrompt(String origin) {}
void onCreateWindow(OnCreateWindowRequest onCreateWindowRequest) {}
///Event fired when javascript calls the `alert()` method to display an alert dialog.
///If [JsAlertResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
@ -441,18 +430,6 @@ class InAppBrowser {
// ignore: missing_return
Future<JsPromptResponse> onJsPrompt(String message, String defaultValue) {}
///Event fired when the WebView notifies that a loading URL has been flagged by Safe Browsing.
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
///
///[url] represents the url of the request.
///
///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat].
///
///**NOTE**: available only on Android.
// ignore: missing_return
Future<SafeBrowsingResponse> onSafeBrowsingHit(
String url, SafeBrowsingThreat threatType) {}
///Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
///
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [HttpAuthChallenge].
@ -525,13 +502,34 @@ class InAppBrowser {
// ignore: missing_return
Future<FetchRequest> shouldInterceptFetchRequest(FetchRequest fetchRequest) {}
///Event fired when the navigation state of the WebView changes throught the usage of
///javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions (`pushState()`, `replaceState()`) and `onpopstate` event.
///Event fired when the host application updates its visited links database.
///This event is also fired when the navigation state of the [InAppWebView] changes through the usage of
///javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions (`pushState()`, `replaceState()`) and `onpopstate` event
///or, also, when the javascript `window.location` changes without reloading the webview (for example appending or modifying an hash to the url).
///
///Also, the event is fired when the javascript `window.location` changes without reloading the webview (for example appending or modifying an hash to the url).
///[url] represents the url being visited.
///
///[url] represents the new url.
void onNavigationStateChange(String url) {}
///[androidIsReload] indicates if this url is being reloaded. Available only on Android.
void onUpdateVisitedHistory(String url, bool androidIsReload) {}
///Event fired when `window.print()` is called from JavaScript side.
///
///[url] represents the url on which is called.
///
///**NOTE**: available on Android 21+.
void onPrint(String url) {}
///Event fired when the WebView notifies that a loading URL has been flagged by Safe Browsing.
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
///
///[url] represents the url of the request.
///
///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat].
///
///**NOTE**: available only on Android 27+.
// ignore: missing_return
Future<SafeBrowsingResponse> androidOnSafeBrowsingHit(
String url, SafeBrowsingThreat threatType) {}
///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied.
///
@ -541,15 +539,25 @@ class InAppBrowser {
///
///**NOTE**: available only on Android 23+.
// ignore: missing_return
Future<PermissionRequestResponse> onPermissionRequest(
Future<PermissionRequestResponse> androidOnPermissionRequest(
String origin, List<String> resources) {}
///Event fired when `window.print()` is called from JavaScript side.
///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin.
///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https.
///On non-secure origins geolocation requests are automatically denied.
///
///[url] represents the url on which is called.
///[origin] represents the origin of the web content attempting to use the Geolocation API.
///
///**NOTE**: available on Android 21+.
void onPrint(String url) {}
///**NOTE**: available only on Android.
Future<GeolocationPermissionShowPromptResponse>
// ignore: missing_return
androidOnGeolocationPermissionsShowPrompt(String origin) {}
///Notify the host application that a request for Geolocation permissions, made with a previous call to [androidOnGeolocationPermissionsShowPrompt] has been canceled.
///Any related UI should therefore be hidden.
///
///**NOTE**: available only on Android.
void androidOnGeolocationPermissionsHidePrompt() {}
void throwIsAlreadyOpened({String message = ''}) {
if (this.isOpened()) {

View File

@ -115,23 +115,12 @@ class InAppWebView extends StatefulWidget {
///Event fired when the [InAppWebView] requests the host application to create a new window,
///for example when trying to open a link with `target="_blank"` or when `window.open()` is called by JavaScript side.
///
///[url] represents the url of the request.
///[onCreateWindowRequest] represents the request.
///
///**NOTE**: on Android you need to set [AndroidInAppWebViewOptions.supportMultipleWindows] option to `true`.
final void Function(InAppWebViewController controller, String url)
final void Function(InAppWebViewController controller, OnCreateWindowRequest onCreateWindowRequest)
onCreateWindow;
///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin.
///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https.
///On non-secure origins geolocation requests are automatically denied.
///
///[origin] represents the origin of the web content attempting to use the Geolocation API.
///
///**NOTE**: available only on Android.
final Future<GeolocationPermissionShowPromptResponse> Function(
InAppWebViewController controller, String origin)
onGeolocationPermissionsShowPrompt;
///Event fired when javascript calls the `alert()` method to display an alert dialog.
///If [JsAlertResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
///
@ -155,17 +144,6 @@ class InAppWebView extends StatefulWidget {
final Future<JsPromptResponse> Function(InAppWebViewController controller,
String message, String defaultValue) onJsPrompt;
///Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing.
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
///
///[url] represents the url of the request.
///
///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat].
///
///**NOTE**: available only on Android.
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller,
String url, SafeBrowsingThreat threatType) onSafeBrowsingHit;
///Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
///
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [HttpAuthChallenge].
@ -258,14 +236,33 @@ class InAppWebView extends StatefulWidget {
InAppWebViewController controller, FetchRequest fetchRequest)
shouldInterceptFetchRequest;
///Event fired when the navigation state of the [InAppWebView] changes through the usage of
///javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions (`pushState()`, `replaceState()`) and `onpopstate` event.
///Event fired when the host application updates its visited links database.
///This event is also fired when the navigation state of the [InAppWebView] changes through the usage of
///javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions (`pushState()`, `replaceState()`) and `onpopstate` event
///or, also, when the javascript `window.location` changes without reloading the webview (for example appending or modifying an hash to the url).
///
///Also, the event is fired when the javascript `window.location` changes without reloading the webview (for example appending or modifying an hash to the url).
///[url] represents the url being visited.
///
///[url] represents the new url.
final void Function(InAppWebViewController controller, String url)
onNavigationStateChange;
///[androidIsReload] indicates if this url is being reloaded. Available only on Android.
final void Function(InAppWebViewController controller, String url, bool androidIsReload) onUpdateVisitedHistory;
///Event fired when `window.print()` is called from JavaScript side.
///
///[url] represents the url on which is called.
///
///**NOTE**: available on Android 21+.
final void Function(InAppWebViewController controller, String url) onPrint;
///Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing.
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
///
///[url] represents the url of the request.
///
///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat].
///
///**NOTE**: available only on Android 27+.
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller,
String url, SafeBrowsingThreat threatType) androidOnSafeBrowsingHit;
///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied.
///
@ -277,14 +274,24 @@ class InAppWebView extends StatefulWidget {
final Future<PermissionRequestResponse> Function(
InAppWebViewController controller,
String origin,
List<String> resources) onPermissionRequest;
List<String> resources) androidOnPermissionRequest;
///Event fired when `window.print()` is called from JavaScript side.
///Event that notifies the host application that web content from the specified origin is attempting to use the Geolocation API, but no permission state is currently set for that origin.
///Note that for applications targeting Android N and later SDKs (API level > `Build.VERSION_CODES.M`) this method is only called for requests originating from secure origins such as https.
///On non-secure origins geolocation requests are automatically denied.
///
///[url] represents the url on which is called.
///[origin] represents the origin of the web content attempting to use the Geolocation API.
///
///**NOTE**: available on Android 21+.
final void Function(InAppWebViewController controller, String url) onPrint;
///**NOTE**: available only on Android.
final Future<GeolocationPermissionShowPromptResponse> Function(
InAppWebViewController controller, String origin)
androidOnGeolocationPermissionsShowPrompt;
///Notify the host application that a request for Geolocation permissions, made with a previous call to [androidOnGeolocationPermissionsShowPrompt] has been canceled.
///Any related UI should therefore be hidden.
///
///**NOTE**: available only on Android.
final Future<void> Function(InAppWebViewController controller) androidOnGeolocationPermissionsHidePrompt;
///Initial url that will be loaded.
final String initialUrl;
@ -330,11 +337,9 @@ class InAppWebView extends StatefulWidget {
this.onDownloadStart,
this.onLoadResourceCustomScheme,
this.onCreateWindow,
this.onGeolocationPermissionsShowPrompt,
this.onJsAlert,
this.onJsConfirm,
this.onJsPrompt,
this.onSafeBrowsingHit,
this.onReceivedHttpAuthRequest,
this.onReceivedServerTrustAuthRequest,
this.onReceivedClientCertRequest,
@ -343,9 +348,12 @@ class InAppWebView extends StatefulWidget {
this.onAjaxReadyStateChange,
this.onAjaxProgress,
this.shouldInterceptFetchRequest,
this.onNavigationStateChange,
this.onPermissionRequest,
this.onUpdateVisitedHistory,
this.onPrint,
this.androidOnSafeBrowsingHit,
this.androidOnPermissionRequest,
this.androidOnGeolocationPermissionsShowPrompt,
this.androidOnGeolocationPermissionsHidePrompt,
this.gestureRecognizers,
}) : super(key: key);
@ -360,13 +368,13 @@ class _InAppWebViewState extends State<InAppWebView> {
Widget build(BuildContext context) {
Map<String, dynamic> initialOptions = {};
initialOptions
.addAll(widget.initialOptions.inAppWebViewOptions?.toMap() ?? {});
.addAll(widget.initialOptions.crossPlatform?.toMap() ?? {});
if (Platform.isAndroid)
initialOptions.addAll(
widget.initialOptions.androidInAppWebViewOptions?.toMap() ?? {});
widget.initialOptions.android?.toMap() ?? {});
else if (Platform.isIOS)
initialOptions
.addAll(widget.initialOptions.iosInAppWebViewOptions?.toMap() ?? {});
.addAll(widget.initialOptions.ios?.toMap() ?? {});
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(
@ -439,10 +447,10 @@ class _InAppWebViewState extends State<InAppWebView> {
}
}
/// Controls an [InAppWebView] widget instance.
/// Controls a WebView, such as an [InAppWebView] widget instance or [InAppBrowser] WebView instance.
///
/// An [InAppWebViewController] instance can be obtained by setting the [InAppWebView.onWebViewCreated]
/// callback for an [InAppWebView] widget.
/// If you are using the [InAppWebView] widget, an [InAppWebViewController] instance can be obtained by setting the [InAppWebView.onWebViewCreated]
/// callback. Instead, if you are using an [InAppBrowser] instance, you can get it through the [InAppBrowser.webViewController] attribute.
class InAppWebViewController {
InAppWebView _widget;
MethodChannel _channel;
@ -456,12 +464,20 @@ class InAppWebViewController {
String _inAppBrowserUuid;
InAppBrowser _inAppBrowser;
///Android controller that contains only android-specific methods
AndroidInAppWebViewController android;
///iOS controller that contains only ios-specific methods
IOSInAppWebViewController ios;
InAppWebViewController(int id, InAppWebView widget) {
this._id = id;
this._channel =
MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id');
this._channel.setMethodCallHandler(handleMethod);
this._widget = widget;
this.android = AndroidInAppWebViewController(this);
this.ios = IOSInAppWebViewController(this);
}
InAppWebViewController.fromInAppBrowser(
@ -520,7 +536,7 @@ class InAppWebViewController {
int iosWKNavigationType = call.arguments["iosWKNavigationType"];
ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest = ShouldOverrideUrlLoadingRequest(url: url, method: method, headers: headers, isForMainFrame: isForMainFrame,
androidHasGesture: androidHasGesture, androidIsRedirect: androidIsRedirect, iosWKNavigationType: IosWKNavigationType.fromValue(iosWKNavigationType));
androidHasGesture: androidHasGesture, androidIsRedirect: androidIsRedirect, iosWKNavigationType: IOSWKNavigationType.fromValue(iosWKNavigationType));
if (_widget != null && _widget.shouldOverrideUrlLoading != null)
return (await _widget.shouldOverrideUrlLoading(this, shouldOverrideUrlLoadingRequest))?.toMap();
@ -576,22 +592,37 @@ class InAppWebViewController {
break;
case "onCreateWindow":
String url = call.arguments["url"];
bool androidIsDialog = call.arguments["androidIsDialog"];
bool androidIsUserGesture = call.arguments["androidIsUserGesture"];
int iosWKNavigationType = call.arguments["iosWKNavigationType"];
OnCreateWindowRequest onCreateWindowRequest = OnCreateWindowRequest(url: url, androidIsDialog: androidIsDialog, androidIsUserGesture: androidIsUserGesture, iosWKNavigationType: IOSWKNavigationType.fromValue(iosWKNavigationType));
if (_widget != null && _widget.onCreateWindow != null)
_widget.onCreateWindow(this, url);
else if (_inAppBrowser != null) _inAppBrowser.onCreateWindow(url);
_widget.onCreateWindow(this, onCreateWindowRequest);
else if (_inAppBrowser != null) _inAppBrowser.onCreateWindow(onCreateWindowRequest);
break;
case "onGeolocationPermissionsShowPrompt":
String origin = call.arguments["origin"];
if (_widget != null &&
_widget.onGeolocationPermissionsShowPrompt != null)
return (await _widget.onGeolocationPermissionsShowPrompt(
_widget.androidOnGeolocationPermissionsShowPrompt != null)
return (await _widget.androidOnGeolocationPermissionsShowPrompt(
this, origin))
?.toMap();
else if (_inAppBrowser != null)
return (await _inAppBrowser
.onGeolocationPermissionsShowPrompt(origin))
.androidOnGeolocationPermissionsShowPrompt(origin))
?.toMap();
break;
case "onGeolocationPermissionsHidePrompt":
if (_widget != null &&
_widget.androidOnGeolocationPermissionsHidePrompt != null)
await _widget.androidOnGeolocationPermissionsHidePrompt(
this);
else if (_inAppBrowser != null)
await _inAppBrowser
.androidOnGeolocationPermissionsHidePrompt();
break;
case "onJsAlert":
String message = call.arguments["message"];
if (_widget != null && _widget.onJsAlert != null)
@ -620,11 +651,11 @@ class InAppWebViewController {
String url = call.arguments["url"];
SafeBrowsingThreat threatType =
SafeBrowsingThreat.fromValue(call.arguments["threatType"]);
if (_widget != null && _widget.onSafeBrowsingHit != null)
return (await _widget.onSafeBrowsingHit(this, url, threatType))
if (_widget != null && _widget.androidOnSafeBrowsingHit != null)
return (await _widget.androidOnSafeBrowsingHit(this, url, threatType))
?.toMap();
else if (_inAppBrowser != null)
return (await _inAppBrowser.onSafeBrowsingHit(url, threatType))
return (await _inAppBrowser.androidOnSafeBrowsingHit(url, threatType))
?.toMap();
break;
case "onReceivedHttpAuthRequest":
@ -695,23 +726,24 @@ class InAppWebViewController {
_inAppBrowser.onFindResultReceived(
activeMatchOrdinal, numberOfMatches, isDoneCounting);
break;
case "onNavigationStateChange":
String url = call.arguments["url"];
if (_widget != null && _widget.onNavigationStateChange != null)
_widget.onNavigationStateChange(this, url);
else if (_inAppBrowser != null)
_inAppBrowser.onNavigationStateChange(url);
break;
case "onPermissionRequest":
String origin = call.arguments["origin"];
List<String> resources = call.arguments["resources"].cast<String>();
if (_widget != null && _widget.onPermissionRequest != null)
return (await _widget.onPermissionRequest(this, origin, resources))
if (_widget != null && _widget.androidOnPermissionRequest != null)
return (await _widget.androidOnPermissionRequest(this, origin, resources))
?.toMap();
else if (_inAppBrowser != null)
return (await _inAppBrowser.onPermissionRequest(origin, resources))
return (await _inAppBrowser.androidOnPermissionRequest(origin, resources))
?.toMap();
break;
case "onUpdateVisitedHistory":
String url = call.arguments["url"];
bool androidIsReload = call.arguments["androidIsReload"];
if (_widget != null && _widget.onUpdateVisitedHistory != null)
_widget.onUpdateVisitedHistory(this, url, androidIsReload);
else if (_inAppBrowser != null)
_inAppBrowser.onUpdateVisitedHistory(url, androidIsReload);
return null;
case "onCallJsHandler":
String handlerName = call.arguments["handlerName"];
// decode args to json
@ -969,7 +1001,7 @@ class InAppWebViewController {
var html = "";
InAppWebViewWidgetOptions options = await getOptions();
if (options != null &&
options.inAppWebViewOptions.javaScriptEnabled == true) {
options.crossPlatform.javaScriptEnabled == true) {
html = await evaluateJavascript(
source: "window.document.getElementsByTagName('html')[0].outerHTML;");
if (html != null && html.isNotEmpty) return html;
@ -1158,13 +1190,13 @@ class InAppWebViewController {
///
///The [encoding] parameter specifies the encoding of the data. The default value is `"utf8"`.
///
///The [historyUrl] 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.
///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.
Future<void> loadData(
{@required String data,
String mimeType = "text/html",
String encoding = "utf8",
String baseUrl = "about:blank",
String historyUrl = "about:blank"}) async {
String androidHistoryUrl = "about:blank"}) async {
assert(data != null);
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
@ -1175,7 +1207,7 @@ class InAppWebViewController {
args.putIfAbsent('mimeType', () => mimeType);
args.putIfAbsent('encoding', () => encoding);
args.putIfAbsent('baseUrl', () => baseUrl);
args.putIfAbsent('historyUrl', () => historyUrl);
args.putIfAbsent('historyUrl', () => androidHistoryUrl);
await _channel.invokeMethod('loadData', args);
}
@ -1464,11 +1496,11 @@ class InAppWebViewController {
}
Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppWebViewOptions?.toMap() ?? {});
optionsMap.addAll(options.crossPlatform?.toMap() ?? {});
if (Platform.isAndroid)
optionsMap.addAll(options.androidInAppWebViewOptions?.toMap() ?? {});
optionsMap.addAll(options.android?.toMap() ?? {});
else if (Platform.isIOS)
optionsMap.addAll(options.iosInAppWebViewOptions?.toMap() ?? {});
optionsMap.addAll(options.ios?.toMap() ?? {});
args.putIfAbsent('options', () => optionsMap);
await _channel.invokeMethod('setOptions', args);
@ -1488,14 +1520,14 @@ class InAppWebViewController {
await _channel.invokeMethod('getOptions', args);
if (options != null) {
options = options.cast<String, dynamic>();
inAppWebViewWidgetOptions.inAppWebViewOptions =
inAppWebViewWidgetOptions.crossPlatform =
InAppWebViewOptions.fromMap(options);
if (Platform.isAndroid)
inAppWebViewWidgetOptions.androidInAppWebViewOptions =
inAppWebViewWidgetOptions.android =
AndroidInAppWebViewOptions.fromMap(options);
else if (Platform.isIOS)
inAppWebViewWidgetOptions.iosInAppWebViewOptions =
IosInAppWebViewOptions.fromMap(options);
inAppWebViewWidgetOptions.ios =
IOSInAppWebViewOptions.fromMap(options);
}
return inAppWebViewWidgetOptions;
@ -1533,62 +1565,6 @@ class InAppWebViewController {
return WebHistory(list: historyList, currentIndex: currentIndex);
}
///Starts Safe Browsing initialization.
///
///URL loads are not guaranteed to be protected by Safe Browsing until after the this method returns true.
///Safe Browsing is not fully supported on all devices. For those devices this method will returns false.
///
///This should not be called if Safe Browsing has been disabled by manifest tag
///or [AndroidInAppWebViewOptions.safeBrowsingEnabled]. This prepares resources used for Safe Browsing.
///
///**NOTE**: available only on Android 27+.
Future<bool> startSafeBrowsing() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
return await _channel.invokeMethod('startSafeBrowsing', args);
}
///Sets the list of hosts (domain names/IP addresses) that are exempt from SafeBrowsing checks. The list is global for all the WebViews.
///
/// Each rule should take one of these:
///| Rule | Example | Matches Subdomain |
///| -- | -- | -- |
///| HOSTNAME | example.com | Yes |
///| .HOSTNAME | .example.com | No |
///| IPV4_LITERAL | 192.168.1.1 | No |
///| IPV6_LITERAL_WITH_BRACKETS | [10:20:30:40:50:60:70:80] | No |
///
///All other rules, including wildcards, are invalid. The correct syntax for hosts is defined by [RFC 3986](https://tools.ietf.org/html/rfc3986#section-3.2.2).
///
///[hosts] represents the list of hosts. This value must never be null.
///
///**NOTE**: available only on Android 27+.
Future<bool> setSafeBrowsingWhitelist({@required List<String> hosts}) async {
assert(hosts != null);
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
args.putIfAbsent('hosts', () => hosts);
return await _channel.invokeMethod('setSafeBrowsingWhitelist', args);
}
///Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`.
///
///**NOTE**: available only on Android 27+.
Future<String> getSafeBrowsingPrivacyPolicyUrl() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
return await _channel.invokeMethod('getSafeBrowsingPrivacyPolicyUrl', args);
}
///Clears all the webview's cache.
Future<void> clearCache() async {
Map<String, dynamic> args = <String, dynamic>{};
@ -1599,34 +1575,6 @@ class InAppWebViewController {
await _channel.invokeMethod('clearCache', args);
}
///Clears the SSL preferences table stored in response to proceeding with SSL certificate errors.
///
///**NOTE**: available only on Android.
Future<void> clearSslPreferences() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
await _channel.invokeMethod('clearSslPreferences', args);
}
///Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests.
///Note that WebView automatically clears these preferences when the system keychain is updated.
///The preferences are shared by all the WebViews that are created by the embedder application.
///
///**NOTE**: On iOS certificate-based credentials are never stored permanently.
///
///**NOTE**: available on Android 21+.
Future<void> clearClientCertPreferences() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
await _channel.invokeMethod('clearClientCertPreferences', args);
}
///Finds all instances of find on the page and highlights them. Notifies [onFindResultReceived] listener.
///
///[find] represents the string to find.
@ -1719,31 +1667,6 @@ class InAppWebViewController {
await _channel.invokeMethod('scrollBy', args);
}
///Does a best-effort attempt to pause any processing that can be paused safely, such as animations and geolocation. Note that this call does not pause JavaScript.
///To pause JavaScript globally, use [pauseTimers()]. To resume WebView, call [resume()].
///
///**NOTE**: available only on Android.
Future<void> pause() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
await _channel.invokeMethod('pause', args);
}
///Resumes a WebView after a previous call to [pause()].
///
///**NOTE**: available only on Android.
Future<void> resume() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
await _channel.invokeMethod('resume', args);
}
///On Android, it pauses all layout, parsing, and JavaScript timers for all WebViews.
///This is a global requests, not restricted to just this WebView. This can be useful if the application has been paused.
///
@ -1781,15 +1704,189 @@ class InAppWebViewController {
await _channel.invokeMethod('printCurrentPage', args);
}
///Gets the height of the HTML content.
Future<int> getContentHeight() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
return await _channel.invokeMethod('getContentHeight', args);
}
///Gets the height of the HTML content.
///
///[zoomFactor] represents the zoom factor to apply. On Android, the zoom factor will be clamped to the Webview's zoom limits and, also, this value must be in the range 0.01 to 100.0 inclusive.
///
///**NOTE**: available on Android 21+.
Future<void> zoomBy(double zoomFactor) async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
args.putIfAbsent('zoomFactor', () => zoomFactor);
return await _channel.invokeMethod('zoomBy', args);
}
///Gets the current scale of this WebView.
Future<double> getScale() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
return await _channel.invokeMethod('getScale', args);
}
///Gets the default user agent.
static Future<String> getDefaultUserAgent() async {
Map<String, dynamic> args = <String, dynamic>{};
return await _staticChannel.invokeMethod('getDefaultUserAgent', args);
}
/*Future<void> dispose() async {
Map<String, dynamic> args = <String, dynamic>{};
if (Platform.isIOS)
await _channel.invokeMethod('removeFromSuperview', args);
}*/
}
///InAppWebViewControllerAndroid class represents the Android controller that contains only android-specific methods for the WebView.
class AndroidInAppWebViewController {
InAppWebViewController _controller;
AndroidInAppWebViewController(InAppWebViewController controller) {
this._controller = controller;
}
///Starts Safe Browsing initialization.
///
///URL loads are not guaranteed to be protected by Safe Browsing until after the this method returns true.
///Safe Browsing is not fully supported on all devices. For those devices this method will returns false.
///
///This should not be called if Safe Browsing has been disabled by manifest tag
///or [AndroidInAppWebViewOptions.safeBrowsingEnabled]. This prepares resources used for Safe Browsing.
///
///**NOTE**: available only on Android 27+.
Future<bool> startSafeBrowsing() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_controller._inAppBrowserUuid != null && _controller._inAppBrowser != null) {
_controller._inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _controller._inAppBrowserUuid);
}
return await _controller._channel.invokeMethod('startSafeBrowsing', args);
}
///Sets the list of hosts (domain names/IP addresses) that are exempt from SafeBrowsing checks. The list is global for all the WebViews.
///
/// Each rule should take one of these:
///| Rule | Example | Matches Subdomain |
///| -- | -- | -- |
///| HOSTNAME | example.com | Yes |
///| .HOSTNAME | .example.com | No |
///| IPV4_LITERAL | 192.168.1.1 | No |
///| IPV6_LITERAL_WITH_BRACKETS | [10:20:30:40:50:60:70:80] | No |
///
///All other rules, including wildcards, are invalid. The correct syntax for hosts is defined by [RFC 3986](https://tools.ietf.org/html/rfc3986#section-3.2.2).
///
///[hosts] represents the list of hosts. This value must never be null.
///
///**NOTE**: available only on Android 27+.
Future<bool> setSafeBrowsingWhitelist({@required List<String> hosts}) async {
assert(hosts != null);
Map<String, dynamic> args = <String, dynamic>{};
if (_controller._inAppBrowserUuid != null && _controller._inAppBrowser != null) {
_controller._inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _controller._inAppBrowserUuid);
}
args.putIfAbsent('hosts', () => hosts);
return await _controller._channel.invokeMethod('setSafeBrowsingWhitelist', args);
}
///Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`.
///
///**NOTE**: available only on Android 27+.
Future<String> getSafeBrowsingPrivacyPolicyUrl() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_controller._inAppBrowserUuid != null && _controller._inAppBrowser != null) {
_controller._inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _controller._inAppBrowserUuid);
}
return await _controller._channel.invokeMethod('getSafeBrowsingPrivacyPolicyUrl', args);
}
///Clears the SSL preferences table stored in response to proceeding with SSL certificate errors.
Future<void> clearSslPreferences() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_controller._inAppBrowserUuid != null && _controller._inAppBrowser != null) {
_controller._inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _controller._inAppBrowserUuid);
}
await _controller._channel.invokeMethod('clearSslPreferences', args);
}
///Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests.
///Note that WebView automatically clears these preferences when the system keychain is updated.
///The preferences are shared by all the WebViews that are created by the embedder application.
///
///**NOTE**: On iOS certificate-based credentials are never stored permanently.
///
///**NOTE**: available on Android 21+.
Future<void> clearClientCertPreferences() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_controller._inAppBrowserUuid != null && _controller._inAppBrowser != null) {
_controller._inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _controller._inAppBrowserUuid);
}
await _controller._channel.invokeMethod('clearClientCertPreferences', args);
}
///Does a best-effort attempt to pause any processing that can be paused safely, such as animations and geolocation. Note that this call does not pause JavaScript.
///To pause JavaScript globally, use [pauseTimers()]. To resume WebView, call [resume()].
Future<void> pause() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_controller._inAppBrowserUuid != null && _controller._inAppBrowser != null) {
_controller._inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _controller._inAppBrowserUuid);
}
await _controller._channel.invokeMethod('pause', args);
}
///Resumes a WebView after a previous call to [pause()].
Future<void> resume() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_controller._inAppBrowserUuid != null && _controller._inAppBrowser != null) {
_controller._inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _controller._inAppBrowserUuid);
}
await _controller._channel.invokeMethod('resume', args);
}
///Gets the URL that was originally requested for the current page.
///This is not always the same as the URL passed to [InAppWebView.onLoadStarted] because although the load for that URL has begun,
///the current page may not have changed. Also, there may have been redirects resulting in a different URL to that originally requested.
Future<String> getOriginalUrl() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_controller._inAppBrowserUuid != null && _controller._inAppBrowser != null) {
_controller._inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _controller._inAppBrowserUuid);
}
return await _controller._channel.invokeMethod('getOriginalUrl', args);
}
}
///InAppWebViewControllerIOS class represents the iOS controller that contains only ios-specific methods for the WebView.
class IOSInAppWebViewController {
InAppWebViewController _controller;
IOSInAppWebViewController(InAppWebViewController controller) {
this._controller = controller;
}
///Reloads the current page, performing end-to-end revalidation using cache-validating conditionals if possible.
Future<void> reloadFromOrigin() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_controller._inAppBrowserUuid != null && _controller._inAppBrowser != null) {
_controller._inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _controller._inAppBrowserUuid);
}
await _controller._channel.invokeMethod('reloadFromOrigin', args);
}
}

View File

@ -223,7 +223,7 @@ class WebHistoryItem {
///GeolocationPermissionPromptResponse class.
///
///Class used by the host application to set the Geolocation permission state for an origin during the [onGeolocationPermissionsShowPrompt] event.
///Class used by the host application to set the Geolocation permission state for an origin during the [androidOnGeolocationPermissionsShowPrompt] event.
class GeolocationPermissionShowPromptResponse {
///The origin for which permissions are set.
String origin;
@ -462,10 +462,10 @@ class SafeBrowsingResponseAction {
int get hashCode => _value.hashCode;
}
///SafeBrowsingResponse class represents the response used by the [onSafeBrowsingHit] event.
///SafeBrowsingResponse class represents the response used by the [androidOnSafeBrowsingHit] event.
///It is used to indicate an action to take when hitting a malicious URL.
class SafeBrowsingResponse {
///If reporting is enabled, all reports will be sent according to the privacy policy referenced by [InAppWebViewController.getSafeBrowsingPrivacyPolicyUrl].
///If reporting is enabled, all reports will be sent according to the privacy policy referenced by [InAppWebViewController.androidGetSafeBrowsingPrivacyPolicyUrl].
bool report;
///Indicate the [SafeBrowsingResponseAction] to take when hitting a malicious URL.
@ -944,13 +944,13 @@ class AndroidInAppWebViewMixedContentMode {
int get hashCode => _value.hashCode;
}
///IosInAppWebViewSelectionGranularity class represents an iOS-specific class used to set the level of granularity with which the user can interactively select content in the web view.
class IosInAppWebViewSelectionGranularity {
///IOSInAppWebViewSelectionGranularity class represents an iOS-specific class used to set the level of granularity with which the user can interactively select content in the web view.
class IOSInAppWebViewSelectionGranularity {
final int _value;
const IosInAppWebViewSelectionGranularity._internal(this._value);
static IosInAppWebViewSelectionGranularity fromValue(int value) {
const IOSInAppWebViewSelectionGranularity._internal(this._value);
static IOSInAppWebViewSelectionGranularity fromValue(int value) {
if (value != null && value >= 0 && value <= 1)
return IosInAppWebViewSelectionGranularity._internal(value);
return IOSInAppWebViewSelectionGranularity._internal(value);
return null;
}
@ -967,11 +967,11 @@ class IosInAppWebViewSelectionGranularity {
}
///Selection granularity varies automatically based on the selection.
static const DYNAMIC = const IosInAppWebViewSelectionGranularity._internal(0);
static const DYNAMIC = const IOSInAppWebViewSelectionGranularity._internal(0);
///Selection endpoints can be placed at any character boundary.
static const CHARACTER =
const IosInAppWebViewSelectionGranularity._internal(1);
const IOSInAppWebViewSelectionGranularity._internal(1);
bool operator ==(value) => value == _value;
@ -979,13 +979,13 @@ class IosInAppWebViewSelectionGranularity {
int get hashCode => _value.hashCode;
}
///IosInAppWebViewDataDetectorTypes class represents an iOS-specific class used to specify a dataDetectoryTypes value that adds interactivity to web content that matches the value.
///IOSInAppWebViewDataDetectorTypes class represents an iOS-specific class used to specify a dataDetectoryTypes value that adds interactivity to web content that matches the value.
///
///**NOTE**: available on iOS 10.0+.
class IosInAppWebViewDataDetectorTypes {
class IOSInAppWebViewDataDetectorTypes {
final String _value;
const IosInAppWebViewDataDetectorTypes._internal(this._value);
static IosInAppWebViewDataDetectorTypes fromValue(String value) {
const IOSInAppWebViewDataDetectorTypes._internal(this._value);
static IOSInAppWebViewDataDetectorTypes fromValue(String value) {
return ([
"NONE",
"PHONE_NUMBER",
@ -999,7 +999,7 @@ class IosInAppWebViewDataDetectorTypes {
"SPOTLIGHT_SUGGESTION",
"ALL"
].contains(value))
? IosInAppWebViewDataDetectorTypes._internal(value)
? IOSInAppWebViewDataDetectorTypes._internal(value)
: null;
}
@ -1008,41 +1008,41 @@ class IosInAppWebViewDataDetectorTypes {
String toString() => _value;
///No detection is performed.
static const NONE = const IosInAppWebViewDataDetectorTypes._internal("NONE");
static const NONE = const IOSInAppWebViewDataDetectorTypes._internal("NONE");
///Phone numbers are detected and turned into links.
static const PHONE_NUMBER =
const IosInAppWebViewDataDetectorTypes._internal("PHONE_NUMBER");
const IOSInAppWebViewDataDetectorTypes._internal("PHONE_NUMBER");
///URLs in text are detected and turned into links.
static const LINK = const IosInAppWebViewDataDetectorTypes._internal("LINK");
static const LINK = const IOSInAppWebViewDataDetectorTypes._internal("LINK");
///Addresses are detected and turned into links.
static const ADDRESS =
const IosInAppWebViewDataDetectorTypes._internal("ADDRESS");
const IOSInAppWebViewDataDetectorTypes._internal("ADDRESS");
///Dates and times that are in the future are detected and turned into links.
static const CALENDAR_EVENT =
const IosInAppWebViewDataDetectorTypes._internal("CALENDAR_EVENT");
const IOSInAppWebViewDataDetectorTypes._internal("CALENDAR_EVENT");
///Tracking numbers are detected and turned into links.
static const TRACKING_NUMBER =
const IosInAppWebViewDataDetectorTypes._internal("TRACKING_NUMBER");
const IOSInAppWebViewDataDetectorTypes._internal("TRACKING_NUMBER");
///Flight numbers are detected and turned into links.
static const FLIGHT_NUMBER =
const IosInAppWebViewDataDetectorTypes._internal("FLIGHT_NUMBER");
const IOSInAppWebViewDataDetectorTypes._internal("FLIGHT_NUMBER");
///Lookup suggestions are detected and turned into links.
static const LOOKUP_SUGGESTION =
const IosInAppWebViewDataDetectorTypes._internal("LOOKUP_SUGGESTION");
const IOSInAppWebViewDataDetectorTypes._internal("LOOKUP_SUGGESTION");
///Spotlight suggestions are detected and turned into links.
static const SPOTLIGHT_SUGGESTION =
const IosInAppWebViewDataDetectorTypes._internal("SPOTLIGHT_SUGGESTION");
const IOSInAppWebViewDataDetectorTypes._internal("SPOTLIGHT_SUGGESTION");
///All of the above data types are turned into links when detected. Choosing this value will automatically include any new detection type that is added.
static const ALL = const IosInAppWebViewDataDetectorTypes._internal("ALL");
static const ALL = const IOSInAppWebViewDataDetectorTypes._internal("ALL");
bool operator ==(value) => value == _value;
@ -1091,13 +1091,13 @@ class InAppWebViewUserPreferredContentMode {
int get hashCode => _value.hashCode;
}
///IosWebViewOptionsPresentationStyle class represents an iOS-specific class used to specify the modal presentation style when presenting a view controller.
class IosWebViewOptionsPresentationStyle {
///IOSWebViewOptionsPresentationStyle class represents an iOS-specific class used to specify the modal presentation style when presenting a view controller.
class IOSWebViewOptionsPresentationStyle {
final int _value;
const IosWebViewOptionsPresentationStyle._internal(this._value);
static IosWebViewOptionsPresentationStyle fromValue(int value) {
const IOSWebViewOptionsPresentationStyle._internal(this._value);
static IOSWebViewOptionsPresentationStyle fromValue(int value) {
if (value != null && value >= 0 && value <= 9)
return IosWebViewOptionsPresentationStyle._internal(value);
return IOSWebViewOptionsPresentationStyle._internal(value);
return null;
}
@ -1131,42 +1131,42 @@ class IosWebViewOptionsPresentationStyle {
///A presentation style in which the presented view covers the screen.
static const FULL_SCREEN =
const IosWebViewOptionsPresentationStyle._internal(0);
const IOSWebViewOptionsPresentationStyle._internal(0);
///A presentation style that partially covers the underlying content.
static const PAGE_SHEET =
const IosWebViewOptionsPresentationStyle._internal(1);
const IOSWebViewOptionsPresentationStyle._internal(1);
///A presentation style that displays the content centered in the screen.
static const FORM_SHEET =
const IosWebViewOptionsPresentationStyle._internal(2);
const IOSWebViewOptionsPresentationStyle._internal(2);
///A presentation style where the content is displayed over another view controllers content.
static const CURRENT_CONTEXT =
const IosWebViewOptionsPresentationStyle._internal(3);
const IOSWebViewOptionsPresentationStyle._internal(3);
///A custom view presentation style that is managed by a custom presentation controller and one or more custom animator objects.
static const CUSTOM = const IosWebViewOptionsPresentationStyle._internal(4);
static const CUSTOM = const IOSWebViewOptionsPresentationStyle._internal(4);
///A view presentation style in which the presented view covers the screen.
static const OVER_FULL_SCREEN =
const IosWebViewOptionsPresentationStyle._internal(5);
const IOSWebViewOptionsPresentationStyle._internal(5);
///A presentation style where the content is displayed over another view controllers content.
static const OVER_CURRENT_CONTEXT =
const IosWebViewOptionsPresentationStyle._internal(6);
const IOSWebViewOptionsPresentationStyle._internal(6);
///A presentation style where the content is displayed in a popover view.
static const POPOVER = const IosWebViewOptionsPresentationStyle._internal(7);
static const POPOVER = const IOSWebViewOptionsPresentationStyle._internal(7);
///A presentation style that indicates no adaptations should be made.
static const NONE = const IosWebViewOptionsPresentationStyle._internal(8);
static const NONE = const IOSWebViewOptionsPresentationStyle._internal(8);
///The default presentation style chosen by the system.
///
///**NOTE**: available on iOS 13.0+.
static const AUTOMATIC =
const IosWebViewOptionsPresentationStyle._internal(9);
const IOSWebViewOptionsPresentationStyle._internal(9);
bool operator ==(value) => value == _value;
@ -1174,13 +1174,13 @@ class IosWebViewOptionsPresentationStyle {
int get hashCode => _value.hashCode;
}
///IosWebViewOptionsTransitionStyle class represents an iOS-specific class used to specify the transition style when presenting a view controller.
class IosWebViewOptionsTransitionStyle {
///IOSWebViewOptionsTransitionStyle class represents an iOS-specific class used to specify the transition style when presenting a view controller.
class IOSWebViewOptionsTransitionStyle {
final int _value;
const IosWebViewOptionsTransitionStyle._internal(this._value);
static IosWebViewOptionsTransitionStyle fromValue(int value) {
const IOSWebViewOptionsTransitionStyle._internal(this._value);
static IOSWebViewOptionsTransitionStyle fromValue(int value) {
if (value != null && value >= 0 && value <= 3)
return IosWebViewOptionsTransitionStyle._internal(value);
return IOSWebViewOptionsTransitionStyle._internal(value);
return null;
}
@ -1203,24 +1203,24 @@ class IosWebViewOptionsTransitionStyle {
///When the view controller is presented, its view slides up from the bottom of the screen.
///On dismissal, the view slides back down. This is the default transition style.
static const COVER_VERTICAL =
const IosWebViewOptionsTransitionStyle._internal(0);
const IOSWebViewOptionsTransitionStyle._internal(0);
///When the view controller is presented, the current view initiates a horizontal 3D flip from right-to-left,
///resulting in the revealing of the new view as if it were on the back of the previous view.
///On dismissal, the flip occurs from left-to-right, returning to the original view.
static const FLIP_HORIZONTAL =
const IosWebViewOptionsTransitionStyle._internal(1);
const IOSWebViewOptionsTransitionStyle._internal(1);
///When the view controller is presented, the current view fades out while the new view fades in at the same time.
///On dismissal, a similar type of cross-fade is used to return to the original view.
static const CROSS_DISSOLVE =
const IosWebViewOptionsTransitionStyle._internal(2);
const IOSWebViewOptionsTransitionStyle._internal(2);
///When the view controller is presented, one corner of the current view curls up to reveal the presented view underneath.
///On dismissal, the curled up page unfurls itself back on top of the presented view.
///A view controller presented using this transition is itself prevented from presenting any additional view controllers.
static const PARTIAL_CURL =
const IosWebViewOptionsTransitionStyle._internal(3);
const IOSWebViewOptionsTransitionStyle._internal(3);
bool operator ==(value) => value == _value;
@ -1228,15 +1228,15 @@ class IosWebViewOptionsTransitionStyle {
int get hashCode => _value.hashCode;
}
///IosWebViewOptionsTransitionStyle class represents an iOS-specific class used to set the custom style for the dismiss button.
///IOSSafariOptionsDismissButtonStyle class represents an iOS-specific class used to set the custom style for the dismiss button.
///
///**NOTE**: available on iOS 11.0+.
class IosSafariOptionsDismissButtonStyle {
class IOSSafariOptionsDismissButtonStyle {
final int _value;
const IosSafariOptionsDismissButtonStyle._internal(this._value);
static IosSafariOptionsDismissButtonStyle fromValue(int value) {
const IOSSafariOptionsDismissButtonStyle._internal(this._value);
static IOSSafariOptionsDismissButtonStyle fromValue(int value) {
if (value != null && value >= 0 && value <= 2)
return IosSafariOptionsDismissButtonStyle._internal(value);
return IOSSafariOptionsDismissButtonStyle._internal(value);
return null;
}
@ -1255,13 +1255,13 @@ class IosSafariOptionsDismissButtonStyle {
}
///Makes the button title the localized string "Done".
static const DONE = const IosSafariOptionsDismissButtonStyle._internal(0);
static const DONE = const IOSSafariOptionsDismissButtonStyle._internal(0);
///Makes the button title the localized string "Close".
static const CLOSE = const IosSafariOptionsDismissButtonStyle._internal(1);
static const CLOSE = const IOSSafariOptionsDismissButtonStyle._internal(1);
///Makes the button title the localized string "Cancel".
static const CANCEL = const IosSafariOptionsDismissButtonStyle._internal(2);
static const CANCEL = const IOSSafariOptionsDismissButtonStyle._internal(2);
bool operator ==(value) => value == _value;
@ -1272,51 +1272,51 @@ class IosSafariOptionsDismissButtonStyle {
///InAppWebViewWidgetOptions class represents the options that can be used for an [InAppWebView].
class InAppWebViewWidgetOptions {
///Cross-platform options.
InAppWebViewOptions inAppWebViewOptions;
InAppWebViewOptions crossPlatform;
///Android-specific options.
AndroidInAppWebViewOptions androidInAppWebViewOptions;
AndroidInAppWebViewOptions android;
///iOS-specific options.
IosInAppWebViewOptions iosInAppWebViewOptions;
IOSInAppWebViewOptions ios;
InAppWebViewWidgetOptions(
{this.inAppWebViewOptions,
this.androidInAppWebViewOptions,
this.iosInAppWebViewOptions});
{this.crossPlatform,
this.android,
this.ios});
}
///InAppBrowserClassOptions class represents the options that can be used for an [InAppBrowser] WebView.
class InAppBrowserClassOptions {
///Cross-platform options.
InAppBrowserOptions inAppBrowserOptions;
InAppBrowserOptions crossPlatform;
///Android-specific options.
AndroidInAppBrowserOptions androidInAppBrowserOptions;
AndroidInAppBrowserOptions android;
///iOS-specific options.
IosInAppBrowserOptions iosInAppBrowserOptions;
IOSInAppBrowserOptions ios;
///WebView options.
InAppWebViewWidgetOptions inAppWebViewWidgetOptions;
InAppBrowserClassOptions(
{this.inAppBrowserOptions,
this.androidInAppBrowserOptions,
this.iosInAppBrowserOptions,
{this.crossPlatform,
this.android,
this.ios,
this.inAppWebViewWidgetOptions});
}
///ChromeSafariBrowserClassOptions class represents the options that can be used for an [ChromeSafariBrowser] window.
class ChromeSafariBrowserClassOptions {
///Android-specific options.
AndroidChromeCustomTabsOptions androidChromeCustomTabsOptions;
AndroidChromeCustomTabsOptions android;
///iOS-specific options.
IosSafariOptions iosSafariOptions;
IOSSafariOptions ios;
ChromeSafariBrowserClassOptions(
{this.androidChromeCustomTabsOptions, this.iosSafariOptions});
{this.android, this.ios});
}
///AjaxRequestAction class used by [AjaxRequest] class.
@ -1950,7 +1950,7 @@ class PermissionRequestResponseAction {
int get hashCode => _value.hashCode;
}
///PermissionRequestResponse class represents the response used by the [onPermissionRequest] event.
///PermissionRequestResponse class represents the response used by the [androidOnPermissionRequest] event.
class PermissionRequestResponse {
///Resources granted to be accessed by origin.
List<String> resources;
@ -1992,34 +1992,34 @@ class ShouldOverrideUrlLoadingAction {
}
}
///IosWKNavigationType class represents the type of action triggering a navigation on iOS for the [shouldOverrideUrlLoading] event.
class IosWKNavigationType {
///IOSWKNavigationType class represents the type of action triggering a navigation on iOS for the [shouldOverrideUrlLoading] event.
class IOSWKNavigationType {
final int _value;
const IosWKNavigationType._internal(this._value);
const IOSWKNavigationType._internal(this._value);
int toValue() => _value;
static IosWKNavigationType fromValue(int value) {
static IOSWKNavigationType fromValue(int value) {
if (value != null && ((value >= 0 && value <= 4) || value == -1))
return IosWKNavigationType._internal(value);
return IOSWKNavigationType._internal(value);
return null;
}
///A link with an href attribute was activated by the user.
static const LINK_ACTIVATED = const IosWKNavigationType._internal(0);
static const LINK_ACTIVATED = const IOSWKNavigationType._internal(0);
///A form was submitted.
static const FORM_SUBMITTED = const IosWKNavigationType._internal(1);
static const FORM_SUBMITTED = const IOSWKNavigationType._internal(1);
///An item from the back-forward list was requested.
static const BACK_FORWARD = const IosWKNavigationType._internal(2);
static const BACK_FORWARD = const IOSWKNavigationType._internal(2);
///The webpage was reloaded.
static const RELOAD = const IosWKNavigationType._internal(3);
static const RELOAD = const IOSWKNavigationType._internal(3);
///A form was resubmitted (for example by going back, going forward, or reloading).
static const FORM_RESUBMITTED = const IosWKNavigationType._internal(4);
static const FORM_RESUBMITTED = const IOSWKNavigationType._internal(4);
///Navigation is taking place for some other reason.
static const OTHER = const IosWKNavigationType._internal(-1);
static const OTHER = const IOSWKNavigationType._internal(-1);
bool operator ==(value) => value == _value;
@ -2053,7 +2053,171 @@ class ShouldOverrideUrlLoadingRequest {
bool androidIsRedirect;
///The type of action triggering the navigation. Available only on iOS.
IosWKNavigationType iosWKNavigationType;
IOSWKNavigationType iosWKNavigationType;
ShouldOverrideUrlLoadingRequest({this.url, this.method, this.headers, this.isForMainFrame, this.androidHasGesture, this.androidIsRedirect, this.iosWKNavigationType});
}
///OnCreateWindowRequest class represents the navigation request used by the [shouldOverrideUrlLoading] event.
class OnCreateWindowRequest {
///Represents the url of the navigation request.
String url;
///Indicates if the new window should be a dialog, rather than a full-size window. Available only on Android.
bool androidIsDialog;
///Indicates if the request was initiated by a user gesture, such as the user clicking a link. Available only on Android.
bool androidIsUserGesture;
///The type of action triggering the navigation. Available only on iOS.
IOSWKNavigationType iosWKNavigationType;
OnCreateWindowRequest({this.url, this.androidIsDialog, this.androidIsUserGesture, this.iosWKNavigationType});
}
///AndroidWebStorage class encapsulates information about the amount of storage currently used by an origin for the JavaScript storage APIs.
///An origin comprises the host, scheme and port of a URI. See [AndroidWebStorageManager] for details.
class AndroidWebStorageOrigin {
///The string representation of this origin.
String origin;
///The quota for this origin, for the Web SQL Database API, in bytes.
int quota;
///The total amount of storage currently being used by this origin, for all JavaScript storage APIs, in bytes.
int usage;
AndroidWebStorageOrigin({this.origin, this.quota, this.usage});
Map<String, dynamic> toMap() {
return {
"origin": origin,
"quota": quota,
"usage": usage
};
}
String toString() {
return toMap().toString();
}
}
///IOSWKWebsiteDataType class represents a website data type.
///
///**NOTE**: available on iOS 9.0+.
class IOSWKWebsiteDataType {
final String _value;
const IOSWKWebsiteDataType._internal(this._value);
static IOSWKWebsiteDataType fromValue(String value) {
return ([
"WKWebsiteDataTypeFetchCache",
"WKWebsiteDataTypeDiskCache",
"WKWebsiteDataTypeMemoryCache",
"WKWebsiteDataTypeOfflineWebApplicationCache",
"WKWebsiteDataTypeCookies",
"WKWebsiteDataTypeSessionStorage",
"WKWebsiteDataTypeLocalStorage",
"WKWebsiteDataTypeWebSQLDatabases",
"WKWebsiteDataTypeIndexedDBDatabases",
"WKWebsiteDataTypeServiceWorkerRegistrations"
].contains(value))
? IOSWKWebsiteDataType._internal(value)
: null;
}
String toValue() => _value;
@override
String toString() => _value;
///On-disk Fetch caches.
///
///**NOTE**: available on iOS 11.3+.
static const WKWebsiteDataTypeFetchCache =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeFetchCache");
///On-disk caches.
static const WKWebsiteDataTypeDiskCache =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeDiskCache");
///In-memory caches.
static const WKWebsiteDataTypeMemoryCache =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeMemoryCache");
///HTML offline web application caches.
static const WKWebsiteDataTypeOfflineWebApplicationCache =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeOfflineWebApplicationCache");
///Cookies.
static const WKWebsiteDataTypeCookies =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeCookies");
///HTML session storage.
static const WKWebsiteDataTypeSessionStorage =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeSessionStorage");
///HTML local storage.
static const WKWebsiteDataTypeLocalStorage =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeLocalStorage");
///WebSQL databases.
static const WKWebsiteDataTypeWebSQLDatabases =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeWebSQLDatabases");
///IndexedDB databases.
static const WKWebsiteDataTypeIndexedDBDatabases =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeIndexedDBDatabases");
///Service worker registrations.
///
///**NOTE**: available on iOS 11.3+.
static const WKWebsiteDataTypeServiceWorkerRegistrations =
const IOSWKWebsiteDataType._internal("WKWebsiteDataTypeServiceWorkerRegistrations");
///Returns a set of all available website data types.
static final Set<IOSWKWebsiteDataType> ALL = [
IOSWKWebsiteDataType.WKWebsiteDataTypeFetchCache,
IOSWKWebsiteDataType.WKWebsiteDataTypeDiskCache,
IOSWKWebsiteDataType.WKWebsiteDataTypeMemoryCache,
IOSWKWebsiteDataType.WKWebsiteDataTypeOfflineWebApplicationCache,
IOSWKWebsiteDataType.WKWebsiteDataTypeCookies,
IOSWKWebsiteDataType.WKWebsiteDataTypeSessionStorage,
IOSWKWebsiteDataType.WKWebsiteDataTypeLocalStorage,
IOSWKWebsiteDataType.WKWebsiteDataTypeWebSQLDatabases,
IOSWKWebsiteDataType.WKWebsiteDataTypeIndexedDBDatabases,
IOSWKWebsiteDataType.WKWebsiteDataTypeServiceWorkerRegistrations
].toSet();
bool operator ==(value) => value == _value;
@override
int get hashCode => _value.hashCode;
}
///WKWebsiteDataRecord class represents website data, grouped by domain name using the public suffix list.
///
///**NOTE**: available on iOS 9.0+.
class IOSWKWebsiteDataRecord {
///The display name for the data record. This is usually the domain name.
String displayName;
///The various types of website data that exist for this data record.
Set<IOSWKWebsiteDataType> dataTypes;
IOSWKWebsiteDataRecord({this.displayName, this.dataTypes});
Map<String, dynamic> toMap() {
List<String> dataTypesString = [];
for (var dataType in dataTypes) {
dataTypesString.add(dataType.toValue());
}
return {
"displayName": displayName,
"dataTypes": dataTypesString
};
}
String toString() {
return toMap().toString();
}
}

View File

@ -0,0 +1,159 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'types.dart';
///WebStorageManager class implements a singleton object (shared instance) which manages the web storage used by WebView instances.
///
///**NOTE for iOS**: available from iOS 9.0+.
class WebStorageManager {
static WebStorageManager _instance;
static const MethodChannel _channel = const MethodChannel(
'com.pichillilorenzo/flutter_inappwebview_webstoragemanager');
AndroidWebStorageManager android = AndroidWebStorageManager();
IOSWebStorageManager ios = IOSWebStorageManager();
///Gets the WebStorage manager shared instance.
static WebStorageManager instance() {
return (_instance != null) ? _instance : _init();
}
static WebStorageManager _init() {
_channel.setMethodCallHandler(_handleMethod);
_instance = new WebStorageManager();
return _instance;
}
static Future<dynamic> _handleMethod(MethodCall call) async {}
}
///AndroidWebStorageManager class is used to manage the JavaScript storage APIs provided by the WebView.
///It manages the Application Cache API, the Web SQL Database API and the HTML5 Web Storage API.
class AndroidWebStorageManager {
///Gets the origins currently using either the Application Cache or Web SQL Database APIs.
Future<List<AndroidWebStorageOrigin>> getOrigins() async {
List<AndroidWebStorageOrigin> originsList = [];
Map<String, dynamic> args = <String, dynamic>{};
List<Map<dynamic, dynamic>> origins = (await WebStorageManager._channel.invokeMethod('getOrigins', args)).cast<Map<dynamic, dynamic>>();
for(var origin in origins) {
originsList.add(AndroidWebStorageOrigin(origin: origin["origin"], quota: origin["quota"], usage: origin["usage"]));
}
return originsList;
}
///Clears all storage currently being used by the JavaScript storage APIs.
///This includes the Application Cache, Web SQL Database and the HTML5 Web Storage APIs.
Future<void> deleteAllData() async {
Map<String, dynamic> args = <String, dynamic>{};
await WebStorageManager._channel.invokeMethod('deleteAllData', args);
}
///Clears the storage currently being used by both the Application Cache and Web SQL Database APIs by the given [origin].
///The origin is specified using its string representation.
Future<void> deleteOrigin({@required String origin}) async {
assert(origin != null);
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("origin", () => origin);
await WebStorageManager._channel.invokeMethod('deleteOrigin', args);
}
///Gets the storage quota for the Web SQL Database API for the given [origin].
///The quota is given in bytes and the origin is specified using its string representation.
///Note that a quota is not enforced on a per-origin basis for the Application Cache API.
Future<int> getQuotaForOrigin({@required String origin}) async {
assert(origin != null);
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("origin", () => origin);
return await WebStorageManager._channel.invokeMethod('getQuotaForOrigin', args);
}
///Gets the amount of storage currently being used by both the Application Cache and Web SQL Database APIs by the given [origin].
///The amount is given in bytes and the origin is specified using its string representation.
Future<int> getUsageForOrigin({@required String origin}) async {
assert(origin != null);
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("origin", () => origin);
return await WebStorageManager._channel.invokeMethod('getUsageForOrigin', args);
}
}
///IOSWebStorageManager class represents various types of data that a website might make use of.
///This includes cookies, disk and memory caches, and persistent data such as WebSQL, IndexedDB databases, and local storage.
///
///**NOTE**: available on iOS 9.0+.
class IOSWebStorageManager {
///Fetches data records containing the given website data types.
///
///[dataTypes] represents the website data types to fetch records for.
Future<List<IOSWKWebsiteDataRecord>> fetchDataRecords({@required Set<IOSWKWebsiteDataType> dataTypes}) async {
assert(dataTypes != null);
List<IOSWKWebsiteDataRecord> recordList = [];
List<String> dataTypesList = [];
for (var dataType in dataTypes) {
dataTypesList.add(dataType.toValue());
}
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("dataTypes", () => dataTypesList);
List<Map<dynamic, dynamic>> records = (await WebStorageManager._channel.invokeMethod('fetchDataRecords', args)).cast<Map<dynamic, dynamic>>();
for(var record in records) {
List<String> dataTypesString = record["dataTypes"].cast<String>();
Set<IOSWKWebsiteDataType> dataTypes = Set();
for(var dataType in dataTypesString) {
dataTypes.add(IOSWKWebsiteDataType.fromValue(dataType));
}
recordList.add(IOSWKWebsiteDataRecord(displayName: record["displayName"], dataTypes: dataTypes));
}
return recordList;
}
///Removes website data of the given types for the given data records.
///
///[dataTypes] represents the website data types that should be removed.
///
///[dataRecords] represents the website data records to delete website data for.
Future<void> removeDataFor({@required Set<IOSWKWebsiteDataType> dataTypes, @required List<IOSWKWebsiteDataRecord> dataRecords}) async {
assert(dataTypes != null && dataRecords != null);
List<String> dataTypesList = [];
for (var dataType in dataTypes) {
dataTypesList.add(dataType.toValue());
}
List<Map<String, dynamic>> recordList = [];
for (var record in dataRecords) {
recordList.add(record.toMap());
}
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("dataTypes", () => dataTypesList);
args.putIfAbsent("recordList", () => recordList);
await WebStorageManager._channel.invokeMethod('removeDataFor', args);
}
///Removes all website data of the given types that has been modified since the given date.
///
///[dataTypes] represents the website data types that should be removed.
///
///[date] represents a date. All website data modified after this date will be removed.
Future<void> removeDataModifiedSince({@required Set<IOSWKWebsiteDataType> dataTypes, @required DateTime date}) async {
assert(dataTypes != null && date != null);
List<String> dataTypesList = [];
for (var dataType in dataTypes) {
dataTypesList.add(dataType.toValue());
}
var timestamp = date.millisecondsSinceEpoch;
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("dataTypes", () => dataTypesList);
args.putIfAbsent("timestamp", () => timestamp);
await WebStorageManager._channel.invokeMethod('removeDataModifiedSince', args);
}
}

View File

@ -256,7 +256,7 @@ class AndroidInAppWebViewOptions
///Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`.
bool supportZoom;
///Set to `true` if you want the database storage API is enabled. The default value is `false`.
///Set to `true` if you want the database storage API is enabled. The default value is `true`.
bool databaseEnabled;
///Set to `true` if you want the DOM storage API is enabled. The default value is `true`.
@ -556,7 +556,7 @@ class AndroidInAppWebViewOptions
}
///This class represents all the iOS-only WebView options available.
class IosInAppWebViewOptions
class IOSInAppWebViewOptions
implements WebViewOptions, BrowserOptions, IosOptions {
///Set to `true` to disable the bouncing of the WebView when the scrolling has reached an edge of the content. The default value is `false`.
bool disallowOverScroll;
@ -599,15 +599,15 @@ class IosInAppWebViewOptions
bool isFraudulentWebsiteWarningEnabled;
///The level of granularity with which the user can interactively select content in the web view.
///The default value is [IosInAppWebViewSelectionGranularity.DYNAMIC]
IosInAppWebViewSelectionGranularity selectionGranularity;
///The default value is [IOSInAppWebViewSelectionGranularity.DYNAMIC]
IOSInAppWebViewSelectionGranularity selectionGranularity;
///Specifying a dataDetectoryTypes value adds interactivity to web content that matches the value.
///For example, Safari adds a link to apple.com in the text Visit apple.com if the dataDetectorTypes property is set to [IosInAppWebViewDataDetectorTypes.LINK].
///The default value is [IosInAppWebViewDataDetectorTypes.NONE].
///For example, Safari adds a link to apple.com in the text Visit apple.com if the dataDetectorTypes property is set to [IOSInAppWebViewDataDetectorTypes.LINK].
///The default value is [IOSInAppWebViewDataDetectorTypes.NONE].
///
///**NOTE**: available on iOS 10.0+.
List<IosInAppWebViewDataDetectorTypes> dataDetectorTypes;
List<IOSInAppWebViewDataDetectorTypes> dataDetectorTypes;
///Set `true` if shared cookies from `HTTPCookieStorage.shared` should used for every load request in the WebView.
///The default value is `false`.
@ -615,7 +615,13 @@ class IosInAppWebViewOptions
///**NOTE**: available on iOS 11.0+.
bool sharedCookiesEnabled;
IosInAppWebViewOptions(
///Configures whether the scroll indicator insets are automatically adjusted by the system.
///The default value is `false`.
///
///**NOTE**: available on iOS 13.0+.
bool automaticallyAdjustsScrollIndicatorInsets;
IOSInAppWebViewOptions(
{this.disallowOverScroll = false,
this.enableViewportScale = false,
this.suppressesIncrementalRendering = false,
@ -626,9 +632,10 @@ class IosInAppWebViewOptions
this.allowsInlineMediaPlayback = false,
this.allowsPictureInPictureMediaPlayback = true,
this.isFraudulentWebsiteWarningEnabled = true,
this.selectionGranularity = IosInAppWebViewSelectionGranularity.DYNAMIC,
this.dataDetectorTypes = const [IosInAppWebViewDataDetectorTypes.NONE],
this.sharedCookiesEnabled = false});
this.selectionGranularity = IOSInAppWebViewSelectionGranularity.DYNAMIC,
this.dataDetectorTypes = const [IOSInAppWebViewDataDetectorTypes.NONE],
this.sharedCookiesEnabled = false,
this.automaticallyAdjustsScrollIndicatorInsets = false});
@override
Map<String, dynamic> toMap() {
@ -652,20 +659,21 @@ class IosInAppWebViewOptions
"isFraudulentWebsiteWarningEnabled": isFraudulentWebsiteWarningEnabled,
"selectionGranularity": selectionGranularity.toValue(),
"dataDetectorTypes": dataDetectorTypesList,
"sharedCookiesEnabled": sharedCookiesEnabled
"sharedCookiesEnabled": sharedCookiesEnabled,
"automaticallyAdjustsScrollIndicatorInsets": automaticallyAdjustsScrollIndicatorInsets
};
}
static IosInAppWebViewOptions fromMap(Map<String, dynamic> map) {
List<IosInAppWebViewDataDetectorTypes> dataDetectorTypes = [];
static IOSInAppWebViewOptions fromMap(Map<String, dynamic> map) {
List<IOSInAppWebViewDataDetectorTypes> dataDetectorTypes = [];
List<String> dataDetectorTypesList =
List<String>.from(map["dataDetectorTypes"] ?? []);
dataDetectorTypesList.forEach((dataDetectorType) {
dataDetectorTypes
.add(IosInAppWebViewDataDetectorTypes.fromValue(dataDetectorType));
.add(IOSInAppWebViewDataDetectorTypes.fromValue(dataDetectorType));
});
IosInAppWebViewOptions options = new IosInAppWebViewOptions();
IOSInAppWebViewOptions options = new IOSInAppWebViewOptions();
options.disallowOverScroll = map["disallowOverScroll"];
options.enableViewportScale = map["enableViewportScale"];
options.suppressesIncrementalRendering =
@ -682,10 +690,11 @@ class IosInAppWebViewOptions
options.isFraudulentWebsiteWarningEnabled =
map["isFraudulentWebsiteWarningEnabled"];
options.selectionGranularity =
IosInAppWebViewSelectionGranularity.fromValue(
IOSInAppWebViewSelectionGranularity.fromValue(
map["selectionGranularity"]);
options.dataDetectorTypes = dataDetectorTypes;
options.sharedCookiesEnabled = map["sharedCookiesEnabled"];
options.automaticallyAdjustsScrollIndicatorInsets = map["automaticallyAdjustsScrollIndicatorInsets"];
return options;
}
}
@ -773,7 +782,7 @@ class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
}
///This class represents all the iOS-only [InAppBrowser] options available.
class IosInAppBrowserOptions implements BrowserOptions, IosOptions {
class IOSInAppBrowserOptions implements BrowserOptions, IosOptions {
///Set to `false` to hide the toolbar at the bottom of the WebView. The default value is `true`.
bool toolbarBottom;
@ -789,23 +798,23 @@ class IosInAppBrowserOptions implements BrowserOptions, IosOptions {
///Set the custom color for the close button.
String closeButtonColor;
///Set the custom modal presentation style when presenting the WebView. The default value is [IosWebViewOptionsPresentationStyle.FULL_SCREEN].
IosWebViewOptionsPresentationStyle presentationStyle;
///Set the custom modal presentation style when presenting the WebView. The default value is [IOSWebViewOptionsPresentationStyle.FULL_SCREEN].
IOSWebViewOptionsPresentationStyle presentationStyle;
///Set to the custom transition style when presenting the WebView. The default value is [IosWebViewOptionsTransitionStyle.COVER_VERTICAL].
IosWebViewOptionsTransitionStyle transitionStyle;
///Set to the custom transition style when presenting the WebView. The default value is [IOSWebViewOptionsTransitionStyle.COVER_VERTICAL].
IOSWebViewOptionsTransitionStyle transitionStyle;
///Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`.
bool spinner;
IosInAppBrowserOptions(
IOSInAppBrowserOptions(
{this.toolbarBottom = true,
this.toolbarBottomBackgroundColor = "",
this.toolbarBottomTranslucent = true,
this.closeButtonCaption = "",
this.closeButtonColor = "",
this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN,
this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL,
this.presentationStyle = IOSWebViewOptionsPresentationStyle.FULL_SCREEN,
this.transitionStyle = IOSWebViewOptionsTransitionStyle.COVER_VERTICAL,
this.spinner = true});
@override
@ -822,17 +831,17 @@ class IosInAppBrowserOptions implements BrowserOptions, IosOptions {
};
}
static IosInAppBrowserOptions fromMap(Map<String, dynamic> map) {
IosInAppBrowserOptions options = new IosInAppBrowserOptions();
static IOSInAppBrowserOptions fromMap(Map<String, dynamic> map) {
IOSInAppBrowserOptions options = new IOSInAppBrowserOptions();
options.toolbarBottom = map["toolbarBottom"];
options.toolbarBottomBackgroundColor = map["toolbarBottomBackgroundColor"];
options.toolbarBottomTranslucent = map["toolbarBottomTranslucent"];
options.closeButtonCaption = map["closeButtonCaption"];
options.closeButtonColor = map["closeButtonColor"];
options.presentationStyle =
IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
IOSWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
options.transitionStyle =
IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
IOSWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
options.spinner = map["spinner"];
return options;
}
@ -887,17 +896,17 @@ class AndroidChromeCustomTabsOptions
}
///This class represents all the iOS-only [ChromeSafariBrowser] options available.
class IosSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
class IOSSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
///Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`.
bool entersReaderIfAvailable;
///Set to `true` to enable bar collapsing. The default value is `false`.
bool barCollapsingEnabled;
///Set the custom style for the dismiss button. The default value is [IosSafariOptionsDismissButtonStyle.DONE].
///Set the custom style for the dismiss button. The default value is [IOSSafariOptionsDismissButtonStyle.DONE].
///
///**NOTE**: available on iOS 11.0+.
IosSafariOptionsDismissButtonStyle dismissButtonStyle;
IOSSafariOptionsDismissButtonStyle dismissButtonStyle;
///Set the custom background color of the navigation bar and the toolbar.
///
@ -909,20 +918,20 @@ class IosSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
///**NOTE**: available on iOS 10.0+.
String preferredControlTintColor;
///Set the custom modal presentation style when presenting the WebView. The default value is [IosWebViewOptionsPresentationStyle.FULL_SCREEN].
IosWebViewOptionsPresentationStyle presentationStyle;
///Set the custom modal presentation style when presenting the WebView. The default value is [IOSWebViewOptionsPresentationStyle.FULL_SCREEN].
IOSWebViewOptionsPresentationStyle presentationStyle;
///Set to the custom transition style when presenting the WebView. The default value is [IosWebViewOptionsTransitionStyle.COVER_VERTICAL].
IosWebViewOptionsTransitionStyle transitionStyle;
///Set to the custom transition style when presenting the WebView. The default value is [IOSWebViewOptionsTransitionStyle.COVER_VERTICAL].
IOSWebViewOptionsTransitionStyle transitionStyle;
IosSafariOptions(
IOSSafariOptions(
{this.entersReaderIfAvailable = false,
this.barCollapsingEnabled = false,
this.dismissButtonStyle = IosSafariOptionsDismissButtonStyle.DONE,
this.dismissButtonStyle = IOSSafariOptionsDismissButtonStyle.DONE,
this.preferredBarTintColor = "",
this.preferredControlTintColor = "",
this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN,
this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL});
this.presentationStyle = IOSWebViewOptionsPresentationStyle.FULL_SCREEN,
this.transitionStyle = IOSWebViewOptionsTransitionStyle.COVER_VERTICAL});
@override
Map<String, dynamic> toMap() {
@ -937,18 +946,18 @@ class IosSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
};
}
static IosSafariOptions fromMap(Map<String, dynamic> map) {
IosSafariOptions options = new IosSafariOptions();
static IOSSafariOptions fromMap(Map<String, dynamic> map) {
IOSSafariOptions options = new IOSSafariOptions();
options.entersReaderIfAvailable = map["entersReaderIfAvailable"];
options.barCollapsingEnabled = map["barCollapsingEnabled"];
options.dismissButtonStyle =
IosSafariOptionsDismissButtonStyle.fromValue(map["dismissButtonStyle"]);
IOSSafariOptionsDismissButtonStyle.fromValue(map["dismissButtonStyle"]);
options.preferredBarTintColor = map["preferredBarTintColor"];
options.preferredControlTintColor = map["preferredControlTintColor"];
options.presentationStyle =
IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
IOSWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
options.transitionStyle =
IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
IOSWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
return options;
}
}