Commit ade4480c authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

Fixed error 'java.lang.ClassCastException: cannot be cast to...

Fixed error 'java.lang.ClassCastException:  cannot be cast to android.view.WindowManagerImpl' on Android when using native alert dialogs, updated README.md with Xcode version required
parent a56b2128
...@@ -15,7 +15,25 @@ ...@@ -15,7 +15,25 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment=""> <list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment="">
<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$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" 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$/example/ios/Flutter/flutter_export_environment.sh" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/Flutter/flutter_export_environment.sh" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.pbxproj" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.pbxproj" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/example/pubspec.yaml" 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$/lib/src/channel_manager.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/channel_manager.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/content_blocker.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/content_blocker.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/src/cookie_manager.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/cookie_manager.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/http_auth_credentials_database.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_localhost_server.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/in_app_localhost_server.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$/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pubspec.yaml" afterDir="false" />
</list> </list>
<ignored path="$PROJECT_DIR$/.dart_tool/" /> <ignored path="$PROJECT_DIR$/.dart_tool/" />
<ignored path="$PROJECT_DIR$/.idea/" /> <ignored path="$PROJECT_DIR$/.idea/" />
...@@ -35,12 +53,13 @@ ...@@ -35,12 +53,13 @@
<component name="ExecutionTargetManager" SELECTED_TARGET="Pixel_3_XL_API_24" /> <component name="ExecutionTargetManager" SELECTED_TARGET="Pixel_3_XL_API_24" />
<component name="FileEditorManager"> <component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300"> <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="true"> <file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/README.md"> <entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="330"> <state relative-caret-position="12735">
<caret line="22" column="92" selection-start-line="22" selection-start-column="92" selection-end-line="22" selection-end-column="92" /> <caret line="849" selection-start-line="849" selection-end-line="849" />
<folding> <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" />
<element signature="e#0#39#0" expanded="true" /> <element signature="e#0#39#0" expanded="true" />
</folding> </folding>
...@@ -51,29 +70,29 @@ ...@@ -51,29 +70,29 @@
<file pinned="false" current-in-tab="false"> <file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/CHANGELOG.md"> <entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="255"> <state relative-caret-position="30">
<caret line="17" column="101" lean-forward="true" selection-start-line="17" selection-start-column="101" selection-end-line="17" selection-end-column="101" /> <caret line="2" column="145" selection-start-line="2" selection-start-column="145" selection-end-line="2" selection-end-column="145" />
</state> </state>
</provider> </provider>
</entry> </entry>
</file> </file>
<file pinned="false" current-in-tab="false"> <file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/pubspec.yaml"> <entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state> <state relative-caret-position="304">
<caret column="26" selection-start-column="6" selection-end-column="26" /> <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> </state>
</provider> </provider>
</entry> </entry>
</file> </file>
<file pinned="false" current-in-tab="false"> <file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart"> <entry file="file://$USER_HOME$/Downloads/in_app_webiew_example.screen.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="235"> <state relative-caret-position="345">
<caret line="1170" column="66" selection-start-line="1170" selection-start-column="66" selection-end-line="1170" selection-end-column="66" /> <caret line="33" column="57" selection-start-line="33" selection-start-column="2" selection-end-line="33" selection-end-column="57" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>
...@@ -90,13 +109,6 @@ ...@@ -90,13 +109,6 @@
</component> </component>
<component name="FindInProjectRecents"> <component name="FindInProjectRecents">
<findStrings> <findStrings>
<find>reload</find>
<find>methods</find>
<find>class</find>
<find>HttpAuthCredentialDatabase</find>
<find>###</find>
<find>#####</find>
<find>loadFile</find>
<find>window.</find> <find>window.</find>
<find>onLoadHttpError</find> <find>onLoadHttpError</find>
<find>microphone</find> <find>microphone</find>
...@@ -117,9 +129,16 @@ ...@@ -117,9 +129,16 @@
<find>[InAppBrowser]</find> <find>[InAppBrowser]</find>
<find>Response({</find> <find>Response({</find>
<find>flutter_inappbrowser</find> <find>flutter_inappbrowser</find>
<find>flutterInAppBrowserPlatformReady</find>
<find>InAppBrowser</find> <find>InAppBrowser</find>
<find>PlatformRead</find> <find>PlatformRead</find>
<find>flutterInAppBrowserPlatformReady</find>
<find>llowContentAccess</find>
<find>ppCache</find>
<find>onReceivedClientCertRequest</find>
<find>a SSL</find>
<find>iltInZoomControls</find>
<find>databaseEnabled</find>
<find>Cookie</find>
</findStrings> </findStrings>
<replaceStrings> <replaceStrings>
<replace>activity.getPreferences(0)</replace> <replace>activity.getPreferences(0)</replace>
...@@ -142,13 +161,10 @@ ...@@ -142,13 +161,10 @@
<component name="IdeDocumentHistory"> <component name="IdeDocumentHistory">
<option name="CHANGED_PATHS"> <option name="CHANGED_PATHS">
<list> <list>
<option value="$PROJECT_DIR$/.github/ISSUE_TEMPLATE/BUG_REPORT.md" />
<option value="$PROJECT_DIR$/example/test_driver/app_test.dart" />
<option value="$PROJECT_DIR$/lib/src/chrome_safari_browser.dart" /> <option value="$PROJECT_DIR$/lib/src/chrome_safari_browser.dart" />
<option value="$PROJECT_DIR$/example/assets/index.html" /> <option value="$PROJECT_DIR$/example/assets/index.html" />
<option value="$PROJECT_DIR$/lib/src/types.dart" /> <option value="$PROJECT_DIR$/lib/src/types.dart" />
<option value="$PROJECT_DIR$/example/android/app/src/main/AndroidManifest.xml" /> <option value="$PROJECT_DIR$/example/android/app/src/main/AndroidManifest.xml" />
<option value="$PROJECT_DIR$/pubspec.yaml" />
<option value="$PROJECT_DIR$/lib/flutter_inappwebview.dart" /> <option value="$PROJECT_DIR$/lib/flutter_inappwebview.dart" />
<option value="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" /> <option value="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" />
<option value="$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart" /> <option value="$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart" />
...@@ -168,7 +184,6 @@ ...@@ -168,7 +184,6 @@
<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_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_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_js_dialog_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_error_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_http_error_test.dart" /> <option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_http_error_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_resource_custom_scheme_test.dart" /> <option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_resource_custom_scheme_test.dart" />
<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_load_resource_test.dart" />
...@@ -180,23 +195,28 @@ ...@@ -180,23 +195,28 @@
<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_on_target_blank_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_should_override_url_loading_test.dart" /> <option value="$PROJECT_DIR$/example/test_driver/in_app_webview_should_override_url_loading_test.dart" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_ssl_request_test.dart" /> <option value="$PROJECT_DIR$/example/test_driver/in_app_webview_ssl_request_test.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
<option value="$PROJECT_DIR$/example/pubspec.yaml" />
<option value="$PROJECT_DIR$/example/lib/main.dart" />
<option value="$PROJECT_DIR$/ios/Classes/InAppBrowserFlutterPlugin.m" /> <option value="$PROJECT_DIR$/ios/Classes/InAppBrowserFlutterPlugin.m" />
<option value="$PROJECT_DIR$/ios/Classes/InAppWebViewFlutterPlugin.h" /> <option value="$PROJECT_DIR$/ios/Classes/InAppWebViewFlutterPlugin.h" />
<option value="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" /> <option value="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
<option value="$PROJECT_DIR$/lib/src/cookie_manager.dart" /> <option value="$PROJECT_DIR$/lib/src/cookie_manager.dart" />
<option value="$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart" /> <option value="$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart" />
<option value="$PROJECT_DIR$/example/test_assets/in_app_webview_initial_file_test.html" /> <option value="$PROJECT_DIR$/example/test_assets/in_app_webview_initial_file_test.html" />
<option value="$PROJECT_DIR$/.git/config" />
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_error_test.dart" />
<option value="$PROJECT_DIR$/example/pubspec.yaml" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
<option value="$PROJECT_DIR$/pubspec.yaml" />
<option value="$PROJECT_DIR$/CHANGELOG.md" /> <option value="$PROJECT_DIR$/CHANGELOG.md" />
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
<option value="$PROJECT_DIR$/lib/src/channel_manager.dart" />
<option value="$PROJECT_DIR$/example/lib/main.dart" />
<option value="$PROJECT_DIR$/README.md" /> <option value="$PROJECT_DIR$/README.md" />
</list> </list>
</option> </option>
</component> </component>
<component name="ProjectFrameBounds"> <component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="-1" />
<option name="y" value="23" /> <option name="y" value="23" />
<option name="width" value="1920" /> <option name="width" value="1920" />
<option name="height" value="1057" /> <option name="height" value="1057" />
...@@ -248,6 +268,42 @@ ...@@ -248,6 +268,42 @@
<item name="flutter_inappwebview" type="462c0819:PsiDirectoryNode" /> <item name="flutter_inappwebview" type="462c0819:PsiDirectoryNode" />
<item name="example" type="462c0819:PsiDirectoryNode" /> <item name="example" type="462c0819:PsiDirectoryNode" />
</path> </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="assets" type="462c0819:PsiDirectoryNode" />
<item name="images" 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="example" type="462c0819:PsiDirectoryNode" />
<item name="test_driver" 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" />
</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> </expand>
<select /> <select />
</subPane> </subPane>
...@@ -284,6 +340,10 @@ ...@@ -284,6 +340,10 @@
<property name="show.migrate.to.gradle.popup" value="false" /> <property name="show.migrate.to.gradle.popup" value="false" />
</component> </component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/example/assets/images" />
<recent name="$PROJECT_DIR$/android/src/main/java" />
</key>
<key name="CopyFile.RECENT_KEYS"> <key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/example/test_driver" /> <recent name="$PROJECT_DIR$/example/test_driver" />
<recent name="$PROJECT_DIR$/example/test_assets" /> <recent name="$PROJECT_DIR$/example/test_assets" />
...@@ -291,10 +351,6 @@ ...@@ -291,10 +351,6 @@
<recent name="$PROJECT_DIR$/example/assets/images" /> <recent name="$PROJECT_DIR$/example/assets/images" />
<recent name="$PROJECT_DIR$/android/libs" /> <recent name="$PROJECT_DIR$/android/libs" />
</key> </key>
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/example/assets/images" />
<recent name="$PROJECT_DIR$/android/src/main/java" />
</key>
</component> </component>
<component name="RunDashboard"> <component name="RunDashboard">
<option name="ruleStates"> <option name="ruleStates">
...@@ -412,8 +468,7 @@ ...@@ -412,8 +468,7 @@
</todo-panel> </todo-panel>
</component> </component>
<component name="ToolWindowManager"> <component name="ToolWindowManager">
<frame x="0" y="23" width="1920" height="1057" extended-state="0" /> <frame x="-1" y="23" width="1920" height="1057" extended-state="6" />
<editor active="true" />
<layout> <layout>
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.6177474" visible="true" weight="0.20766774" /> <window_info content_ui="combo" id="Project" order="0" sideWeight="0.6177474" visible="true" weight="0.20766774" />
<window_info id="Structure" order="1" sideWeight="0.38225257" side_tool="true" weight="0.2087327" /> <window_info id="Structure" order="1" sideWeight="0.38225257" side_tool="true" weight="0.2087327" />
...@@ -434,7 +489,7 @@ ...@@ -434,7 +489,7 @@
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" /> <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="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="Version Control" order="9" />
<window_info active="true" anchor="bottom" id="Terminal" order="10" sideWeight="0.4946752" visible="true" weight="0.38860103" /> <window_info active="true" anchor="bottom" id="Terminal" order="10" sideWeight="0.4946752" visible="true" weight="0.5668394" />
<window_info anchor="bottom" id="Logcat" order="11" weight="0.32953367" /> <window_info anchor="bottom" id="Logcat" order="11" weight="0.32953367" />
<window_info anchor="bottom" id="Messages" order="12" sideWeight="0.4968051" weight="0.33782384" /> <window_info anchor="bottom" id="Messages" order="12" sideWeight="0.4968051" weight="0.33782384" />
<window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" /> <window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" />
...@@ -464,55 +519,6 @@ ...@@ -464,55 +519,6 @@
</ignored-roots> </ignored-roots>
</component> </component>
<component name="editorHistoryManager"> <component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/lib/src/content_blocker.dart">
<provider selected="true" editor-type-id="text-editor">
<state>
<folding>
<element signature="e#0#41#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/test.sh">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="570">
<caret line="1614" column="101" selection-start-line="1614" selection-start-column="70" selection-end-line="1614" selection-end-column="101" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/flutter_webview_example_android.iml">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/example/flutter_webview_example.iml">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/ios/flutter_inappwebview.podspec">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="60">
<caret line="4" column="44" selection-start-line="4" selection-start-column="44" selection-end-line="4" selection-end-column="44" />
</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="45">
<caret line="3" column="57" selection-start-line="3" selection-start-column="57" selection-end-line="3" selection-end-column="57" />
</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 relative-caret-position="15">
<caret line="1" column="57" selection-start-line="1" selection-start-column="57" selection-end-line="1" selection-end-column="57" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/custom_widget_test.dart"> <entry file="file://$PROJECT_DIR$/example/test_driver/custom_widget_test.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="45"> <state relative-caret-position="45">
...@@ -562,13 +568,6 @@ ...@@ -562,13 +568,6 @@
</state> </state>
</provider> </provider>
</entry> </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="30">
<caret line="2" column="57" selection-start-line="2" selection-start-column="57" selection-end-line="2" selection-end-column="57" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_initial_url_test.dart"> <entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_initial_url_test.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30"> <state relative-caret-position="30">
...@@ -611,13 +610,6 @@ ...@@ -611,13 +610,6 @@
</state> </state>
</provider> </provider>
</entry> </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="30">
<caret line="2" column="57" selection-start-line="2" selection-start-column="57" selection-end-line="2" selection-end-column="57" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_http_error_test.dart"> <entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_http_error_test.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30"> <state relative-caret-position="30">
...@@ -688,143 +680,222 @@ ...@@ -688,143 +680,222 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_ssl_request_test.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="15">
<caret line="1" column="57" selection-start-line="1" selection-start-column="57" selection-end-line="1" selection-end-column="57" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/ios/Classes/InAppWebViewFlutterPlugin.h">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="285">
<caret line="19" column="36" selection-start-line="19" selection-start-column="36" selection-end-line="19" selection-end-column="36" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/ios/Classes/InAppWebViewFlutterPlugin.m">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300">
<caret line="20" column="41" selection-start-line="20" selection-start-column="16" selection-end-line="20" selection-end-column="41" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-496"> <state relative-caret-position="765">
<caret line="51" column="91" selection-start-line="51" selection-start-column="71" selection-end-line="51" selection-end-column="91" />
</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="180">
<caret line="12" column="101" selection-start-line="12" selection-start-column="101" selection-end-line="12" selection-end-column="101" />
<folding> <folding>
<element signature="e#1#40#0" expanded="true" /> <element signature="e#0#20#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart"> <entry file="file://$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="32"> <state relative-caret-position="195">
<caret line="3" column="20" selection-start-line="3" selection-start-column="20" selection-end-line="3" selection-end-column="20" /> <caret line="13" column="101" selection-start-line="13" selection-start-column="101" selection-end-line="13" selection-end-column="101" />
<folding> <folding>
<element signature="e#0#17#0" expanded="true" /> <element signature="e#0#20#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart"> <entry file="file://$PROJECT_DIR$/example/assets/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-147" />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/test_assets/in_app_webview_initial_file_test.html">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="90"> <state relative-caret-position="135">
<caret line="6" column="8" selection-start-line="6" selection-start-column="8" selection-end-line="6" selection-end-column="8" /> <caret line="9" column="22" selection-start-line="9" selection-start-column="22" selection-end-line="9" selection-end-column="22" />
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart"> <entry file="file://$PROJECT_DIR$/android/src/main/AndroidManifest.xml">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<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"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="15"> <state relative-caret-position="195">
<caret line="1" column="57" selection-start-line="1" selection-start-column="57" selection-end-line="1" selection-end-column="57" /> <caret line="13" lean-forward="true" selection-start-line="13" selection-end-line="13" />
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml"> <entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_error_test.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="180"> <state relative-caret-position="357">
<caret line="12" column="32" selection-start-line="12" selection-start-column="32" selection-end-line="12" selection-end-column="32" /> <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> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/ios/Classes/InAppWebViewFlutterPlugin.h"> <entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="285"> <state relative-caret-position="161">
<caret line="19" column="36" selection-start-line="19" selection-start-column="36" selection-end-line="19" selection-end-column="36" /> <caret line="480" column="9" selection-start-line="480" selection-start-column="9" selection-end-line="480" selection-end-column="9" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/ios/Classes/InAppWebViewFlutterPlugin.m"> <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"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300"> <state relative-caret-position="75">
<caret line="20" column="41" selection-start-line="20" selection-start-column="16" selection-end-line="20" selection-end-column="41" /> <caret line="11" column="5" selection-start-line="11" selection-start-column="5" selection-end-line="11" selection-end-column="5" />
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/example/lib/main.dart"> <entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_ssl_request_test.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>
</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"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="182"> <state relative-caret-position="96">
<caret line="14" column="1" lean-forward="true" selection-start-line="14" selection-start-column="1" selection-end-line="14" selection-end-column="1" /> <caret line="28" column="85" selection-start-line="28" selection-start-column="20" selection-end-line="28" selection-end-column="85" />
<folding> <folding>
<element signature="e#0#20#0" expanded="true" /> <element signature="e#0#39#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift"> <entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="765"> <state relative-caret-position="360">
<caret line="51" column="91" selection-start-line="51" selection-start-column="71" selection-end-line="51" selection-end-column="91" /> <caret line="24" column="24" selection-start-line="24" selection-start-column="24" selection-end-line="24" selection-end-column="24" />
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart"> <entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="235"> <state relative-caret-position="161">
<caret line="1170" column="66" selection-start-line="1170" selection-start-column="66" selection-end-line="1170" selection-end-column="66" /> <caret line="105" column="30" selection-start-line="105" selection-start-column="15" selection-end-line="105" selection-end-column="30" />
<folding> <folding>
<element signature="e#0#17#0" expanded="true" /> <element signature="e#0#17#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/lib/src/cookie_manager.dart"> <entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="180"> <state relative-caret-position="165">
<caret line="12" column="101" selection-start-line="12" selection-start-column="101" selection-end-line="12" selection-end-column="101" /> <caret line="11" column="10" selection-start-line="11" selection-start-column="10" selection-end-line="11" selection-end-column="10" />
</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="413">
<caret line="539" column="3" lean-forward="true" selection-start-line="539" selection-start-column="3" selection-end-line="539" selection-end-column="3" />
<folding> <folding>
<element signature="e#0#20#0" expanded="true" /> <element signature="e#0#20#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart"> <entry file="file://$PROJECT_DIR$/lib/src/channel_manager.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195"> <state relative-caret-position="225">
<caret line="13" column="101" selection-start-line="13" selection-start-column="101" selection-end-line="13" selection-end-column="101" /> <caret line="15" column="36" selection-start-line="15" selection-start-column="36" selection-end-line="15" selection-end-column="36" />
<folding> <folding>
<element signature="e#0#20#0" expanded="true" /> <element signature="e#0#20#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/example/assets/index.html"> <entry file="file://$PROJECT_DIR$/lib/flutter_inappwebview.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-147" /> <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> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/example/test_assets/in_app_webview_initial_file_test.html"> <entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="135"> <state relative-caret-position="10620">
<caret line="9" column="22" selection-start-line="9" selection-start-column="22" selection-end-line="9" selection-end-column="22" /> <caret line="708" column="23" lean-forward="true" selection-start-line="708" selection-start-column="23" selection-end-line="708" selection-end-column="23" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/android/src/main/AndroidManifest.xml"> <entry file="file://$USER_HOME$/Downloads/in_app_webiew_example.screen.dart">
<provider selected="true" editor-type-id="text-editor" /> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="345">
<caret line="33" column="57" selection-start-line="33" selection-start-column="2" selection-end-line="33" selection-end-column="57" />
</state>
</provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/CHANGELOG.md"> <entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="255"> <state relative-caret-position="12735">
<caret line="17" column="101" lean-forward="true" selection-start-line="17" selection-start-column="101" selection-end-line="17" selection-end-column="101" /> <caret line="849" selection-start-line="849" selection-end-line="849" />
<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> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/pubspec.yaml"> <entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state> <state relative-caret-position="30">
<caret column="26" selection-start-column="6" selection-end-column="26" /> <caret line="2" column="145" selection-start-line="2" selection-start-column="145" selection-end-line="2" selection-end-column="145" />
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/README.md"> <entry file="file://$PROJECT_DIR$/example/README.md">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="330"> <state relative-caret-position="304">
<caret line="22" column="92" selection-start-line="22" selection-start-column="92" selection-end-line="22" selection-end-column="92" /> <caret line="78" column="1" selection-start-line="78" selection-start-column="1" selection-end-line="78" selection-end-column="1" />
<folding> <folding>
<element signature="e#0#39#0" expanded="true" /> <element signature="e#0#20#0" expanded="true" />
<element signature="e#0#39#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
......
## 2.0.1+1
- Fixed error "java.lang.ClassCastException: $Proxy1 cannot be cast to android.view.WindowManagerImpl" on Android when using native alert dialogs
## 2.0.1 ## 2.0.1
- Added `onPermissionRequest` event. This event is 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). - Added `onPermissionRequest` event. This event is 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).
......
...@@ -14,7 +14,7 @@ A Flutter plugin that allows you to add an inline webview or open an in-app brow ...@@ -14,7 +14,7 @@ A Flutter plugin that allows you to add an inline webview or open an in-app brow
- Dart sdk: ">=2.0.0-dev.68.0 <3.0.0" - Dart sdk: ">=2.0.0-dev.68.0 <3.0.0"
- Flutter: ">=1.9.1+hotfix.5 <2.0.0" - Flutter: ">=1.9.1+hotfix.5 <2.0.0"
- Android: `minSdkVersion 17` - Android: `minSdkVersion 17`
- iOS: `--ios-language swift` - iOS: `--ios-language swift`, Xcode version `>= 11`
### Note for Android ### Note for Android
...@@ -440,7 +440,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: ...@@ -440,7 +440,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `onSafeBrowsingHit`: Event fired when the webview notifies that a loading URL has been flagged by Safe Browsing (available only on Android). * `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. * `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). * `onReceivedServerTrustAuthRequest`: Event fired when the WebView need to perform server trust authentication (certificate validation).
* `onReceivedClientCertRequest`: Notify the host application to handle a SSL client certificate request. * `onReceivedClientCertRequest`: Notify the host application to handle an SSL client certificate request.
* `onFindResultReceived`: Event fired as find-on-page operations progress. * `onFindResultReceived`: Event fired as find-on-page operations progress.
* `shouldInterceptAjaxRequest`: Event fired when an `XMLHttpRequest` is sent to a server. * `shouldInterceptAjaxRequest`: Event fired when an `XMLHttpRequest` is sent to a server.
* `onAjaxReadyStateChange`: Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes. * `onAjaxReadyStateChange`: Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes.
......
...@@ -164,7 +164,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -164,7 +164,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
}; };
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(view.getContext(), R.style.Theme_AppCompat_Dialog_Alert); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(registrar.activeContext(), R.style.Theme_AppCompat_Dialog_Alert);
alertDialogBuilder.setMessage(alertMessage); alertDialogBuilder.setMessage(alertMessage);
if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) { if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) {
alertDialogBuilder.setPositiveButton(confirmButtonTitle, clickListener); alertDialogBuilder.setPositiveButton(confirmButtonTitle, clickListener);
...@@ -255,7 +255,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -255,7 +255,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
}; };
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(view.getContext(), R.style.Theme_AppCompat_Dialog_Alert); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(registrar.activeContext(), R.style.Theme_AppCompat_Dialog_Alert);
alertDialogBuilder.setMessage(alertMessage); alertDialogBuilder.setMessage(alertMessage);
if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) { if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) {
alertDialogBuilder.setPositiveButton(confirmButtonTitle, confirmClickListener); alertDialogBuilder.setPositiveButton(confirmButtonTitle, confirmClickListener);
...@@ -372,7 +372,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -372,7 +372,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
} }
}; };
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(view.getContext(), R.style.Theme_AppCompat_Dialog_Alert); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(registrar.activeContext(), R.style.Theme_AppCompat_Dialog_Alert);
alertDialogBuilder.setMessage(alertMessage); alertDialogBuilder.setMessage(alertMessage);
if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) { if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) {
alertDialogBuilder.setPositiveButton(confirmButtonTitle, confirmClickListener); alertDialogBuilder.setPositiveButton(confirmButtonTitle, confirmClickListener);
......
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
# This is a generated file; do not edit or check into version control. # This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter" export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/test_driver/app.dart" export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart"
export "FLUTTER_BUILD_DIR=build" export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios" export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios" export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios"
export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1" export "FLUTTER_BUILD_NUMBER=1"
export "TRACK_WIDGET_CREATION=true"
...@@ -268,6 +268,8 @@ ...@@ -268,6 +268,8 @@
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework",
"${BUILT_PRODUCTS_DIR}/connectivity/connectivity.framework",
"${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework", "${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework",
"${BUILT_PRODUCTS_DIR}/flutter_inappwebview/flutter_inappwebview.framework", "${BUILT_PRODUCTS_DIR}/flutter_inappwebview/flutter_inappwebview.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
...@@ -275,6 +277,8 @@ ...@@ -275,6 +277,8 @@
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
......
...@@ -22,6 +22,7 @@ dependencies: ...@@ -22,6 +22,7 @@ dependencies:
flutter_downloader: ^1.3.2 flutter_downloader: ^1.3.2
path_provider: ^1.4.0 path_provider: ^1.4.0
permission_handler: ^3.3.0 permission_handler: ^3.3.0
connectivity: ^0.4.5+6
flutter_inappwebview: flutter_inappwebview:
path: ../ path: ../
......
...@@ -27,7 +27,7 @@ class InAppWebViewOnLoadErrorTestState extends WidgetTestState { ...@@ -27,7 +27,7 @@ class InAppWebViewOnLoadErrorTestState extends WidgetTestState {
Expanded( Expanded(
child: Container( child: Container(
child: InAppWebView( child: InAppWebView(
initialUrl: "http://not-existing-domain.org/", initialUrl: "https://not-existing-domain.org/",
initialHeaders: {}, initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions( initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions( inAppWebViewOptions: InAppWebViewOptions(
......
...@@ -6,7 +6,8 @@ import 'package:flutter/services.dart'; ...@@ -6,7 +6,8 @@ import 'package:flutter/services.dart';
import 'types.dart' show ListenerCallback; import 'types.dart' show ListenerCallback;
class ChannelManager { class ChannelManager {
static const MethodChannel channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser'); static const MethodChannel channel =
const MethodChannel('com.pichillilorenzo/flutter_inappbrowser');
static bool initialized = false; static bool initialized = false;
static final listeners = HashMap<String, ListenerCallback>(); static final listeners = HashMap<String, ListenerCallback>();
...@@ -16,12 +17,11 @@ class ChannelManager { ...@@ -16,12 +17,11 @@ class ChannelManager {
} }
static void addListener(String key, ListenerCallback callback) { static void addListener(String key, ListenerCallback callback) {
if (!initialized) if (!initialized) init();
init();
listeners.putIfAbsent(key, () => callback); listeners.putIfAbsent(key, () => callback);
} }
static void init () { static void init() {
channel.setMethodCallHandler(_handleMethod); channel.setMethodCallHandler(_handleMethod);
initialized = true; initialized = true;
} }
......
...@@ -20,7 +20,7 @@ class ChromeSafariBrowser { ...@@ -20,7 +20,7 @@ class ChromeSafariBrowser {
bool _isOpened = false; bool _isOpened = false;
///Initialize the [ChromeSafariBrowser] instance with an [InAppBrowser] fallback instance or `null`. ///Initialize the [ChromeSafariBrowser] instance with an [InAppBrowser] fallback instance or `null`.
ChromeSafariBrowser ({bFallback}) { ChromeSafariBrowser({bFallback}) {
uuid = uuidGenerator.v4(); uuid = uuidGenerator.v4();
browserFallback = bFallback; browserFallback = bFallback;
ChannelManager.addListener(uuid, handleMethod); ChannelManager.addListener(uuid, handleMethod);
...@@ -28,7 +28,7 @@ class ChromeSafariBrowser { ...@@ -28,7 +28,7 @@ class ChromeSafariBrowser {
} }
Future<dynamic> handleMethod(MethodCall call) async { Future<dynamic> handleMethod(MethodCall call) async {
switch(call.method) { switch (call.method) {
case "onChromeSafariBrowserOpened": case "onChromeSafariBrowserOpened":
onOpened(); onOpened();
break; break;
...@@ -53,7 +53,11 @@ class ChromeSafariBrowser { ...@@ -53,7 +53,11 @@ class ChromeSafariBrowser {
///[headersFallback]: The additional header of the [InAppBrowser] instance fallback to be used in the HTTP request for this URL, specified as a map from name to value. ///[headersFallback]: The additional header of the [InAppBrowser] instance fallback to be used in the HTTP request for this URL, specified as a map from name to value.
/// ///
///[optionsFallback]: Options used by the [InAppBrowser] instance fallback. ///[optionsFallback]: Options used by the [InAppBrowser] instance fallback.
Future<void> open({@required String url, ChromeSafariBrowserClassOptions options, Map<String, String> headersFallback = const {}, InAppBrowserClassOptions optionsFallback}) async { Future<void> open(
{@required String url,
ChromeSafariBrowserClassOptions options,
Map<String, String> headersFallback = const {},
InAppBrowserClassOptions optionsFallback}) async {
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $url!'); this.throwIsAlreadyOpened(message: 'Cannot open $url!');
...@@ -65,21 +69,33 @@ class ChromeSafariBrowser { ...@@ -65,21 +69,33 @@ class ChromeSafariBrowser {
Map<String, dynamic> optionsFallbackMap = {}; Map<String, dynamic> optionsFallbackMap = {};
if (optionsFallback != null) { if (optionsFallback != null) {
optionsFallbackMap.addAll(optionsFallback.inAppBrowserOptions?.toMap() ?? {}); optionsFallbackMap
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {}); .addAll(optionsFallback.inAppBrowserOptions?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback
.inAppWebViewWidgetOptions?.inAppWebViewOptions
?.toMap() ??
{});
if (Platform.isAndroid) { if (Platform.isAndroid) {
optionsFallbackMap.addAll(optionsFallback.androidInAppBrowserOptions?.toMap() ?? {}); optionsFallbackMap
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {}); .addAll(optionsFallback.androidInAppBrowserOptions?.toMap() ?? {});
} optionsFallbackMap.addAll(optionsFallback
else if (Platform.isIOS) { .inAppWebViewWidgetOptions?.androidInAppWebViewOptions
optionsFallbackMap.addAll(optionsFallback.iosInAppBrowserOptions?.toMap() ?? {}); ?.toMap() ??
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {}); {});
} else if (Platform.isIOS) {
optionsFallbackMap
.addAll(optionsFallback.iosInAppBrowserOptions?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback
.inAppWebViewWidgetOptions?.iosInAppWebViewOptions
?.toMap() ??
{});
} }
} }
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid); args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('uuidFallback', () => (browserFallback != null) ? browserFallback.uuid : ''); args.putIfAbsent('uuidFallback',
() => (browserFallback != null) ? browserFallback.uuid : '');
args.putIfAbsent('url', () => url); args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headersFallback); args.putIfAbsent('headers', () => headersFallback);
args.putIfAbsent('options', () => optionsMap); args.putIfAbsent('options', () => optionsMap);
...@@ -91,19 +107,13 @@ class ChromeSafariBrowser { ...@@ -91,19 +107,13 @@ class ChromeSafariBrowser {
} }
///Event fires when the [ChromeSafariBrowser] is opened. ///Event fires when the [ChromeSafariBrowser] is opened.
void onOpened() { void onOpened() {}
}
///Event fires when the [ChromeSafariBrowser] is loaded. ///Event fires when the [ChromeSafariBrowser] is loaded.
void onLoaded() { void onLoaded() {}
}
///Event fires when the [ChromeSafariBrowser] is closed. ///Event fires when the [ChromeSafariBrowser] is closed.
void onClosed() { void onClosed() {}
}
///Returns `true` if the [ChromeSafariBrowser] instance is opened, otherwise `false`. ///Returns `true` if the [ChromeSafariBrowser] instance is opened, otherwise `false`.
bool isOpened() { bool isOpened() {
...@@ -112,13 +122,17 @@ class ChromeSafariBrowser { ...@@ -112,13 +122,17 @@ class ChromeSafariBrowser {
void throwIsAlreadyOpened({String message = ''}) { void throwIsAlreadyOpened({String message = ''}) {
if (this.isOpened()) { if (this.isOpened()) {
throw Exception(['Error: ${ (message.isEmpty) ? '' : message + ' '}The browser is already opened.']); throw Exception([
'Error: ${(message.isEmpty) ? '' : message + ' '}The browser is already opened.'
]);
} }
} }
void throwIsNotOpened({String message = ''}) { void throwIsNotOpened({String message = ''}) {
if (!this.isOpened()) { if (!this.isOpened()) {
throw Exception(['Error: ${ (message.isEmpty) ? '' : message + ' '}The browser is not opened.']); throw Exception([
'Error: ${(message.isEmpty) ? '' : message + ' '}The browser is not opened.'
]);
} }
} }
} }
...@@ -11,27 +11,22 @@ import 'types.dart'; ...@@ -11,27 +11,22 @@ import 'types.dart';
class ContentBlocker { class ContentBlocker {
///Trigger of the content blocker. The trigger tells to the WebView when to perform the corresponding action. ///Trigger of the content blocker. The trigger tells to the WebView when to perform the corresponding action.
ContentBlockerTrigger trigger; ContentBlockerTrigger trigger;
///Action associated to the trigger. The action tells to the WebView what to do when the trigger is matched. ///Action associated to the trigger. The action tells to the WebView what to do when the trigger is matched.
ContentBlockerAction action; ContentBlockerAction action;
ContentBlocker({@required this.trigger,@required this.action}); ContentBlocker({@required this.trigger, @required this.action});
Map<String, Map<String, dynamic>> toMap() { Map<String, Map<String, dynamic>> toMap() {
return { return {"trigger": trigger.toMap(), "action": action.toMap()};
"trigger": trigger.toMap(),
"action": action.toMap()
};
} }
static ContentBlocker fromMap(Map<dynamic, Map<dynamic, dynamic>> map) { static ContentBlocker fromMap(Map<dynamic, Map<dynamic, dynamic>> map) {
return ContentBlocker( return ContentBlocker(
trigger: ContentBlockerTrigger.fromMap( trigger: ContentBlockerTrigger.fromMap(
Map<String, dynamic>.from(map["trigger"]) Map<String, dynamic>.from(map["trigger"])),
),
action: ContentBlockerAction.fromMap( action: ContentBlockerAction.fromMap(
Map<String, dynamic>.from(map["action"]) Map<String, dynamic>.from(map["action"])));
)
);
} }
} }
...@@ -42,29 +37,42 @@ class ContentBlocker { ...@@ -42,29 +37,42 @@ class ContentBlocker {
class ContentBlockerTrigger { class ContentBlockerTrigger {
///A regular expression pattern to match the URL against. ///A regular expression pattern to match the URL against.
String urlFilter; String urlFilter;
///Used only by iOS. A Boolean value. The default value is false. ///Used only by iOS. A Boolean value. The default value is false.
bool urlFilterIsCaseSensitive; bool urlFilterIsCaseSensitive;
///A list of [ContentBlockerTriggerResourceType] representing the resource types (how the browser intends to use the resource) that the rule should match. ///A list of [ContentBlockerTriggerResourceType] representing the resource types (how the browser intends to use the resource) that the rule should match.
///If not specified, the rule matches all resource types. ///If not specified, the rule matches all resource types.
List<ContentBlockerTriggerResourceType> resourceType; List<ContentBlockerTriggerResourceType> resourceType;
///A list of strings matched to a URL's domain; limits action to a list of specific domains. ///A list of strings matched to a URL's domain; limits action to a list of specific domains.
///Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with [ContentBlockerTrigger.unlessDomain]. ///Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with [ContentBlockerTrigger.unlessDomain].
List<String> ifDomain; List<String> ifDomain;
///A list of strings matched to a URL's domain; acts on any site except domains in a provided list. ///A list of strings matched to a URL's domain; acts on any site except domains in a provided list.
///Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with [ContentBlockerTrigger.ifDomain]. ///Values must be lowercase ASCII, or punycode for non-ASCII. Add * in front to match domain and subdomains. Can't be used with [ContentBlockerTrigger.ifDomain].
List<String> unlessDomain; List<String> unlessDomain;
///A list of [ContentBlockerTriggerLoadType] that can include one of two mutually exclusive values. If not specified, the rule matches all load types. ///A list of [ContentBlockerTriggerLoadType] that can include one of two mutually exclusive values. If not specified, the rule matches all load types.
List<ContentBlockerTriggerLoadType> loadType; List<ContentBlockerTriggerLoadType> loadType;
///A list of strings matched to the entire main document URL; limits the action to a specific list of URL patterns. ///A list of strings matched to the entire main document URL; limits the action to a specific list of URL patterns.
///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.unlessTopUrl]. ///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.unlessTopUrl].
List<String> ifTopUrl; List<String> ifTopUrl;
///An array of strings matched to the entire main document URL; acts on any site except URL patterns in provided list. ///An array of strings matched to the entire main document URL; acts on any site except URL patterns in provided list.
///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.ifTopUrl]. ///Values must be lowercase ASCII, or punycode for non-ASCII. Can't be used with [ContentBlockerTrigger.ifTopUrl].
List<String> unlessTopUrl; List<String> unlessTopUrl;
ContentBlockerTrigger({@required String urlFilter, bool urlFilterIsCaseSensitive = false, List<ContentBlockerTriggerResourceType> resourceType = const [], ContentBlockerTrigger(
List<String> ifDomain = const [], List<String> unlessDomain = const [], List<ContentBlockerTriggerLoadType> loadType = const [], {@required String urlFilter,
List<String> ifTopUrl = const [], List<String> unlessTopUrl = const []}) { bool urlFilterIsCaseSensitive = false,
List<ContentBlockerTriggerResourceType> resourceType = const [],
List<String> ifDomain = const [],
List<String> unlessDomain = const [],
List<ContentBlockerTriggerLoadType> loadType = const [],
List<String> ifTopUrl = const [],
List<String> unlessTopUrl = const []}) {
this.urlFilter = urlFilter; this.urlFilter = urlFilter;
assert(this.urlFilter != null); assert(this.urlFilter != null);
this.resourceType = resourceType; this.resourceType = resourceType;
...@@ -101,7 +109,9 @@ class ContentBlockerTrigger { ...@@ -101,7 +109,9 @@ class ContentBlockerTrigger {
}; };
map.keys map.keys
.where((key) => map[key] == null || (map[key] is List && (map[key] as List).length == 0)) // filter keys .where((key) =>
map[key] == null ||
(map[key] is List && (map[key] as List).length == 0)) // filter keys
.toList() // create a copy to avoid concurrent modifications .toList() // create a copy to avoid concurrent modifications
.forEach(map.remove); .forEach(map.remove);
...@@ -112,7 +122,8 @@ class ContentBlockerTrigger { ...@@ -112,7 +122,8 @@ class ContentBlockerTrigger {
List<ContentBlockerTriggerResourceType> resourceType = []; List<ContentBlockerTriggerResourceType> resourceType = [];
List<ContentBlockerTriggerLoadType> loadType = []; List<ContentBlockerTriggerLoadType> loadType = [];
List<String> resourceTypeStringList = List<String>.from(map["resource-type"] ?? []); List<String> resourceTypeStringList =
List<String>.from(map["resource-type"] ?? []);
resourceTypeStringList.forEach((type) { resourceTypeStringList.forEach((type) {
resourceType.add(ContentBlockerTriggerResourceType.fromValue(type)); resourceType.add(ContentBlockerTriggerResourceType.fromValue(type));
}); });
...@@ -130,8 +141,7 @@ class ContentBlockerTrigger { ...@@ -130,8 +141,7 @@ class ContentBlockerTrigger {
resourceType: resourceType, resourceType: resourceType,
loadType: loadType, loadType: loadType,
ifTopUrl: List<String>.from(map["if-top-url"] ?? []), ifTopUrl: List<String>.from(map["if-top-url"] ?? []),
unlessTopUrl: List<String>.from(map["unless-top-url"] ?? []) unlessTopUrl: List<String>.from(map["unless-top-url"] ?? []));
);
} }
} }
...@@ -143,11 +153,13 @@ class ContentBlockerTrigger { ...@@ -143,11 +153,13 @@ class ContentBlockerTrigger {
class ContentBlockerAction { class ContentBlockerAction {
///Type of the action. ///Type of the action.
ContentBlockerActionType type; ContentBlockerActionType type;
///If the action type is [ContentBlockerActionType.CSS_DISPLAY_NONE], then also the [selector] property is required, otherwise it is ignored. ///If the action type is [ContentBlockerActionType.CSS_DISPLAY_NONE], then also the [selector] property is required, otherwise it is ignored.
///It specify a string that defines a selector list. Use CSS identifiers as the individual selector values, separated by commas. ///It specify a string that defines a selector list. Use CSS identifiers as the individual selector values, separated by commas.
String selector; String selector;
ContentBlockerAction({@required ContentBlockerActionType type, String selector}) { ContentBlockerAction(
{@required ContentBlockerActionType type, String selector}) {
this.type = type; this.type = type;
assert(this.type != null); assert(this.type != null);
if (this.type == ContentBlockerActionType.CSS_DISPLAY_NONE) { if (this.type == ContentBlockerActionType.CSS_DISPLAY_NONE) {
...@@ -157,13 +169,12 @@ class ContentBlockerAction { ...@@ -157,13 +169,12 @@ class ContentBlockerAction {
} }
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
Map<String, dynamic> map = { Map<String, dynamic> map = {"type": type.toValue(), "selector": selector};
"type": type.toValue(),
"selector": selector
};
map.keys map.keys
.where((key) => map[key] == null || (map[key] is List && (map[key] as List).length == 0)) // filter keys .where((key) =>
map[key] == null ||
(map[key] is List && (map[key] as List).length == 0)) // filter keys
.toList() // create a copy to avoid concurrent modifications .toList() // create a copy to avoid concurrent modifications
.forEach(map.remove); .forEach(map.remove);
...@@ -173,7 +184,6 @@ class ContentBlockerAction { ...@@ -173,7 +184,6 @@ class ContentBlockerAction {
static ContentBlockerAction fromMap(Map<String, dynamic> map) { static ContentBlockerAction fromMap(Map<String, dynamic> map) {
return ContentBlockerAction( return ContentBlockerAction(
type: ContentBlockerActionType.fromValue(map["type"]), type: ContentBlockerActionType.fromValue(map["type"]),
selector: map["selector"] selector: map["selector"]);
);
} }
} }
...@@ -10,7 +10,8 @@ import 'types.dart'; ...@@ -10,7 +10,8 @@ import 'types.dart';
///**NOTE for iOS**: available from iOS 11.0+. ///**NOTE for iOS**: available from iOS 11.0+.
class CookieManager { class CookieManager {
static CookieManager _instance; static CookieManager _instance;
static const MethodChannel _channel = const MethodChannel('com.pichillilorenzo/flutter_inappwebview_cookiemanager'); static const MethodChannel _channel = const MethodChannel(
'com.pichillilorenzo/flutter_inappwebview_cookiemanager');
///Gets the cookie manager shared instance. ///Gets the cookie manager shared instance.
static CookieManager instance() { static CookieManager instance() {
...@@ -23,21 +24,22 @@ class CookieManager { ...@@ -23,21 +24,22 @@ class CookieManager {
return _instance; return _instance;
} }
static Future<dynamic> _handleMethod(MethodCall call) async { static Future<dynamic> _handleMethod(MethodCall call) async {}
}
///Sets a cookie for the given [url]. Any existing cookie with the same [host], [path] and [name] will be replaced with the new cookie. The cookie being set will be ignored if it is expired. ///Sets a cookie for the given [url]. Any existing cookie with the same [host], [path] and [name] will be replaced with the new cookie. The cookie being set will be ignored if it is expired.
/// ///
///The default value of [path] is `"/"`. ///The default value of [path] is `"/"`.
///If [domain] is `null`, its default value will be the domain name of [url]. ///If [domain] is `null`, its default value will be the domain name of [url].
Future<void> setCookie({@required String url, @required String name, @required String value, Future<void> setCookie(
{@required String url,
@required String name,
@required String value,
String domain, String domain,
String path = "/", String path = "/",
int expiresDate, int expiresDate,
int maxAge, int maxAge,
bool isSecure }) async { bool isSecure}) async {
if (domain == null) if (domain == null) domain = _getDomainName(url);
domain = _getDomainName(url);
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
assert(name != null && name.isNotEmpty); assert(name != null && name.isNotEmpty);
...@@ -64,17 +66,20 @@ class CookieManager { ...@@ -64,17 +66,20 @@ class CookieManager {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('url', () => url); args.putIfAbsent('url', () => url);
List<dynamic> cookieListMap = await _channel.invokeMethod('getCookies', args); List<dynamic> cookieListMap =
await _channel.invokeMethod('getCookies', args);
cookieListMap = cookieListMap.cast<Map<dynamic, dynamic>>(); cookieListMap = cookieListMap.cast<Map<dynamic, dynamic>>();
List<Cookie> cookies = []; List<Cookie> cookies = [];
for(var i = 0; i < cookieListMap.length; i++) { for (var i = 0; i < cookieListMap.length; i++) {
cookies.add(Cookie(name: cookieListMap[i]["name"], value: cookieListMap[i]["value"])); cookies.add(Cookie(
name: cookieListMap[i]["name"], value: cookieListMap[i]["value"]));
} }
return cookies; return cookies;
} }
///Gets a cookie by its [name] for the given [url]. ///Gets a cookie by its [name] for the given [url].
Future<Cookie> getCookie({@required String url, @required String name}) async { Future<Cookie> getCookie(
{@required String url, @required String name}) async {
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
assert(name != null && name.isNotEmpty); assert(name != null && name.isNotEmpty);
...@@ -82,7 +87,7 @@ class CookieManager { ...@@ -82,7 +87,7 @@ class CookieManager {
args.putIfAbsent('url', () => url); args.putIfAbsent('url', () => url);
List<dynamic> cookies = await _channel.invokeMethod('getCookies', args); List<dynamic> cookies = await _channel.invokeMethod('getCookies', args);
cookies = cookies.cast<Map<dynamic, dynamic>>(); cookies = cookies.cast<Map<dynamic, dynamic>>();
for(var i = 0; i < cookies.length; i++) { for (var i = 0; i < cookies.length; i++) {
cookies[i] = cookies[i].cast<String, dynamic>(); cookies[i] = cookies[i].cast<String, dynamic>();
if (cookies[i]["name"] == name) if (cookies[i]["name"] == name)
return Cookie(name: cookies[i]["name"], value: cookies[i]["value"]); return Cookie(name: cookies[i]["name"], value: cookies[i]["value"]);
...@@ -94,9 +99,12 @@ class CookieManager { ...@@ -94,9 +99,12 @@ class CookieManager {
/// ///
///The default value of [path] is `"/"`. ///The default value of [path] is `"/"`.
///If [domain] is `null` or empty, its default value will be the domain name of [url]. ///If [domain] is `null` or empty, its default value will be the domain name of [url].
Future<void> deleteCookie({@required String url, @required String name, String domain = "", String path = "/"}) async { Future<void> deleteCookie(
if (domain == null || domain.isEmpty) {@required String url,
domain = _getDomainName(url); @required String name,
String domain = "",
String path = "/"}) async {
if (domain == null || domain.isEmpty) domain = _getDomainName(url);
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
assert(name != null && name.isNotEmpty); assert(name != null && name.isNotEmpty);
...@@ -115,9 +123,9 @@ class CookieManager { ...@@ -115,9 +123,9 @@ class CookieManager {
/// ///
///The default value of [path] is `"/"`. ///The default value of [path] is `"/"`.
///If [domain] is `null` or empty, its default value will be the domain name of [url]. ///If [domain] is `null` or empty, its default value will be the domain name of [url].
Future<void> deleteCookies({@required String url, String domain = "", String path = "/"}) async { Future<void> deleteCookies(
if (domain == null || domain.isEmpty) {@required String url, String domain = "", String path = "/"}) async {
domain = _getDomainName(url); if (domain == null || domain.isEmpty) domain = _getDomainName(url);
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
assert(domain != null && url.isNotEmpty); assert(domain != null && url.isNotEmpty);
...@@ -139,8 +147,7 @@ class CookieManager { ...@@ -139,8 +147,7 @@ class CookieManager {
String _getDomainName(String url) { String _getDomainName(String url) {
Uri uri = Uri.parse(url); Uri uri = Uri.parse(url);
String domain = uri.host; String domain = uri.host;
if (domain == null) if (domain == null) return "";
return "";
return domain.startsWith("www.") ? domain.substring(4) : domain; return domain.startsWith("www.") ? domain.substring(4) : domain;
} }
} }
...@@ -11,7 +11,8 @@ import 'package:flutter/services.dart'; ...@@ -11,7 +11,8 @@ import 'package:flutter/services.dart';
///doesn't offer the same functionalities as iOS `URLCredentialStorage`. ///doesn't offer the same functionalities as iOS `URLCredentialStorage`.
class HttpAuthCredentialDatabase { class HttpAuthCredentialDatabase {
static HttpAuthCredentialDatabase _instance; static HttpAuthCredentialDatabase _instance;
static const MethodChannel _channel = const MethodChannel('com.pichillilorenzo/flutter_inappwebview_credential_database'); static const MethodChannel _channel = const MethodChannel(
'com.pichillilorenzo/flutter_inappwebview_credential_database');
///Gets the database shared instance. ///Gets the database shared instance.
static HttpAuthCredentialDatabase instance() { static HttpAuthCredentialDatabase instance() {
...@@ -24,44 +25,57 @@ class HttpAuthCredentialDatabase { ...@@ -24,44 +25,57 @@ class HttpAuthCredentialDatabase {
return _instance; return _instance;
} }
static Future<dynamic> _handleMethod(MethodCall call) async { static Future<dynamic> _handleMethod(MethodCall call) async {}
}
///Gets a map list of all HTTP auth credentials saved. ///Gets a map list of all HTTP auth credentials saved.
///Each map contains the key `protectionSpace` of type [ProtectionSpace] ///Each map contains the key `protectionSpace` of type [ProtectionSpace]
///and the key `credentials` of type `List<HttpAuthCredential>` that contains all the HTTP auth credentials saved for that `protectionSpace`. ///and the key `credentials` of type `List<HttpAuthCredential>` that contains all the HTTP auth credentials saved for that `protectionSpace`.
Future<List<Map<String, dynamic>>> getAllAuthCredentials() async { Future<List<Map<String, dynamic>>> getAllAuthCredentials() async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
List<dynamic> allCredentials = await _channel.invokeMethod('getAllAuthCredentials', args); List<dynamic> allCredentials =
await _channel.invokeMethod('getAllAuthCredentials', args);
List<Map<String, dynamic>> result = []; List<Map<String, dynamic>> result = [];
for (Map<dynamic, dynamic> map in allCredentials) { for (Map<dynamic, dynamic> map in allCredentials) {
Map<dynamic, dynamic> protectionSpace = map["protectionSpace"]; Map<dynamic, dynamic> protectionSpace = map["protectionSpace"];
List<dynamic> credentials = map["credentials"]; List<dynamic> credentials = map["credentials"];
result.add({ result.add({
"protectionSpace": ProtectionSpace(host: protectionSpace["host"], protocol: protectionSpace["protocol"], realm: protectionSpace["realm"], port: protectionSpace["port"]), "protectionSpace": ProtectionSpace(
"credentials": credentials.map((credential) => HttpAuthCredential(username: credential["username"], password: credential["password"])).toList() host: protectionSpace["host"],
protocol: protectionSpace["protocol"],
realm: protectionSpace["realm"],
port: protectionSpace["port"]),
"credentials": credentials
.map((credential) => HttpAuthCredential(
username: credential["username"],
password: credential["password"]))
.toList()
}); });
} }
return result; return result;
} }
///Gets all the HTTP auth credentials saved for that [protectionSpace]. ///Gets all the HTTP auth credentials saved for that [protectionSpace].
Future<List<HttpAuthCredential>> getHttpAuthCredentials({@required ProtectionSpace protectionSpace}) async { Future<List<HttpAuthCredential>> getHttpAuthCredentials(
{@required ProtectionSpace protectionSpace}) async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host); args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol); args.putIfAbsent("protocol", () => protectionSpace.protocol);
args.putIfAbsent("realm", () => protectionSpace.realm); args.putIfAbsent("realm", () => protectionSpace.realm);
args.putIfAbsent("port", () => protectionSpace.port); args.putIfAbsent("port", () => protectionSpace.port);
List<dynamic> credentialList = await _channel.invokeMethod('getHttpAuthCredentials', args); List<dynamic> credentialList =
await _channel.invokeMethod('getHttpAuthCredentials', args);
List<HttpAuthCredential> credentials = []; List<HttpAuthCredential> credentials = [];
for (Map<dynamic, dynamic> credential in credentialList) { for (Map<dynamic, dynamic> credential in credentialList) {
credentials.add(HttpAuthCredential(username: credential["username"], password: credential["password"])); credentials.add(HttpAuthCredential(
username: credential["username"], password: credential["password"]));
} }
return credentials; return credentials;
} }
///Saves an HTTP auth [credential] for that [protectionSpace]. ///Saves an HTTP auth [credential] for that [protectionSpace].
Future<void> setHttpAuthCredential({@required ProtectionSpace protectionSpace, @required HttpAuthCredential credential}) async { Future<void> setHttpAuthCredential(
{@required ProtectionSpace protectionSpace,
@required HttpAuthCredential credential}) async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host); args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol); args.putIfAbsent("protocol", () => protectionSpace.protocol);
...@@ -73,7 +87,9 @@ class HttpAuthCredentialDatabase { ...@@ -73,7 +87,9 @@ class HttpAuthCredentialDatabase {
} }
///Removes an HTTP auth [credential] for that [protectionSpace]. ///Removes an HTTP auth [credential] for that [protectionSpace].
Future<void> removeHttpAuthCredential({@required ProtectionSpace protectionSpace, @required HttpAuthCredential credential}) async { Future<void> removeHttpAuthCredential(
{@required ProtectionSpace protectionSpace,
@required HttpAuthCredential credential}) async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host); args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol); args.putIfAbsent("protocol", () => protectionSpace.protocol);
...@@ -85,7 +101,8 @@ class HttpAuthCredentialDatabase { ...@@ -85,7 +101,8 @@ class HttpAuthCredentialDatabase {
} }
///Removes all the HTTP auth credentials saved for that [protectionSpace]. ///Removes all the HTTP auth credentials saved for that [protectionSpace].
Future<void> removeHttpAuthCredentials({@required ProtectionSpace protectionSpace}) async { Future<void> removeHttpAuthCredentials(
{@required ProtectionSpace protectionSpace}) async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host); args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol); args.putIfAbsent("protocol", () => protectionSpace.protocol);
......
...@@ -14,23 +14,25 @@ import 'in_app_webview.dart' show InAppWebViewController; ...@@ -14,23 +14,25 @@ import 'in_app_webview.dart' show InAppWebViewController;
/// ///
///This class uses the native WebView of the platform. ///This class uses the native WebView of the platform.
class InAppBrowser { class InAppBrowser {
String uuid; String uuid;
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap = HashMap<String, JavaScriptHandlerCallback>(); Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
HashMap<String, JavaScriptHandlerCallback>();
bool _isOpened = false; bool _isOpened = false;
/// WebView Controller that can be used to access the [InAppWebView] API. /// WebView Controller that can be used to access the [InAppWebView] API.
InAppWebViewController webViewController; InAppWebViewController webViewController;
/// ///
InAppBrowser () { InAppBrowser() {
uuid = uuidGenerator.v4(); uuid = uuidGenerator.v4();
ChannelManager.addListener(uuid, handleMethod); ChannelManager.addListener(uuid, handleMethod);
_isOpened = false; _isOpened = false;
webViewController = new InAppWebViewController.fromInAppBrowser(uuid, ChannelManager.channel, this); webViewController = new InAppWebViewController.fromInAppBrowser(
uuid, ChannelManager.channel, this);
} }
Future<dynamic> handleMethod(MethodCall call) async { Future<dynamic> handleMethod(MethodCall call) async {
switch(call.method) { switch (call.method) {
case "onBrowserCreated": case "onBrowserCreated":
this._isOpened = true; this._isOpened = true;
onBrowserCreated(); onBrowserCreated();
...@@ -51,21 +53,29 @@ class InAppBrowser { ...@@ -51,21 +53,29 @@ class InAppBrowser {
///[headers]: The additional headers to be used in the HTTP request for this URL, specified as a map from name to value. ///[headers]: The additional headers to be used in the HTTP request for this URL, specified as a map from name to value.
/// ///
///[options]: Options for the [InAppBrowser]. ///[options]: Options for the [InAppBrowser].
Future<void> open({String url = "about:blank", Map<String, String> headers = const {}, InAppBrowserClassOptions options}) async { Future<void> open(
{String url = "about:blank",
Map<String, String> headers = const {},
InAppBrowserClassOptions options}) async {
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $url!'); this.throwIsAlreadyOpened(message: 'Cannot open $url!');
Map<String, dynamic> optionsMap = {}; Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) { if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(options
} .inAppWebViewWidgetOptions?.androidInAppWebViewOptions
else if (Platform.isIOS) { ?.toMap() ??
{});
} else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
{});
} }
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
...@@ -113,21 +123,29 @@ class InAppBrowser { ...@@ -113,21 +123,29 @@ class InAppBrowser {
///[headers]: The additional headers to be used in the HTTP request for this URL, specified as a map from name to value. ///[headers]: The additional headers to be used in the HTTP request for this URL, specified as a map from name to value.
/// ///
///[options]: Options for the [InAppBrowser]. ///[options]: Options for the [InAppBrowser].
Future<void> openFile({@required String assetFilePath, Map<String, String> headers = const {}, InAppBrowserClassOptions options}) async { Future<void> openFile(
{@required String assetFilePath,
Map<String, String> headers = const {},
InAppBrowserClassOptions options}) async {
assert(assetFilePath != null && assetFilePath.isNotEmpty); assert(assetFilePath != null && assetFilePath.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!'); this.throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!');
Map<String, dynamic> optionsMap = {}; Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) { if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(options
} .inAppWebViewWidgetOptions?.androidInAppWebViewOptions
else if (Platform.isIOS) { ?.toMap() ??
{});
} else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
{});
} }
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
...@@ -149,20 +167,30 @@ class InAppBrowser { ...@@ -149,20 +167,30 @@ class InAppBrowser {
///The [encoding] parameter specifies the encoding of the data. ///The [encoding] parameter specifies the encoding of the data.
/// ///
///The [options] parameter specifies the options for the [InAppBrowser]. ///The [options] parameter specifies the options for the [InAppBrowser].
Future<void> openData({@required String data, String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", InAppBrowserClassOptions options}) async { Future<void> openData(
{@required String data,
String mimeType = "text/html",
String encoding = "utf8",
String baseUrl = "about:blank",
InAppBrowserClassOptions options}) async {
assert(data != null); assert(data != null);
Map<String, dynamic> optionsMap = {}; Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) { if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(options
} .inAppWebViewWidgetOptions?.androidInAppWebViewOptions
else if (Platform.isIOS) { ?.toMap() ??
{});
} else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
{});
} }
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
...@@ -233,14 +261,19 @@ class InAppBrowser { ...@@ -233,14 +261,19 @@ class InAppBrowser {
Map<String, dynamic> optionsMap = {}; Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) { if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(options
} .inAppWebViewWidgetOptions?.androidInAppWebViewOptions
else if (Platform.isIOS) { ?.toMap() ??
{});
} else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {}); optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {}); optionsMap.addAll(
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
{});
} }
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
...@@ -257,19 +290,27 @@ class InAppBrowser { ...@@ -257,19 +290,27 @@ class InAppBrowser {
args.putIfAbsent('uuid', () => uuid); args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('optionsType', () => "InAppBrowserOptions"); args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
InAppBrowserClassOptions inAppBrowserClassOptions = InAppBrowserClassOptions(); InAppBrowserClassOptions inAppBrowserClassOptions =
Map<dynamic, dynamic> options = await ChannelManager.channel.invokeMethod('getOptions', args); InAppBrowserClassOptions();
Map<dynamic, dynamic> options =
await ChannelManager.channel.invokeMethod('getOptions', args);
if (options != null) { if (options != null) {
options = options.cast<String, dynamic>(); options = options.cast<String, dynamic>();
inAppBrowserClassOptions.inAppBrowserOptions = InAppBrowserOptions.fromMap(options); inAppBrowserClassOptions.inAppBrowserOptions =
inAppBrowserClassOptions.inAppWebViewWidgetOptions.inAppWebViewOptions = InAppWebViewOptions.fromMap(options); InAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions.inAppWebViewOptions =
InAppWebViewOptions.fromMap(options);
if (Platform.isAndroid) { if (Platform.isAndroid) {
inAppBrowserClassOptions.androidInAppBrowserOptions = AndroidInAppBrowserOptions.fromMap(options); inAppBrowserClassOptions.androidInAppBrowserOptions =
inAppBrowserClassOptions.inAppWebViewWidgetOptions.androidInAppWebViewOptions = AndroidInAppWebViewOptions.fromMap(options); AndroidInAppBrowserOptions.fromMap(options);
} inAppBrowserClassOptions
else if (Platform.isIOS) { .inAppWebViewWidgetOptions.androidInAppWebViewOptions =
inAppBrowserClassOptions.iosInAppBrowserOptions = IosInAppBrowserOptions.fromMap(options); AndroidInAppWebViewOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options); } else if (Platform.isIOS) {
inAppBrowserClassOptions.iosInAppBrowserOptions =
IosInAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions
.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options);
} }
} }
...@@ -282,29 +323,19 @@ class InAppBrowser { ...@@ -282,29 +323,19 @@ class InAppBrowser {
} }
///Event fired when the [InAppBrowser] is created. ///Event fired when the [InAppBrowser] is created.
void onBrowserCreated() { void onBrowserCreated() {}
}
///Event fired when the [InAppBrowser] window is closed. ///Event fired when the [InAppBrowser] window is closed.
void onExit() { void onExit() {}
}
///Event fired when the [InAppBrowser] starts to load an [url]. ///Event fired when the [InAppBrowser] starts to load an [url].
void onLoadStart(String url) { void onLoadStart(String url) {}
}
///Event fired when the [InAppBrowser] finishes loading an [url]. ///Event fired when the [InAppBrowser] finishes loading an [url].
void onLoadStop(String url) { void onLoadStop(String url) {}
}
///Event fired when the [InAppBrowser] encounters an error loading an [url]. ///Event fired when the [InAppBrowser] encounters an error loading an [url].
void onLoadError(String url, int code, String message) { void onLoadError(String url, int code, String message) {}
}
///Event fired when the [InAppBrowser] main page receives an HTTP error. ///Event fired when the [InAppBrowser] main page receives an HTTP error.
/// ///
...@@ -315,51 +346,37 @@ class InAppBrowser { ...@@ -315,51 +346,37 @@ class InAppBrowser {
///[description] represents the description of the HTTP error. On iOS, it is always an empty string. ///[description] represents the description of the HTTP error. On iOS, it is always an empty string.
/// ///
///**NOTE**: available on Android 23+. ///**NOTE**: available on Android 23+.
void onLoadHttpError(String url, int statusCode, String description) { void onLoadHttpError(String url, int statusCode, String description) {}
}
///Event fired when the current [progress] (range 0-100) of loading a page is changed. ///Event fired when the current [progress] (range 0-100) of loading a page is changed.
void onProgressChanged(int progress) { void onProgressChanged(int progress) {}
}
///Event fired when the [InAppBrowser] webview receives a [ConsoleMessage]. ///Event fired when the [InAppBrowser] webview receives a [ConsoleMessage].
void onConsoleMessage(ConsoleMessage consoleMessage) { void onConsoleMessage(ConsoleMessage consoleMessage) {}
}
///Give the host application a chance to take control when a URL is about to be loaded in the current WebView. ///Give the host application a chance to take control when a URL is about to be loaded in the current WebView.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`.
void shouldOverrideUrlLoading(String url) { void shouldOverrideUrlLoading(String url) {}
}
///Event fired when the [InAppBrowser] webview loads a resource. ///Event fired when the [InAppBrowser] webview loads a resource.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnLoadResource] and [InAppWebViewOptions.javaScriptEnabled] options to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnLoadResource] and [InAppWebViewOptions.javaScriptEnabled] options to `true`.
void onLoadResource(LoadedResource resource) { void onLoadResource(LoadedResource resource) {}
}
///Event fired when the [InAppBrowser] webview scrolls. ///Event fired when the [InAppBrowser] webview scrolls.
/// ///
///[x] represents the current horizontal scroll origin in pixels. ///[x] represents the current horizontal scroll origin in pixels.
/// ///
///[y] represents the current vertical scroll origin in pixels. ///[y] represents the current vertical scroll origin in pixels.
void onScrollChanged(int x, int y) { void onScrollChanged(int x, int y) {}
}
///Event fired when [InAppBrowser] recognizes and starts a downloadable file. ///Event fired when [InAppBrowser] recognizes and starts a downloadable file.
/// ///
///[url] represents the url of the file. ///[url] represents the url of the file.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`.
void onDownloadStart(String url) { void onDownloadStart(String url) {}
}
///Event fired when the [InAppBrowser] webview 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`. ///Event fired when the [InAppBrowser] webview 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`.
/// ///
...@@ -367,18 +384,15 @@ class InAppBrowser { ...@@ -367,18 +384,15 @@ class InAppBrowser {
/// ///
///[url] represents the url of the request. ///[url] represents the url of the request.
// ignore: missing_return // ignore: missing_return
Future<CustomSchemeResponse> onLoadResourceCustomScheme(String scheme, String url) { Future<CustomSchemeResponse> onLoadResourceCustomScheme(
String scheme, String url) {}
}
///Event fired when the [InAppBrowser] webview tries to open a link with `target="_blank"`. ///Event fired when the [InAppBrowser] webview tries to open a link with `target="_blank"`.
/// ///
///[url] represents the url of the link. ///[url] represents the url of the link.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnTargetBlank] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnTargetBlank] option to `true`.
void onTargetBlank(String url) { void onTargetBlank(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. ///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. ///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.
...@@ -388,27 +402,22 @@ class InAppBrowser { ...@@ -388,27 +402,22 @@ class InAppBrowser {
/// ///
///**NOTE**: available only on Android. ///**NOTE**: available only on Android.
// ignore: missing_return // ignore: missing_return
Future<GeolocationPermissionShowPromptResponse> onGeolocationPermissionsShowPrompt (String origin) { Future<GeolocationPermissionShowPromptResponse>
onGeolocationPermissionsShowPrompt(String origin) {}
}
///Event fired when javascript calls the `alert()` method to display an alert dialog. ///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. ///If [JsAlertResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
/// ///
///[message] represents the message to be displayed in the alert dialog. ///[message] represents the message to be displayed in the alert dialog.
// ignore: missing_return // ignore: missing_return
Future<JsAlertResponse> onJsAlert(String message) { Future<JsAlertResponse> onJsAlert(String message) {}
}
///Event fired when javascript calls the `confirm()` method to display a confirm dialog. ///Event fired when javascript calls the `confirm()` method to display a confirm dialog.
///If [JsConfirmResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog. ///If [JsConfirmResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
/// ///
///[message] represents the message to be displayed in the alert dialog. ///[message] represents the message to be displayed in the alert dialog.
// ignore: missing_return // ignore: missing_return
Future<JsConfirmResponse> onJsConfirm(String message) { Future<JsConfirmResponse> onJsConfirm(String message) {}
}
///Event fired when javascript calls the `prompt()` method to display a prompt dialog. ///Event fired when javascript calls the `prompt()` method to display a prompt dialog.
///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog. ///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
...@@ -416,9 +425,7 @@ class InAppBrowser { ...@@ -416,9 +425,7 @@ class InAppBrowser {
///[message] represents the message to be displayed in the alert dialog. ///[message] represents the message to be displayed in the alert dialog.
///[defaultValue] represents the default value displayed in the prompt dialog. ///[defaultValue] represents the default value displayed in the prompt dialog.
// ignore: missing_return // ignore: missing_return
Future<JsPromptResponse> onJsPrompt(String message, String defaultValue) { Future<JsPromptResponse> onJsPrompt(String message, String defaultValue) {}
}
///Event fired when the WebView notifies that a loading URL has been flagged by Safe Browsing. ///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. ///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
...@@ -429,37 +436,33 @@ class InAppBrowser { ...@@ -429,37 +436,33 @@ class InAppBrowser {
/// ///
///**NOTE**: available only on Android. ///**NOTE**: available only on Android.
// ignore: missing_return // ignore: missing_return
Future<SafeBrowsingResponse> onSafeBrowsingHit(String url, SafeBrowsingThreat threatType) { 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. ///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]. ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [HttpAuthChallenge].
// ignore: missing_return // ignore: missing_return
Future<HttpAuthResponse> onReceivedHttpAuthRequest(HttpAuthChallenge challenge) { Future<HttpAuthResponse> onReceivedHttpAuthRequest(
HttpAuthChallenge challenge) {}
}
///Event fired when the WebView need to perform server trust authentication (certificate validation). ///Event fired when the WebView need to perform server trust authentication (certificate validation).
///The host application must return either [ServerTrustAuthResponse] instance with [ServerTrustAuthResponseAction.CANCEL] or [ServerTrustAuthResponseAction.PROCEED]. ///The host application must return either [ServerTrustAuthResponse] instance with [ServerTrustAuthResponseAction.CANCEL] or [ServerTrustAuthResponseAction.PROCEED].
/// ///
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ServerTrustChallenge]. ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ServerTrustChallenge].
// ignore: missing_return // ignore: missing_return
Future<ServerTrustAuthResponse> onReceivedServerTrustAuthRequest(ServerTrustChallenge challenge) { Future<ServerTrustAuthResponse> onReceivedServerTrustAuthRequest(
ServerTrustChallenge challenge) {}
} ///Notify the host application to handle an SSL client certificate request.
///Notify the host application to handle a SSL client certificate request.
///Webview stores the response in memory (for the life of the application) if [ClientCertResponseAction.PROCEED] or [ClientCertResponseAction.CANCEL] ///Webview stores the response in memory (for the life of the application) if [ClientCertResponseAction.PROCEED] or [ClientCertResponseAction.CANCEL]
///is called and does not call [onReceivedClientCertRequest] again for the same host and port pair. ///is called and does not call [onReceivedClientCertRequest] again for the same host and port pair.
///Note that, multiple layers in chromium network stack might be caching the responses. ///Note that, multiple layers in chromium network stack might be caching the responses.
/// ///
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ClientCertChallenge]. ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ClientCertChallenge].
// ignore: missing_return // ignore: missing_return
Future<ClientCertResponse> onReceivedClientCertRequest(ClientCertChallenge challenge) { Future<ClientCertResponse> onReceivedClientCertRequest(
ClientCertChallenge challenge) {}
}
///Event fired as find-on-page operations progress. ///Event fired as find-on-page operations progress.
///The listener may be notified multiple times while the operation is underway, and the numberOfMatches value should not be considered final unless [isDoneCounting] is true. ///The listener may be notified multiple times while the operation is underway, and the numberOfMatches value should not be considered final unless [isDoneCounting] is true.
...@@ -469,9 +472,8 @@ class InAppBrowser { ...@@ -469,9 +472,8 @@ class InAppBrowser {
///[numberOfMatches] represents how many matches have been found. ///[numberOfMatches] represents how many matches have been found.
/// ///
///[isDoneCounting] whether the find operation has actually completed. ///[isDoneCounting] whether the find operation has actually completed.
void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting) { void onFindResultReceived(
int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting) {}
}
///Event fired when an `XMLHttpRequest` is sent to a server. ///Event fired when an `XMLHttpRequest` is sent to a server.
///It gives the host application a chance to take control over the request before sending it. ///It gives the host application a chance to take control over the request before sending it.
...@@ -480,9 +482,7 @@ class InAppBrowser { ...@@ -480,9 +482,7 @@ class InAppBrowser {
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`.
// ignore: missing_return // ignore: missing_return
Future<AjaxRequest> shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) { Future<AjaxRequest> shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) {}
}
///Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes. ///Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes.
///It gives the host application a chance to abort the request. ///It gives the host application a chance to abort the request.
...@@ -491,9 +491,7 @@ class InAppBrowser { ...@@ -491,9 +491,7 @@ class InAppBrowser {
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`.
// ignore: missing_return // ignore: missing_return
Future<AjaxRequestAction> onAjaxReadyStateChange(AjaxRequest ajaxRequest) { Future<AjaxRequestAction> onAjaxReadyStateChange(AjaxRequest ajaxRequest) {}
}
///Event fired as an `XMLHttpRequest` progress. ///Event fired as an `XMLHttpRequest` progress.
///It gives the host application a chance to abort the request. ///It gives the host application a chance to abort the request.
...@@ -502,9 +500,7 @@ class InAppBrowser { ...@@ -502,9 +500,7 @@ class InAppBrowser {
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptAjaxRequest] option to `true`.
// ignore: missing_return // ignore: missing_return
Future<AjaxRequestAction> onAjaxProgress(AjaxRequest ajaxRequest) { Future<AjaxRequestAction> onAjaxProgress(AjaxRequest ajaxRequest) {}
}
///Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API). ///Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API).
///It gives the host application a chance to take control over the request before sending it. ///It gives the host application a chance to take control over the request before sending it.
...@@ -513,9 +509,7 @@ class InAppBrowser { ...@@ -513,9 +509,7 @@ class InAppBrowser {
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptFetchRequest] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldInterceptFetchRequest] option to `true`.
// ignore: missing_return // ignore: missing_return
Future<FetchRequest> shouldInterceptFetchRequest(FetchRequest fetchRequest) { Future<FetchRequest> shouldInterceptFetchRequest(FetchRequest fetchRequest) {}
}
///Event fired when the navigation state of the WebView changes throught the usage of ///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. ///javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions (`pushState()`, `replaceState()`) and `onpopstate` event.
...@@ -523,9 +517,7 @@ class InAppBrowser { ...@@ -523,9 +517,7 @@ class InAppBrowser {
///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). ///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 new url. ///[url] represents the new url.
void onNavigationStateChange(String url) { void onNavigationStateChange(String url) {}
}
///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied. ///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied.
/// ///
...@@ -534,20 +526,23 @@ class InAppBrowser { ...@@ -534,20 +526,23 @@ class InAppBrowser {
///[resources] represents the array of resources the web content wants to access. ///[resources] represents the array of resources the web content wants to access.
/// ///
///**NOTE**: available only on Android 23+. ///**NOTE**: available only on Android 23+.
Future<PermissionRequestResponse> onPermissionRequest(String origin, List<String> resources) { // ignore: missing_return
Future<PermissionRequestResponse> onPermissionRequest(
} String origin, List<String> resources) {}
void throwIsAlreadyOpened({String message = ''}) { void throwIsAlreadyOpened({String message = ''}) {
if (this.isOpened()) { if (this.isOpened()) {
throw Exception(['Error: ${ (message.isEmpty) ? '' : message + ' '}The browser is already opened.']); throw Exception([
'Error: ${(message.isEmpty) ? '' : message + ' '}The browser is already opened.'
]);
} }
} }
void throwIsNotOpened({String message = ''}) { void throwIsNotOpened({String message = ''}) {
if (!this.isOpened()) { if (!this.isOpened()) {
throw Exception(['Error: ${ (message.isEmpty) ? '' : message + ' '}The browser is not opened.']); throw Exception([
'Error: ${(message.isEmpty) ? '' : message + ' '}The browser is not opened.'
]);
} }
} }
} }
...@@ -8,7 +8,6 @@ import 'package:mime/mime.dart'; ...@@ -8,7 +8,6 @@ import 'package:mime/mime.dart';
/// ///
///This class allows you to create a simple server on `http://localhost:[port]/` in order to be able to load your assets file on a server. The default [port] value is `8080`. ///This class allows you to create a simple server on `http://localhost:[port]/` in order to be able to load your assets file on a server. The default [port] value is `8080`.
class InAppLocalhostServer { class InAppLocalhostServer {
HttpServer _server; HttpServer _server;
int _port = 8080; int _port = 8080;
...@@ -28,7 +27,6 @@ class InAppLocalhostServer { ...@@ -28,7 +27,6 @@ class InAppLocalhostServer {
///``` ///```
///The `NSAllowsLocalNetworking` key is available since **iOS 10**. ///The `NSAllowsLocalNetworking` key is available since **iOS 10**.
Future<void> start() async { Future<void> start() async {
if (this._server != null) { if (this._server != null) {
throw Exception('Server already started on http://localhost:$_port'); throw Exception('Server already started on http://localhost:$_port');
} }
...@@ -48,8 +46,7 @@ class InAppLocalhostServer { ...@@ -48,8 +46,7 @@ class InAppLocalhostServer {
path += (path.endsWith('/')) ? 'index.html' : ''; path += (path.endsWith('/')) ? 'index.html' : '';
try { try {
body = (await rootBundle.load(path)) body = (await rootBundle.load(path)).buffer.asUint8List();
.buffer.asUint8List();
} catch (e) { } catch (e) {
print(e.toString()); print(e.toString());
request.response.close(); request.response.close();
...@@ -57,14 +54,17 @@ class InAppLocalhostServer { ...@@ -57,14 +54,17 @@ class InAppLocalhostServer {
} }
var contentType = ['text', 'html']; var contentType = ['text', 'html'];
if (!request.requestedUri.path.endsWith('/') && request.requestedUri.pathSegments.isNotEmpty) { if (!request.requestedUri.path.endsWith('/') &&
var mimeType = lookupMimeType(request.requestedUri.path, headerBytes: body); request.requestedUri.pathSegments.isNotEmpty) {
var mimeType =
lookupMimeType(request.requestedUri.path, headerBytes: body);
if (mimeType != null) { if (mimeType != null) {
contentType = mimeType.split('/'); contentType = mimeType.split('/');
} }
} }
request.response.headers.contentType = new ContentType(contentType[0], contentType[1], charset: 'utf-8'); request.response.headers.contentType =
new ContentType(contentType[0], contentType[1], charset: 'utf-8');
request.response.add(body); request.response.add(body);
request.response.close(); request.response.close();
}); });
...@@ -84,5 +84,4 @@ class InAppLocalhostServer { ...@@ -84,5 +84,4 @@ class InAppLocalhostServer {
this._server = null; this._server = null;
} }
} }
} }
...@@ -16,24 +16,31 @@ import 'types.dart'; ...@@ -16,24 +16,31 @@ import 'types.dart';
import 'in_app_browser.dart'; import 'in_app_browser.dart';
import 'webview_options.dart'; import 'webview_options.dart';
const javaScriptHandlerForbiddenNames = ["onLoadResource", "shouldInterceptAjaxRequest", "onAjaxReadyStateChange", "onAjaxProgress", "shouldInterceptFetchRequest"]; const javaScriptHandlerForbiddenNames = [
"onLoadResource",
"shouldInterceptAjaxRequest",
"onAjaxReadyStateChange",
"onAjaxProgress",
"shouldInterceptFetchRequest"
];
///InAppWebView Widget class. ///InAppWebView Widget class.
/// ///
///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree. ///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree.
class InAppWebView extends StatefulWidget { class InAppWebView extends StatefulWidget {
///Event fired when the [InAppWebView] is created. ///Event fired when the [InAppWebView] is created.
final void Function(InAppWebViewController controller) onWebViewCreated; final void Function(InAppWebViewController controller) onWebViewCreated;
///Event fired when the [InAppWebView] starts to load an [url]. ///Event fired when the [InAppWebView] starts to load an [url].
final void Function(InAppWebViewController controller, String url) onLoadStart; final void Function(InAppWebViewController controller, String url)
onLoadStart;
///Event fired when the [InAppWebView] finishes loading an [url]. ///Event fired when the [InAppWebView] finishes loading an [url].
final void Function(InAppWebViewController controller, String url) onLoadStop; final void Function(InAppWebViewController controller, String url) onLoadStop;
///Event fired when the [InAppWebView] encounters an error loading an [url]. ///Event fired when the [InAppWebView] encounters an error loading an [url].
final void Function(InAppWebViewController controller, String url, int code, String message) onLoadError; final void Function(InAppWebViewController controller, String url, int code,
String message) onLoadError;
///Event fired when the [InAppWebView] main page receives an HTTP error. ///Event fired when the [InAppWebView] main page receives an HTTP error.
/// ///
...@@ -44,51 +51,63 @@ class InAppWebView extends StatefulWidget { ...@@ -44,51 +51,63 @@ class InAppWebView extends StatefulWidget {
///[description] represents the description of the HTTP error. On iOS, it is always an empty string. ///[description] represents the description of the HTTP error. On iOS, it is always an empty string.
/// ///
///**NOTE**: available on Android 23+. ///**NOTE**: available on Android 23+.
final void Function(InAppWebViewController controller, String url, int statusCode, String description) onLoadHttpError; final void Function(InAppWebViewController controller, String url,
int statusCode, String description) onLoadHttpError;
///Event fired when the current [progress] of loading a page is changed. ///Event fired when the current [progress] of loading a page is changed.
final void Function(InAppWebViewController controller, int progress) onProgressChanged; final void Function(InAppWebViewController controller, int progress)
onProgressChanged;
///Event fired when the [InAppWebView] receives a [ConsoleMessage]. ///Event fired when the [InAppWebView] receives a [ConsoleMessage].
final void Function(InAppWebViewController controller, ConsoleMessage consoleMessage) onConsoleMessage; final void Function(
InAppWebViewController controller, ConsoleMessage consoleMessage)
onConsoleMessage;
///Give the host application a chance to take control when a URL is about to be loaded in the current WebView. ///Give the host application a chance to take control when a URL is about to be loaded in the current WebView.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useShouldOverrideUrlLoading] option to `true`.
final void Function(InAppWebViewController controller, String url) shouldOverrideUrlLoading; final void Function(InAppWebViewController controller, String url)
shouldOverrideUrlLoading;
///Event fired when the [InAppWebView] loads a resource. ///Event fired when the [InAppWebView] loads a resource.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnLoadResource] and [InAppWebViewOptions.javaScriptEnabled] options to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnLoadResource] and [InAppWebViewOptions.javaScriptEnabled] options to `true`.
final void Function(InAppWebViewController controller, LoadedResource resource) onLoadResource; final void Function(
InAppWebViewController controller, LoadedResource resource)
onLoadResource;
///Event fired when the [InAppWebView] scrolls. ///Event fired when the [InAppWebView] scrolls.
/// ///
///[x] represents the current horizontal scroll origin in pixels. ///[x] represents the current horizontal scroll origin in pixels.
/// ///
///[y] represents the current vertical scroll origin in pixels. ///[y] represents the current vertical scroll origin in pixels.
final void Function(InAppWebViewController controller, int x, int y) onScrollChanged; final void Function(InAppWebViewController controller, int x, int y)
onScrollChanged;
///Event fired when [InAppWebView] recognizes and starts a downloadable file. ///Event fired when [InAppWebView] recognizes and starts a downloadable file.
/// ///
///[url] represents the url of the file. ///[url] represents the url of the file.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`.
final void Function(InAppWebViewController controller, String url) onDownloadStart; final void Function(InAppWebViewController controller, String url)
onDownloadStart;
///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`. ///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`.
/// ///
///[scheme] represents the scheme of the url. ///[scheme] represents the scheme of the url.
/// ///
///[url] represents the url of the request. ///[url] represents the url of the request.
final Future<CustomSchemeResponse> Function(InAppWebViewController controller, String scheme, String url) onLoadResourceCustomScheme; final Future<CustomSchemeResponse> Function(
InAppWebViewController controller, String scheme, String url)
onLoadResourceCustomScheme;
///Event fired when the [InAppWebView] tries to open a link with `target="_blank"`. ///Event fired when the [InAppWebView] tries to open a link with `target="_blank"`.
/// ///
///[url] represents the url of the link. ///[url] represents the url of the link.
/// ///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnTargetBlank] option to `true`. ///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnTargetBlank] option to `true`.
final void Function(InAppWebViewController controller, String url) onTargetBlank; final void Function(InAppWebViewController controller, String url)
onTargetBlank;
///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. ///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. ///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.
...@@ -97,19 +116,23 @@ class InAppWebView extends StatefulWidget { ...@@ -97,19 +116,23 @@ class InAppWebView extends StatefulWidget {
///[origin] represents the origin of the web content attempting to use the Geolocation API. ///[origin] represents the origin of the web content attempting to use the Geolocation API.
/// ///
///**NOTE**: available only on Android. ///**NOTE**: available only on Android.
final Future<GeolocationPermissionShowPromptResponse> Function(InAppWebViewController controller, String origin) onGeolocationPermissionsShowPrompt; final Future<GeolocationPermissionShowPromptResponse> Function(
InAppWebViewController controller, String origin)
onGeolocationPermissionsShowPrompt;
///Event fired when javascript calls the `alert()` method to display an alert dialog. ///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. ///If [JsAlertResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
/// ///
///[message] represents the message to be displayed in the alert dialog. ///[message] represents the message to be displayed in the alert dialog.
final Future<JsAlertResponse> Function(InAppWebViewController controller, String message) onJsAlert; final Future<JsAlertResponse> Function(
InAppWebViewController controller, String message) onJsAlert;
///Event fired when javascript calls the `confirm()` method to display a confirm dialog. ///Event fired when javascript calls the `confirm()` method to display a confirm dialog.
///If [JsConfirmResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog. ///If [JsConfirmResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
/// ///
///[message] represents the message to be displayed in the alert dialog. ///[message] represents the message to be displayed in the alert dialog.
final Future<JsConfirmResponse> Function(InAppWebViewController controller, String message) onJsConfirm; final Future<JsConfirmResponse> Function(
InAppWebViewController controller, String message) onJsConfirm;
///Event fired when javascript calls the `prompt()` method to display a prompt dialog. ///Event fired when javascript calls the `prompt()` method to display a prompt dialog.
///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog. ///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
...@@ -117,7 +140,8 @@ class InAppWebView extends StatefulWidget { ...@@ -117,7 +140,8 @@ class InAppWebView extends StatefulWidget {
///[message] represents the message to be displayed in the alert dialog. ///[message] represents the message to be displayed in the alert dialog.
/// ///
///[defaultValue] represents the default value displayed in the prompt dialog. ///[defaultValue] represents the default value displayed in the prompt dialog.
final Future<JsPromptResponse> Function(InAppWebViewController controller, String message, String defaultValue) onJsPrompt; 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. ///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. ///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
...@@ -127,26 +151,33 @@ class InAppWebView extends StatefulWidget { ...@@ -127,26 +151,33 @@ class InAppWebView extends StatefulWidget {
///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat]. ///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat].
/// ///
///**NOTE**: available only on Android. ///**NOTE**: available only on Android.
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller, String url, SafeBrowsingThreat threatType) onSafeBrowsingHit; 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. ///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]. ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [HttpAuthChallenge].
final Future<HttpAuthResponse> Function(InAppWebViewController controller, HttpAuthChallenge challenge) onReceivedHttpAuthRequest; final Future<HttpAuthResponse> Function(
InAppWebViewController controller, HttpAuthChallenge challenge)
onReceivedHttpAuthRequest;
///Event fired when the WebView need to perform server trust authentication (certificate validation). ///Event fired when the WebView need to perform server trust authentication (certificate validation).
///The host application must return either [ServerTrustAuthResponse] instance with [ServerTrustAuthResponseAction.CANCEL] or [ServerTrustAuthResponseAction.PROCEED]. ///The host application must return either [ServerTrustAuthResponse] instance with [ServerTrustAuthResponseAction.CANCEL] or [ServerTrustAuthResponseAction.PROCEED].
/// ///
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ServerTrustChallenge]. ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ServerTrustChallenge].
final Future<ServerTrustAuthResponse> Function(InAppWebViewController controller, ServerTrustChallenge challenge) onReceivedServerTrustAuthRequest; final Future<ServerTrustAuthResponse> Function(
InAppWebViewController controller, ServerTrustChallenge challenge)
onReceivedServerTrustAuthRequest;
///Notify the host application to handle a SSL client certificate request. ///Notify the host application to handle an SSL client certificate request.
///Webview stores the response in memory (for the life of the application) if [ClientCertResponseAction.PROCEED] or [ClientCertResponseAction.CANCEL] ///Webview stores the response in memory (for the life of the application) if [ClientCertResponseAction.PROCEED] or [ClientCertResponseAction.CANCEL]
///is called and does not call [onReceivedClientCertRequest] again for the same host and port pair. ///is called and does not call [onReceivedClientCertRequest] again for the same host and port pair.
///Note that, multiple layers in chromium network stack might be caching the responses. ///Note that, multiple layers in chromium network stack might be caching the responses.
/// ///
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ClientCertChallenge]. ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ClientCertChallenge].
final Future<ClientCertResponse> Function(InAppWebViewController controller, ClientCertChallenge challenge) onReceivedClientCertRequest; final Future<ClientCertResponse> Function(
InAppWebViewController controller, ClientCertChallenge challenge)
onReceivedClientCertRequest;
///Event fired as find-on-page operations progress. ///Event fired as find-on-page operations progress.
///The listener may be notified multiple times while the operation is underway, and the numberOfMatches value should not be considered final unless [isDoneCounting] is true. ///The listener may be notified multiple times while the operation is underway, and the numberOfMatches value should not be considered final unless [isDoneCounting] is true.
...@@ -156,7 +187,8 @@ class InAppWebView extends StatefulWidget { ...@@ -156,7 +187,8 @@ class InAppWebView extends StatefulWidget {
///[numberOfMatches] represents how many matches have been found. ///[numberOfMatches] represents how many matches have been found.
/// ///
///[isDoneCounting] whether the find operation has actually completed. ///[isDoneCounting] whether the find operation has actually completed.
final void Function(InAppWebViewController controller, int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting) onFindResultReceived; final void Function(InAppWebViewController controller, int activeMatchOrdinal,
int numberOfMatches, bool isDoneCounting) onFindResultReceived;
///Event fired when an `XMLHttpRequest` is sent to a server. ///Event fired when an `XMLHttpRequest` is sent to a server.
///It gives the host application a chance to take control over the request before sending it. ///It gives the host application a chance to take control over the request before sending it.
...@@ -168,7 +200,9 @@ class InAppWebView extends StatefulWidget { ...@@ -168,7 +200,9 @@ class InAppWebView extends StatefulWidget {
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code ///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms). ///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure. ///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure.
final Future<AjaxRequest> Function(InAppWebViewController controller, AjaxRequest ajaxRequest) shouldInterceptAjaxRequest; final Future<AjaxRequest> Function(
InAppWebViewController controller, AjaxRequest ajaxRequest)
shouldInterceptAjaxRequest;
///Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes. ///Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes.
///It gives the host application a chance to abort the request. ///It gives the host application a chance to abort the request.
...@@ -180,7 +214,9 @@ class InAppWebView extends StatefulWidget { ...@@ -180,7 +214,9 @@ class InAppWebView extends StatefulWidget {
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code ///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms). ///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure. ///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure.
final Future<AjaxRequestAction> Function(InAppWebViewController controller, AjaxRequest ajaxRequest) onAjaxReadyStateChange; final Future<AjaxRequestAction> Function(
InAppWebViewController controller, AjaxRequest ajaxRequest)
onAjaxReadyStateChange;
///Event fired as an `XMLHttpRequest` progress. ///Event fired as an `XMLHttpRequest` progress.
///It gives the host application a chance to abort the request. ///It gives the host application a chance to abort the request.
...@@ -192,7 +228,9 @@ class InAppWebView extends StatefulWidget { ...@@ -192,7 +228,9 @@ class InAppWebView extends StatefulWidget {
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code ///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms). ///used to intercept ajax requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure. ///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the ajax requests will be intercept for sure.
final Future<AjaxRequestAction> Function(InAppWebViewController controller, AjaxRequest ajaxRequest) onAjaxProgress; final Future<AjaxRequestAction> Function(
InAppWebViewController controller, AjaxRequest ajaxRequest)
onAjaxProgress;
///Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API). ///Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API).
///It gives the host application a chance to take control over the request before sending it. ///It gives the host application a chance to take control over the request before sending it.
...@@ -204,7 +242,9 @@ class InAppWebView extends StatefulWidget { ...@@ -204,7 +242,9 @@ class InAppWebView extends StatefulWidget {
///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code ///can inject javascript code right after the document element is created but before any other content is loaded, in Android the javascript code
///used to intercept fetch requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms). ///used to intercept fetch requests is loaded as soon as possible so it won't be instantaneous as iOS but just after some milliseconds (< ~100ms).
///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the fetch requests will be intercept for sure. ///Inside the `window.addEventListener("flutterInAppWebViewPlatformReady")` event, the fetch requests will be intercept for sure.
final Future<FetchRequest> Function(InAppWebViewController controller, FetchRequest fetchRequest) shouldInterceptFetchRequest; final Future<FetchRequest> Function(
InAppWebViewController controller, FetchRequest fetchRequest)
shouldInterceptFetchRequest;
///Event fired when the navigation state of the [InAppWebView] changes throught the usage of ///Event fired when the navigation state of the [InAppWebView] 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. ///javascript **[History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)** functions (`pushState()`, `replaceState()`) and `onpopstate` event.
...@@ -212,7 +252,8 @@ class InAppWebView extends StatefulWidget { ...@@ -212,7 +252,8 @@ class InAppWebView extends StatefulWidget {
///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). ///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 new url. ///[url] represents the new url.
final void Function(InAppWebViewController controller, String url) onNavigationStateChange; final void Function(InAppWebViewController controller, String url)
onNavigationStateChange;
///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied. ///Event fired when the WebView is requesting permission to access the specified resources and the permission currently isn't granted or denied.
/// ///
...@@ -221,18 +262,26 @@ class InAppWebView extends StatefulWidget { ...@@ -221,18 +262,26 @@ class InAppWebView extends StatefulWidget {
///[resources] represents the array of resources the web content wants to access. ///[resources] represents the array of resources the web content wants to access.
/// ///
///**NOTE**: available only on Android 23+. ///**NOTE**: available only on Android 23+.
final Future<PermissionRequestResponse> Function(InAppWebViewController controller, String origin, List<String> resources) onPermissionRequest; final Future<PermissionRequestResponse> Function(
InAppWebViewController controller,
String origin,
List<String> resources) onPermissionRequest;
///Initial url that will be loaded. ///Initial url that will be loaded.
final String initialUrl; final String initialUrl;
///Initial asset file that will be loaded. See [InAppWebView.loadFile()] for explanation. ///Initial asset file that will be loaded. See [InAppWebView.loadFile()] for explanation.
final String initialFile; final String initialFile;
///Initial [InAppWebViewInitialData] that will be loaded. ///Initial [InAppWebViewInitialData] that will be loaded.
final InAppWebViewInitialData initialData; final InAppWebViewInitialData initialData;
///Initial headers that will be used. ///Initial headers that will be used.
final Map<String, String> initialHeaders; final Map<String, String> initialHeaders;
///Initial options that will be used. ///Initial options that will be used.
final InAppWebViewWidgetOptions initialOptions; final InAppWebViewWidgetOptions initialOptions;
/// `gestureRecognizers` specifies which gestures should be consumed by the web view. /// `gestureRecognizers` specifies which gestures should be consumed by the web view.
/// It is possible for other gesture recognizers to be competing with the web view on pointer /// It is possible for other gesture recognizers to be competing with the web view on pointer
/// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle /// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle
...@@ -248,7 +297,7 @@ class InAppWebView extends StatefulWidget { ...@@ -248,7 +297,7 @@ class InAppWebView extends StatefulWidget {
this.initialFile, this.initialFile,
this.initialData, this.initialData,
this.initialHeaders = const {}, this.initialHeaders = const {},
this.initialOptions, @required this.initialOptions,
this.onWebViewCreated, this.onWebViewCreated,
this.onLoadStart, this.onLoadStart,
this.onLoadStop, this.onLoadStop,
...@@ -285,17 +334,19 @@ class InAppWebView extends StatefulWidget { ...@@ -285,17 +334,19 @@ class InAppWebView extends StatefulWidget {
} }
class _InAppWebViewState extends State<InAppWebView> { class _InAppWebViewState extends State<InAppWebView> {
InAppWebViewController _controller; InAppWebViewController _controller;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Map<String, dynamic> initialOptions = {}; Map<String, dynamic> initialOptions = {};
initialOptions.addAll(widget.initialOptions.inAppWebViewOptions?.toMap() ?? {}); initialOptions
.addAll(widget.initialOptions.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) if (Platform.isAndroid)
initialOptions.addAll(widget.initialOptions.androidInAppWebViewOptions?.toMap() ?? {}); initialOptions.addAll(
widget.initialOptions.androidInAppWebViewOptions?.toMap() ?? {});
else if (Platform.isIOS) else if (Platform.isIOS)
initialOptions.addAll(widget.initialOptions.iosInAppWebViewOptions?.toMap() ?? {}); initialOptions
.addAll(widget.initialOptions.iosInAppWebViewOptions?.toMap() ?? {});
if (defaultTargetPlatform == TargetPlatform.android) { if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView( return AndroidView(
...@@ -356,7 +407,7 @@ class _InAppWebViewState extends State<InAppWebView> { ...@@ -356,7 +407,7 @@ class _InAppWebViewState extends State<InAppWebView> {
} }
@override @override
void dispose(){ void dispose() {
super.dispose(); super.dispose();
} }
...@@ -373,10 +424,10 @@ class _InAppWebViewState extends State<InAppWebView> { ...@@ -373,10 +424,10 @@ class _InAppWebViewState extends State<InAppWebView> {
/// An [InAppWebViewController] instance can be obtained by setting the [InAppWebView.onWebViewCreated] /// An [InAppWebViewController] instance can be obtained by setting the [InAppWebView.onWebViewCreated]
/// callback for an [InAppWebView] widget. /// callback for an [InAppWebView] widget.
class InAppWebViewController { class InAppWebViewController {
InAppWebView _widget; InAppWebView _widget;
MethodChannel _channel; MethodChannel _channel;
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap = HashMap<String, JavaScriptHandlerCallback>(); Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
HashMap<String, JavaScriptHandlerCallback>();
// ignore: unused_field // ignore: unused_field
bool _isOpened = false; bool _isOpened = false;
// ignore: unused_field // ignore: unused_field
...@@ -384,35 +435,34 @@ class InAppWebViewController { ...@@ -384,35 +435,34 @@ class InAppWebViewController {
String _inAppBrowserUuid; String _inAppBrowserUuid;
InAppBrowser _inAppBrowser; InAppBrowser _inAppBrowser;
InAppWebViewController(int id, InAppWebView widget) { InAppWebViewController(int id, InAppWebView widget) {
this._id = id; this._id = id;
this._channel = MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id'); this._channel =
MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id');
this._channel.setMethodCallHandler(handleMethod); this._channel.setMethodCallHandler(handleMethod);
this._widget = widget; this._widget = widget;
} }
InAppWebViewController.fromInAppBrowser(String uuid, MethodChannel channel, InAppBrowser inAppBrowser) { InAppWebViewController.fromInAppBrowser(
String uuid, MethodChannel channel, InAppBrowser inAppBrowser) {
this._inAppBrowserUuid = uuid; this._inAppBrowserUuid = uuid;
this._channel = channel; this._channel = channel;
this._inAppBrowser = inAppBrowser; this._inAppBrowser = inAppBrowser;
} }
Future<dynamic> handleMethod(MethodCall call) async { Future<dynamic> handleMethod(MethodCall call) async {
switch(call.method) { switch (call.method) {
case "onLoadStart": case "onLoadStart":
String url = call.arguments["url"]; String url = call.arguments["url"];
if (_widget != null && _widget.onLoadStart != null) if (_widget != null && _widget.onLoadStart != null)
_widget.onLoadStart(this, url); _widget.onLoadStart(this, url);
else if (_inAppBrowser != null) else if (_inAppBrowser != null) _inAppBrowser.onLoadStart(url);
_inAppBrowser.onLoadStart(url);
break; break;
case "onLoadStop": case "onLoadStop":
String url = call.arguments["url"]; String url = call.arguments["url"];
if (_widget != null && _widget.onLoadStop != null) if (_widget != null && _widget.onLoadStop != null)
_widget.onLoadStop(this, url); _widget.onLoadStop(this, url);
else if (_inAppBrowser != null) else if (_inAppBrowser != null) _inAppBrowser.onLoadStop(url);
_inAppBrowser.onLoadStop(url);
break; break;
case "onLoadError": case "onLoadError":
String url = call.arguments["url"]; String url = call.arguments["url"];
...@@ -448,8 +498,10 @@ class InAppWebViewController { ...@@ -448,8 +498,10 @@ class InAppWebViewController {
break; break;
case "onConsoleMessage": case "onConsoleMessage":
String message = call.arguments["message"]; String message = call.arguments["message"];
ConsoleMessageLevel messageLevel = ConsoleMessageLevel.fromValue(call.arguments["messageLevel"]); ConsoleMessageLevel messageLevel =
ConsoleMessage consoleMessage = ConsoleMessage(message: message, messageLevel: messageLevel); ConsoleMessageLevel.fromValue(call.arguments["messageLevel"]);
ConsoleMessage consoleMessage =
ConsoleMessage(message: message, messageLevel: messageLevel);
if (_widget != null && _widget.onConsoleMessage != null) if (_widget != null && _widget.onConsoleMessage != null)
_widget.onConsoleMessage(this, consoleMessage); _widget.onConsoleMessage(this, consoleMessage);
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
...@@ -460,31 +512,31 @@ class InAppWebViewController { ...@@ -460,31 +512,31 @@ class InAppWebViewController {
int y = call.arguments["y"]; int y = call.arguments["y"];
if (_widget != null && _widget.onScrollChanged != null) if (_widget != null && _widget.onScrollChanged != null)
_widget.onScrollChanged(this, x, y); _widget.onScrollChanged(this, x, y);
else if (_inAppBrowser != null) else if (_inAppBrowser != null) _inAppBrowser.onScrollChanged(x, y);
_inAppBrowser.onScrollChanged(x, y);
break; break;
case "onDownloadStart": case "onDownloadStart":
String url = call.arguments["url"]; String url = call.arguments["url"];
if (_widget != null && _widget.onDownloadStart != null) if (_widget != null && _widget.onDownloadStart != null)
_widget.onDownloadStart(this, url); _widget.onDownloadStart(this, url);
else if (_inAppBrowser != null) else if (_inAppBrowser != null) _inAppBrowser.onDownloadStart(url);
_inAppBrowser.onDownloadStart(url);
break; break;
case "onLoadResourceCustomScheme": case "onLoadResourceCustomScheme":
String scheme = call.arguments["scheme"]; String scheme = call.arguments["scheme"];
String url = call.arguments["url"]; String url = call.arguments["url"];
if (_widget != null && _widget.onLoadResourceCustomScheme != null) { if (_widget != null && _widget.onLoadResourceCustomScheme != null) {
try { try {
var response = await _widget.onLoadResourceCustomScheme(this, scheme, url); var response =
return (response != null) ? response.toJson(): null; await _widget.onLoadResourceCustomScheme(this, scheme, url);
return (response != null) ? response.toJson() : null;
} catch (error) { } catch (error) {
print(error); print(error);
return null; return null;
} }
} else if (_inAppBrowser != null) { } else if (_inAppBrowser != null) {
try { try {
var response = await _inAppBrowser.onLoadResourceCustomScheme(scheme, url); var response =
return (response != null) ? response.toJson(): null; await _inAppBrowser.onLoadResourceCustomScheme(scheme, url);
return (response != null) ? response.toJson() : null;
} catch (error) { } catch (error) {
print(error); print(error);
return null; return null;
...@@ -495,15 +547,19 @@ class InAppWebViewController { ...@@ -495,15 +547,19 @@ class InAppWebViewController {
String url = call.arguments["url"]; String url = call.arguments["url"];
if (_widget != null && _widget.onTargetBlank != null) if (_widget != null && _widget.onTargetBlank != null)
_widget.onTargetBlank(this, url); _widget.onTargetBlank(this, url);
else if (_inAppBrowser != null) else if (_inAppBrowser != null) _inAppBrowser.onTargetBlank(url);
_inAppBrowser.onTargetBlank(url);
break; break;
case "onGeolocationPermissionsShowPrompt": case "onGeolocationPermissionsShowPrompt":
String origin = call.arguments["origin"]; String origin = call.arguments["origin"];
if (_widget != null && _widget.onGeolocationPermissionsShowPrompt != null) if (_widget != null &&
return (await _widget.onGeolocationPermissionsShowPrompt(this, origin))?.toMap(); _widget.onGeolocationPermissionsShowPrompt != null)
return (await _widget.onGeolocationPermissionsShowPrompt(
this, origin))
?.toMap();
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return (await _inAppBrowser.onGeolocationPermissionsShowPrompt(origin))?.toMap(); return (await _inAppBrowser
.onGeolocationPermissionsShowPrompt(origin))
?.toMap();
break; break;
case "onJsAlert": case "onJsAlert":
String message = call.arguments["message"]; String message = call.arguments["message"];
...@@ -523,17 +579,22 @@ class InAppWebViewController { ...@@ -523,17 +579,22 @@ class InAppWebViewController {
String message = call.arguments["message"]; String message = call.arguments["message"];
String defaultValue = call.arguments["defaultValue"]; String defaultValue = call.arguments["defaultValue"];
if (_widget != null && _widget.onJsPrompt != null) if (_widget != null && _widget.onJsPrompt != null)
return (await _widget.onJsPrompt(this, message, defaultValue))?.toMap(); return (await _widget.onJsPrompt(this, message, defaultValue))
?.toMap();
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return (await _inAppBrowser.onJsPrompt(message, defaultValue))?.toMap(); return (await _inAppBrowser.onJsPrompt(message, defaultValue))
?.toMap();
break; break;
case "onSafeBrowsingHit": case "onSafeBrowsingHit":
String url = call.arguments["url"]; String url = call.arguments["url"];
SafeBrowsingThreat threatType = SafeBrowsingThreat.fromValue(call.arguments["threatType"]); SafeBrowsingThreat threatType =
SafeBrowsingThreat.fromValue(call.arguments["threatType"]);
if (_widget != null && _widget.onSafeBrowsingHit != null) if (_widget != null && _widget.onSafeBrowsingHit != null)
return (await _widget.onSafeBrowsingHit(this, url, threatType))?.toMap(); return (await _widget.onSafeBrowsingHit(this, url, threatType))
?.toMap();
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return (await _inAppBrowser.onSafeBrowsingHit(url, threatType))?.toMap(); return (await _inAppBrowser.onSafeBrowsingHit(url, threatType))
?.toMap();
break; break;
case "onReceivedHttpAuthRequest": case "onReceivedHttpAuthRequest":
String host = call.arguments["host"]; String host = call.arguments["host"];
...@@ -541,12 +602,17 @@ class InAppWebViewController { ...@@ -541,12 +602,17 @@ class InAppWebViewController {
String realm = call.arguments["realm"]; String realm = call.arguments["realm"];
int port = call.arguments["port"]; int port = call.arguments["port"];
int previousFailureCount = call.arguments["previousFailureCount"]; int previousFailureCount = call.arguments["previousFailureCount"];
var protectionSpace = ProtectionSpace(host: host, protocol: protocol, realm: realm, port: port); var protectionSpace = ProtectionSpace(
var challenge = HttpAuthChallenge(previousFailureCount: previousFailureCount, protectionSpace: protectionSpace); host: host, protocol: protocol, realm: realm, port: port);
var challenge = HttpAuthChallenge(
previousFailureCount: previousFailureCount,
protectionSpace: protectionSpace);
if (_widget != null && _widget.onReceivedHttpAuthRequest != null) if (_widget != null && _widget.onReceivedHttpAuthRequest != null)
return (await _widget.onReceivedHttpAuthRequest(this, challenge))?.toMap(); return (await _widget.onReceivedHttpAuthRequest(this, challenge))
?.toMap();
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return (await _inAppBrowser.onReceivedHttpAuthRequest(challenge))?.toMap(); return (await _inAppBrowser.onReceivedHttpAuthRequest(challenge))
?.toMap();
break; break;
case "onReceivedServerTrustAuthRequest": case "onReceivedServerTrustAuthRequest":
String host = call.arguments["host"]; String host = call.arguments["host"];
...@@ -556,33 +622,47 @@ class InAppWebViewController { ...@@ -556,33 +622,47 @@ class InAppWebViewController {
int error = call.arguments["error"]; int error = call.arguments["error"];
String message = call.arguments["message"]; String message = call.arguments["message"];
Uint8List serverCertificate = call.arguments["serverCertificate"]; Uint8List serverCertificate = call.arguments["serverCertificate"];
var protectionSpace = ProtectionSpace(host: host, protocol: protocol, realm: realm, port: port); var protectionSpace = ProtectionSpace(
var challenge = ServerTrustChallenge(protectionSpace: protectionSpace, error: error, message: message, serverCertificate: serverCertificate); host: host, protocol: protocol, realm: realm, port: port);
var challenge = ServerTrustChallenge(
protectionSpace: protectionSpace,
error: error,
message: message,
serverCertificate: serverCertificate);
if (_widget != null && _widget.onReceivedServerTrustAuthRequest != null) if (_widget != null && _widget.onReceivedServerTrustAuthRequest != null)
return (await _widget.onReceivedServerTrustAuthRequest(this, challenge))?.toMap(); return (await _widget.onReceivedServerTrustAuthRequest(
this, challenge))
?.toMap();
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return (await _inAppBrowser.onReceivedServerTrustAuthRequest(challenge))?.toMap(); return (await _inAppBrowser
.onReceivedServerTrustAuthRequest(challenge))
?.toMap();
break; break;
case "onReceivedClientCertRequest": case "onReceivedClientCertRequest":
String host = call.arguments["host"]; String host = call.arguments["host"];
String protocol = call.arguments["protocol"]; String protocol = call.arguments["protocol"];
String realm = call.arguments["realm"]; String realm = call.arguments["realm"];
int port = call.arguments["port"]; int port = call.arguments["port"];
var protectionSpace = ProtectionSpace(host: host, protocol: protocol, realm: realm, port: port); var protectionSpace = ProtectionSpace(
host: host, protocol: protocol, realm: realm, port: port);
var challenge = ClientCertChallenge(protectionSpace: protectionSpace); var challenge = ClientCertChallenge(protectionSpace: protectionSpace);
if (_widget != null && _widget.onReceivedClientCertRequest != null) if (_widget != null && _widget.onReceivedClientCertRequest != null)
return (await _widget.onReceivedClientCertRequest(this, challenge))?.toMap(); return (await _widget.onReceivedClientCertRequest(this, challenge))
?.toMap();
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return (await _inAppBrowser.onReceivedClientCertRequest(challenge))?.toMap(); return (await _inAppBrowser.onReceivedClientCertRequest(challenge))
?.toMap();
break; break;
case "onFindResultReceived": case "onFindResultReceived":
int activeMatchOrdinal = call.arguments["activeMatchOrdinal"]; int activeMatchOrdinal = call.arguments["activeMatchOrdinal"];
int numberOfMatches = call.arguments["numberOfMatches"]; int numberOfMatches = call.arguments["numberOfMatches"];
bool isDoneCounting = call.arguments["isDoneCounting"]; bool isDoneCounting = call.arguments["isDoneCounting"];
if (_widget != null && _widget.onFindResultReceived != null) if (_widget != null && _widget.onFindResultReceived != null)
_widget.onFindResultReceived(this, activeMatchOrdinal, numberOfMatches, isDoneCounting); _widget.onFindResultReceived(
this, activeMatchOrdinal, numberOfMatches, isDoneCounting);
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
_inAppBrowser.onFindResultReceived(activeMatchOrdinal, numberOfMatches, isDoneCounting); _inAppBrowser.onFindResultReceived(
activeMatchOrdinal, numberOfMatches, isDoneCounting);
break; break;
case "onNavigationStateChange": case "onNavigationStateChange":
String url = call.arguments["url"]; String url = call.arguments["url"];
...@@ -595,24 +675,34 @@ class InAppWebViewController { ...@@ -595,24 +675,34 @@ class InAppWebViewController {
String origin = call.arguments["origin"]; String origin = call.arguments["origin"];
List<String> resources = call.arguments["resources"].cast<String>(); List<String> resources = call.arguments["resources"].cast<String>();
if (_widget != null && _widget.onPermissionRequest != null) if (_widget != null && _widget.onPermissionRequest != null)
return (await _widget.onPermissionRequest(this, origin, resources))?.toMap(); return (await _widget.onPermissionRequest(this, origin, resources))
?.toMap();
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return (await _inAppBrowser.onPermissionRequest(origin, resources))?.toMap(); return (await _inAppBrowser.onPermissionRequest(origin, resources))
?.toMap();
break; break;
case "onCallJsHandler": case "onCallJsHandler":
String handlerName = call.arguments["handlerName"]; String handlerName = call.arguments["handlerName"];
// decode args to json // decode args to json
List<dynamic> args = jsonDecode(call.arguments["args"]); List<dynamic> args = jsonDecode(call.arguments["args"]);
switch(handlerName) { switch (handlerName) {
case "onLoadResource": case "onLoadResource":
Map<dynamic, dynamic> argMap = args[0]; Map<dynamic, dynamic> argMap = args[0];
String initiatorType = argMap["initiatorType"]; String initiatorType = argMap["initiatorType"];
String url = argMap["name"]; String url = argMap["name"];
double startTime = argMap["startTime"] is int ? argMap["startTime"].toDouble() : argMap["startTime"]; double startTime = argMap["startTime"] is int
double duration = argMap["duration"] is int ? argMap["duration"].toDouble() : argMap["duration"]; ? argMap["startTime"].toDouble()
: argMap["startTime"];
var response = new LoadedResource(initiatorType: initiatorType, url: url, startTime: startTime, duration: duration); double duration = argMap["duration"] is int
? argMap["duration"].toDouble()
: argMap["duration"];
var response = new LoadedResource(
initiatorType: initiatorType,
url: url,
startTime: startTime,
duration: duration);
if (_widget != null && _widget.onLoadResource != null) if (_widget != null && _widget.onLoadResource != null)
_widget.onLoadResource(this, response); _widget.onLoadResource(this, response);
...@@ -631,12 +721,23 @@ class InAppWebViewController { ...@@ -631,12 +721,23 @@ class InAppWebViewController {
AjaxRequestHeaders headers = AjaxRequestHeaders(argMap["headers"]); AjaxRequestHeaders headers = AjaxRequestHeaders(argMap["headers"]);
String responseType = argMap["responseType"]; String responseType = argMap["responseType"];
var request = new AjaxRequest(data: data, method: method, url: url, isAsync: isAsync, user: user, password: password, withCredentials: withCredentials, headers: headers, responseType: responseType); var request = new AjaxRequest(
data: data,
method: method,
url: url,
isAsync: isAsync,
user: user,
password: password,
withCredentials: withCredentials,
headers: headers,
responseType: responseType);
if (_widget != null && _widget.shouldInterceptAjaxRequest != null) if (_widget != null && _widget.shouldInterceptAjaxRequest != null)
return jsonEncode(await _widget.shouldInterceptAjaxRequest(this, request)); return jsonEncode(
await _widget.shouldInterceptAjaxRequest(this, request));
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return jsonEncode(await _inAppBrowser.shouldInterceptAjaxRequest(request)); return jsonEncode(
await _inAppBrowser.shouldInterceptAjaxRequest(request));
return null; return null;
case "onAjaxReadyStateChange": case "onAjaxReadyStateChange":
Map<dynamic, dynamic> argMap = args[0]; Map<dynamic, dynamic> argMap = args[0];
...@@ -658,14 +759,31 @@ class InAppWebViewController { ...@@ -658,14 +759,31 @@ class InAppWebViewController {
String statusText = argMap["statusText"]; String statusText = argMap["statusText"];
Map<dynamic, dynamic> responseHeaders = argMap["responseHeaders"]; Map<dynamic, dynamic> responseHeaders = argMap["responseHeaders"];
var request = new AjaxRequest(data: data, method: method, url: url, isAsync: isAsync, user: user, password: password, var request = new AjaxRequest(
withCredentials: withCredentials, headers: headers, readyState: AjaxRequestReadyState.fromValue(readyState), status: status, responseURL: responseURL, data: data,
responseType: responseType, response: response, responseText: responseText, responseXML: responseXML, statusText: statusText, responseHeaders: responseHeaders); method: method,
url: url,
isAsync: isAsync,
user: user,
password: password,
withCredentials: withCredentials,
headers: headers,
readyState: AjaxRequestReadyState.fromValue(readyState),
status: status,
responseURL: responseURL,
responseType: responseType,
response: response,
responseText: responseText,
responseXML: responseXML,
statusText: statusText,
responseHeaders: responseHeaders);
if (_widget != null && _widget.onAjaxReadyStateChange != null) if (_widget != null && _widget.onAjaxReadyStateChange != null)
return jsonEncode(await _widget.onAjaxReadyStateChange(this, request)); return jsonEncode(
await _widget.onAjaxReadyStateChange(this, request));
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return jsonEncode(await _inAppBrowser.onAjaxReadyStateChange(request)); return jsonEncode(
await _inAppBrowser.onAjaxReadyStateChange(request));
return null; return null;
case "onAjaxProgress": case "onAjaxProgress":
Map<dynamic, dynamic> argMap = args[0]; Map<dynamic, dynamic> argMap = args[0];
...@@ -688,11 +806,31 @@ class InAppWebViewController { ...@@ -688,11 +806,31 @@ class InAppWebViewController {
Map<dynamic, dynamic> responseHeaders = argMap["responseHeaders"]; Map<dynamic, dynamic> responseHeaders = argMap["responseHeaders"];
Map<dynamic, dynamic> eventMap = argMap["event"]; Map<dynamic, dynamic> eventMap = argMap["event"];
AjaxRequestEvent event = AjaxRequestEvent(lengthComputable: eventMap["lengthComputable"], loaded: eventMap["loaded"], total: eventMap["total"], type: AjaxRequestEventType.fromValue(eventMap["type"])); AjaxRequestEvent event = AjaxRequestEvent(
lengthComputable: eventMap["lengthComputable"],
var request = new AjaxRequest(data: data, method: method, url: url, isAsync: isAsync, user: user, password: password, loaded: eventMap["loaded"],
withCredentials: withCredentials, headers: headers, readyState: AjaxRequestReadyState.fromValue(readyState), status: status, responseURL: responseURL, total: eventMap["total"],
responseType: responseType, response: response, responseText: responseText, responseXML: responseXML, statusText: statusText, responseHeaders: responseHeaders, event: event); type: AjaxRequestEventType.fromValue(eventMap["type"]));
var request = new AjaxRequest(
data: data,
method: method,
url: url,
isAsync: isAsync,
user: user,
password: password,
withCredentials: withCredentials,
headers: headers,
readyState: AjaxRequestReadyState.fromValue(readyState),
status: status,
responseURL: responseURL,
responseType: responseType,
response: response,
responseText: responseText,
responseXML: responseXML,
statusText: statusText,
responseHeaders: responseHeaders,
event: event);
if (_widget != null && _widget.onAjaxProgress != null) if (_widget != null && _widget.onAjaxProgress != null)
return jsonEncode(await _widget.onAjaxProgress(this, request)); return jsonEncode(await _widget.onAjaxProgress(this, request));
...@@ -706,7 +844,9 @@ class InAppWebViewController { ...@@ -706,7 +844,9 @@ class InAppWebViewController {
Map<dynamic, dynamic> headers = argMap["headers"]; Map<dynamic, dynamic> headers = argMap["headers"];
Uint8List body = Uint8List.fromList(argMap["body"].cast<int>()); Uint8List body = Uint8List.fromList(argMap["body"].cast<int>());
String mode = argMap["mode"]; String mode = argMap["mode"];
FetchRequestCredential credentials = FetchRequest.createFetchRequestCredentialFromMap(argMap["credentials"]); FetchRequestCredential credentials =
FetchRequest.createFetchRequestCredentialFromMap(
argMap["credentials"]);
String cache = argMap["cache"]; String cache = argMap["cache"];
String redirect = argMap["redirect"]; String redirect = argMap["redirect"];
String referrer = argMap["referrer"]; String referrer = argMap["referrer"];
...@@ -714,13 +854,26 @@ class InAppWebViewController { ...@@ -714,13 +854,26 @@ class InAppWebViewController {
String integrity = argMap["integrity"]; String integrity = argMap["integrity"];
bool keepalive = argMap["keepalive"]; bool keepalive = argMap["keepalive"];
var request = new FetchRequest(url: url, method: method, headers: headers, body: body, mode: mode, credentials: credentials, var request = new FetchRequest(
cache: cache, redirect: redirect, referrer: referrer, referrerPolicy: referrerPolicy, integrity: integrity, keepalive: keepalive); url: url,
method: method,
headers: headers,
body: body,
mode: mode,
credentials: credentials,
cache: cache,
redirect: redirect,
referrer: referrer,
referrerPolicy: referrerPolicy,
integrity: integrity,
keepalive: keepalive);
if (_widget != null && _widget.shouldInterceptFetchRequest != null) if (_widget != null && _widget.shouldInterceptFetchRequest != null)
return jsonEncode(await _widget.shouldInterceptFetchRequest(this, request)); return jsonEncode(
await _widget.shouldInterceptFetchRequest(this, request));
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return jsonEncode(await _inAppBrowser.shouldInterceptFetchRequest(request)); return jsonEncode(
await _inAppBrowser.shouldInterceptFetchRequest(request));
return null; return null;
} }
...@@ -777,10 +930,11 @@ class InAppWebViewController { ...@@ -777,10 +930,11 @@ class InAppWebViewController {
Future<String> getHtml() async { Future<String> getHtml() async {
var html = ""; var html = "";
InAppWebViewWidgetOptions options = await getOptions(); InAppWebViewWidgetOptions options = await getOptions();
if (options != null && options.inAppWebViewOptions.javaScriptEnabled == true) { if (options != null &&
html = await evaluateJavascript(source: "window.document.getElementsByTagName('html')[0].outerHTML;"); options.inAppWebViewOptions.javaScriptEnabled == true) {
if (html != null && html.isNotEmpty) html = await evaluateJavascript(
return html; source: "window.document.getElementsByTagName('html')[0].outerHTML;");
if (html != null && html.isNotEmpty) return html;
} }
var webviewUrl = await getUrl(); var webviewUrl = await getUrl();
...@@ -789,13 +943,13 @@ class InAppWebViewController { ...@@ -789,13 +943,13 @@ class InAppWebViewController {
var assetPath = assetPathSplitted[assetPathSplitted.length - 1]; var assetPath = assetPathSplitted[assetPathSplitted.length - 1];
var bytes = await rootBundle.load(assetPath); var bytes = await rootBundle.load(assetPath);
html = utf8.decode(bytes.buffer.asUint8List()); html = utf8.decode(bytes.buffer.asUint8List());
} } else {
else {
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
var url = Uri.parse(webviewUrl); var url = Uri.parse(webviewUrl);
try { try {
var htmlRequest = await client.getUrl(url); var htmlRequest = await client.getUrl(url);
html = await (await htmlRequest.close()).transform(Utf8Decoder()).join(); html =
await (await htmlRequest.close()).transform(Utf8Decoder()).join();
} catch (e) { } catch (e) {
print(e); print(e);
} }
...@@ -809,7 +963,9 @@ class InAppWebViewController { ...@@ -809,7 +963,9 @@ class InAppWebViewController {
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
var webviewUrl = await getUrl(); var webviewUrl = await getUrl();
var url = (webviewUrl.startsWith("file:///")) ? Uri.file(webviewUrl) : Uri.parse(webviewUrl); var url = (webviewUrl.startsWith("file:///"))
? Uri.file(webviewUrl)
: Uri.parse(webviewUrl);
String manifestUrl; String manifestUrl;
var html = await getHtml(); var html = await getHtml();
...@@ -835,14 +991,18 @@ class InAppWebViewController { ...@@ -835,14 +991,18 @@ class InAppWebViewController {
if (manifestUrl.startsWith("/")) { if (manifestUrl.startsWith("/")) {
manifestUrl = manifestUrl.substring(1); manifestUrl = manifestUrl.substring(1);
} }
manifestUrl = ((assetPathBase == null) ? url.scheme + "://" + url.host + "/" : assetPathBase) + manifestUrl; manifestUrl = ((assetPathBase == null)
? url.scheme + "://" + url.host + "/"
: assetPathBase) +
manifestUrl;
} }
continue; continue;
} }
if (!attributes["rel"].contains("icon")) { if (!attributes["rel"].contains("icon")) {
continue; continue;
} }
favicons.addAll(_createFavicons(url, assetPathBase, attributes["href"], attributes["rel"], attributes["sizes"], false)); favicons.addAll(_createFavicons(url, assetPathBase, attributes["href"],
attributes["rel"], attributes["sizes"], false));
} }
// try to get /favicon.ico // try to get /favicon.ico
...@@ -850,7 +1010,7 @@ class InAppWebViewController { ...@@ -850,7 +1010,7 @@ class InAppWebViewController {
var faviconUrl = url.scheme + "://" + url.host + "/favicon.ico"; var faviconUrl = url.scheme + "://" + url.host + "/favicon.ico";
await client.headUrl(Uri.parse(faviconUrl)); await client.headUrl(Uri.parse(faviconUrl));
favicons.add(Favicon(url: faviconUrl, rel: "shortcut icon")); favicons.add(Favicon(url: faviconUrl, rel: "shortcut icon"));
} catch(e) { } catch (e) {
print("/favicon.ico file not found: " + e.toString()); print("/favicon.ico file not found: " + e.toString());
} }
...@@ -864,16 +1024,19 @@ class InAppWebViewController { ...@@ -864,16 +1024,19 @@ class InAppWebViewController {
try { try {
manifestRequest = await client.getUrl(Uri.parse(manifestUrl)); manifestRequest = await client.getUrl(Uri.parse(manifestUrl));
manifestResponse = await manifestRequest.close(); manifestResponse = await manifestRequest.close();
manifestFound = manifestResponse.statusCode == 200 && manifestResponse.headers.contentType?.mimeType == "application/json"; manifestFound = manifestResponse.statusCode == 200 &&
} catch(e) { manifestResponse.headers.contentType?.mimeType == "application/json";
} catch (e) {
print("Manifest file not found: " + e.toString()); print("Manifest file not found: " + e.toString());
} }
if (manifestFound) { if (manifestFound) {
Map<String, dynamic> manifest = json.decode(await manifestResponse.transform(Utf8Decoder()).join()); Map<String, dynamic> manifest =
json.decode(await manifestResponse.transform(Utf8Decoder()).join());
if (manifest.containsKey("icons")) { if (manifest.containsKey("icons")) {
for(Map<String, dynamic> icon in manifest["icons"]) { for (Map<String, dynamic> icon in manifest["icons"]) {
favicons.addAll(_createFavicons(url, assetPathBase, icon["src"], icon["rel"], icon["sizes"], true)); favicons.addAll(_createFavicons(url, assetPathBase, icon["src"],
icon["rel"], icon["sizes"], true));
} }
} }
} }
...@@ -885,7 +1048,8 @@ class InAppWebViewController { ...@@ -885,7 +1048,8 @@ class InAppWebViewController {
return url.startsWith("http://") || url.startsWith("https://"); return url.startsWith("http://") || url.startsWith("https://");
} }
List<Favicon> _createFavicons(Uri url, String assetPathBase, String urlIcon, String rel, String sizes, bool isManifest) { List<Favicon> _createFavicons(Uri url, String assetPathBase, String urlIcon,
String rel, String sizes, bool isManifest) {
List<Favicon> favicons = []; List<Favicon> favicons = [];
List<String> urlSplitted = urlIcon.split("/"); List<String> urlSplitted = urlIcon.split("/");
...@@ -893,17 +1057,26 @@ class InAppWebViewController { ...@@ -893,17 +1057,26 @@ class InAppWebViewController {
if (urlIcon.startsWith("/")) { if (urlIcon.startsWith("/")) {
urlIcon = urlIcon.substring(1); urlIcon = urlIcon.substring(1);
} }
urlIcon = ((assetPathBase == null) ? url.scheme + "://" + url.host + "/" : assetPathBase) + urlIcon; urlIcon = ((assetPathBase == null)
? url.scheme + "://" + url.host + "/"
: assetPathBase) +
urlIcon;
} }
if (isManifest) { if (isManifest) {
rel = (sizes != null) ? urlSplitted[urlSplitted.length - 1].replaceFirst("-" + sizes, "").split(" ")[0].split(".")[0] : null; rel = (sizes != null)
? urlSplitted[urlSplitted.length - 1]
.replaceFirst("-" + sizes, "")
.split(" ")[0]
.split(".")[0]
: null;
} }
if (sizes != null && sizes.isNotEmpty && sizes != "any") { if (sizes != null && sizes.isNotEmpty && sizes != "any") {
List<String> sizesSplitted = sizes.split(" "); List<String> sizesSplitted = sizes.split(" ");
for (String size in sizesSplitted) { for (String size in sizesSplitted) {
int width = int.parse(size.split("x")[0]); int width = int.parse(size.split("x")[0]);
int height = int.parse(size.split("x")[1]); int height = int.parse(size.split("x")[1]);
favicons.add(Favicon(url: urlIcon, rel: rel, width: width, height: height)); favicons
.add(Favicon(url: urlIcon, rel: rel, width: width, height: height));
} }
} else { } else {
favicons.add(Favicon(url: urlIcon, rel: rel, width: null, height: null)); favicons.add(Favicon(url: urlIcon, rel: rel, width: null, height: null));
...@@ -913,7 +1086,8 @@ class InAppWebViewController { ...@@ -913,7 +1086,8 @@ class InAppWebViewController {
} }
///Loads the given [url] with optional [headers] specified as a map from name to value. ///Loads the given [url] with optional [headers] specified as a map from name to value.
Future<void> loadUrl({@required String url, Map<String, String> headers = const {}}) async { Future<void> loadUrl(
{@required String url, Map<String, String> headers = const {}}) async {
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) { if (_inAppBrowserUuid != null && _inAppBrowser != null) {
...@@ -926,7 +1100,8 @@ class InAppWebViewController { ...@@ -926,7 +1100,8 @@ class InAppWebViewController {
} }
///Loads the given [url] with [postData] using `POST` method into this WebView. ///Loads the given [url] with [postData] using `POST` method into this WebView.
Future<void> postUrl({@required String url, @required Uint8List postData}) async { Future<void> postUrl(
{@required String url, @required Uint8List postData}) async {
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
assert(postData != null); assert(postData != null);
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
...@@ -942,7 +1117,11 @@ class InAppWebViewController { ...@@ -942,7 +1117,11 @@ class InAppWebViewController {
///Loads the given [data] into this WebView, using [baseUrl] as the base URL for the content. ///Loads the given [data] into this WebView, using [baseUrl] as the base URL for the content.
///The [mimeType] parameter specifies the format of the data. ///The [mimeType] parameter specifies the format of the data.
///The [encoding] parameter specifies the encoding of the data. ///The [encoding] parameter specifies the encoding of the data.
Future<void> loadData({@required String data, String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank"}) async { Future<void> loadData(
{@required String data,
String mimeType = "text/html",
String encoding = "utf8",
String baseUrl = "about:blank"}) async {
assert(data != null); assert(data != null);
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) { if (_inAppBrowserUuid != null && _inAppBrowser != null) {
...@@ -985,7 +1164,9 @@ class InAppWebViewController { ...@@ -985,7 +1164,9 @@ class InAppWebViewController {
///inAppBrowser.loadFile("assets/index.html"); ///inAppBrowser.loadFile("assets/index.html");
///... ///...
///``` ///```
Future<void> loadFile({@required String assetFilePath, Map<String, String> headers = const {}}) async { Future<void> loadFile(
{@required String assetFilePath,
Map<String, String> headers = const {}}) async {
assert(assetFilePath != null && assetFilePath.isNotEmpty); assert(assetFilePath != null && assetFilePath.isNotEmpty);
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) { if (_inAppBrowserUuid != null && _inAppBrowser != null) {
...@@ -1107,8 +1288,7 @@ class InAppWebViewController { ...@@ -1107,8 +1288,7 @@ class InAppWebViewController {
} }
args.putIfAbsent('source', () => source); args.putIfAbsent('source', () => source);
var data = await _channel.invokeMethod('evaluateJavascript', args); var data = await _channel.invokeMethod('evaluateJavascript', args);
if (data != null && Platform.isAndroid) if (data != null && Platform.isAndroid) data = json.decode(data);
data = json.decode(data);
return data; return data;
} }
...@@ -1124,7 +1304,8 @@ class InAppWebViewController { ...@@ -1124,7 +1304,8 @@ class InAppWebViewController {
} }
///Injects a JavaScript file into the WebView from the flutter assets directory. ///Injects a JavaScript file into the WebView from the flutter assets directory.
Future<void> injectJavascriptFileFromAsset({@required String assetFilePath}) async { Future<void> injectJavascriptFileFromAsset(
{@required String assetFilePath}) async {
String source = await rootBundle.loadString(assetFilePath); String source = await rootBundle.loadString(assetFilePath);
await evaluateJavascript(source: source); await evaluateJavascript(source: source);
} }
...@@ -1201,7 +1382,9 @@ class InAppWebViewController { ...@@ -1201,7 +1382,9 @@ class InAppWebViewController {
/// }); /// });
/// """); /// """);
///``` ///```
void addJavaScriptHandler({@required String handlerName, @required JavaScriptHandlerCallback callback}) { void addJavaScriptHandler(
{@required String handlerName,
@required JavaScriptHandlerCallback callback}) {
assert(!javaScriptHandlerForbiddenNames.contains(handlerName)); assert(!javaScriptHandlerForbiddenNames.contains(handlerName));
this.javaScriptHandlersMap[handlerName] = (callback); this.javaScriptHandlersMap[handlerName] = (callback);
} }
...@@ -1209,7 +1392,8 @@ class InAppWebViewController { ...@@ -1209,7 +1392,8 @@ class InAppWebViewController {
///Removes a JavaScript message handler previously added with the [addJavaScriptHandler()] associated to [handlerName] key. ///Removes a JavaScript message handler previously added with the [addJavaScriptHandler()] associated to [handlerName] key.
///Returns the value associated with [handlerName] before it was removed. ///Returns the value associated with [handlerName] before it was removed.
///Returns `null` if [handlerName] was not found. ///Returns `null` if [handlerName] was not found.
JavaScriptHandlerCallback removeJavaScriptHandler({@required String handlerName}) { JavaScriptHandlerCallback removeJavaScriptHandler(
{@required String handlerName}) {
return this.javaScriptHandlersMap.remove(handlerName); return this.javaScriptHandlersMap.remove(handlerName);
} }
...@@ -1252,15 +1436,20 @@ class InAppWebViewController { ...@@ -1252,15 +1436,20 @@ class InAppWebViewController {
args.putIfAbsent('uuid', () => _inAppBrowserUuid); args.putIfAbsent('uuid', () => _inAppBrowserUuid);
} }
InAppWebViewWidgetOptions inAppWebViewWidgetOptions = InAppWebViewWidgetOptions(); InAppWebViewWidgetOptions inAppWebViewWidgetOptions =
Map<dynamic, dynamic> options = await _channel.invokeMethod('getOptions', args); InAppWebViewWidgetOptions();
Map<dynamic, dynamic> options =
await _channel.invokeMethod('getOptions', args);
if (options != null) { if (options != null) {
options = options.cast<String, dynamic>(); options = options.cast<String, dynamic>();
inAppWebViewWidgetOptions.inAppWebViewOptions = InAppWebViewOptions.fromMap(options); inAppWebViewWidgetOptions.inAppWebViewOptions =
InAppWebViewOptions.fromMap(options);
if (Platform.isAndroid) if (Platform.isAndroid)
inAppWebViewWidgetOptions.androidInAppWebViewOptions = AndroidInAppWebViewOptions.fromMap(options); inAppWebViewWidgetOptions.androidInAppWebViewOptions =
AndroidInAppWebViewOptions.fromMap(options);
else if (Platform.isIOS) else if (Platform.isIOS)
inAppWebViewWidgetOptions.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options); inAppWebViewWidgetOptions.iosInAppWebViewOptions =
IosInAppWebViewOptions.fromMap(options);
} }
return inAppWebViewWidgetOptions; return inAppWebViewWidgetOptions;
...@@ -1276,7 +1465,8 @@ class InAppWebViewController { ...@@ -1276,7 +1465,8 @@ class InAppWebViewController {
_inAppBrowser.throwIsNotOpened(); _inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid); args.putIfAbsent('uuid', () => _inAppBrowserUuid);
} }
Map<dynamic, dynamic> result = await _channel.invokeMethod('getCopyBackForwardList', args); Map<dynamic, dynamic> result =
await _channel.invokeMethod('getCopyBackForwardList', args);
result = result.cast<String, dynamic>(); result = result.cast<String, dynamic>();
List<dynamic> historyListMap = result["history"]; List<dynamic> historyListMap = result["history"];
...@@ -1285,9 +1475,14 @@ class InAppWebViewController { ...@@ -1285,9 +1475,14 @@ class InAppWebViewController {
int currentIndex = result["currentIndex"]; int currentIndex = result["currentIndex"];
List<WebHistoryItem> historyList = List(); List<WebHistoryItem> historyList = List();
for(var i = 0; i < historyListMap.length; i++) { for (var i = 0; i < historyListMap.length; i++) {
LinkedHashMap<dynamic, dynamic> historyItem = historyListMap[i]; LinkedHashMap<dynamic, dynamic> historyItem = historyListMap[i];
historyList.add(WebHistoryItem(originalUrl: historyItem["originalUrl"], title: historyItem["title"], url: historyItem["url"], index: i, offset: i - currentIndex)); historyList.add(WebHistoryItem(
originalUrl: historyItem["originalUrl"],
title: historyItem["title"],
url: historyItem["url"],
index: i,
offset: i - currentIndex));
} }
return WebHistory(list: historyList, currentIndex: currentIndex); return WebHistory(list: historyList, currentIndex: currentIndex);
} }
...@@ -1434,12 +1629,14 @@ class InAppWebViewController { ...@@ -1434,12 +1629,14 @@ class InAppWebViewController {
///Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerCss()]. ///Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerCss()].
Future<String> getTRexRunnerHtml() async { Future<String> getTRexRunnerHtml() async {
return await rootBundle.loadString("packages/flutter_inappwebview/t_rex_runner/t-rex.html"); return await rootBundle
.loadString("packages/flutter_inappwebview/t_rex_runner/t-rex.html");
} }
///Gets the css of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerHtml()]. ///Gets the css of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerHtml()].
Future<String> getTRexRunnerCss() async { Future<String> getTRexRunnerCss() async {
return await rootBundle.loadString("packages/flutter_inappwebview/t_rex_runner/t-rex.css"); return await rootBundle
.loadString("packages/flutter_inappwebview/t_rex_runner/t-rex.css");
} }
///Scrolls the WebView to the position. ///Scrolls the WebView to the position.
......
...@@ -32,10 +32,11 @@ class ConsoleMessageLevel { ...@@ -32,10 +32,11 @@ class ConsoleMessageLevel {
return ConsoleMessageLevel._internal(value); return ConsoleMessageLevel._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 0: case 0:
return "TIP"; return "TIP";
case 2: case 2:
...@@ -65,18 +66,19 @@ class ConsoleMessageLevel { ...@@ -65,18 +66,19 @@ class ConsoleMessageLevel {
///Public class representing a resource response of the [InAppBrowser] WebView. ///Public class representing a resource response of the [InAppBrowser] WebView.
///It is used by the method [InAppBrowser.onLoadResource()]. ///It is used by the method [InAppBrowser.onLoadResource()].
class LoadedResource { class LoadedResource {
///A string representing the type of resource. ///A string representing the type of resource.
String initiatorType; String initiatorType;
///Resource URL. ///Resource URL.
String url; String url;
///Returns the [DOMHighResTimeStamp](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp) for the time a resource fetch started. ///Returns the [DOMHighResTimeStamp](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp) for the time a resource fetch started.
double startTime; double startTime;
///Returns the [DOMHighResTimeStamp](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp) duration to fetch a resource. ///Returns the [DOMHighResTimeStamp](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp) duration to fetch a resource.
double duration; double duration;
LoadedResource({this.initiatorType, this.url, this.startTime, this.duration}); LoadedResource({this.initiatorType, this.url, this.startTime, this.duration});
} }
///Initial [data] as a content for an [InAppWebView] instance, using [baseUrl] as the base URL for it. ///Initial [data] as a content for an [InAppWebView] instance, using [baseUrl] as the base URL for it.
...@@ -88,7 +90,11 @@ class InAppWebViewInitialData { ...@@ -88,7 +90,11 @@ class InAppWebViewInitialData {
String encoding; String encoding;
String baseUrl; String baseUrl;
InAppWebViewInitialData({@required this.data, this.mimeType = "text/html", this.encoding = "utf8", this.baseUrl = "about:blank"}); InAppWebViewInitialData(
{@required this.data,
this.mimeType = "text/html",
this.encoding = "utf8",
this.baseUrl = "about:blank"});
Map<String, String> toMap() { Map<String, String> toMap() {
return { return {
...@@ -136,12 +142,17 @@ class WebResourceResponse { ...@@ -136,12 +142,17 @@ class WebResourceResponse {
class CustomSchemeResponse { class CustomSchemeResponse {
///Data enconded to 'base64'. ///Data enconded to 'base64'.
Uint8List data; Uint8List data;
///Content-Type of the data, such as `image/png`. ///Content-Type of the data, such as `image/png`.
String contentType; String contentType;
///Content-Enconding of the data, such as `utf-8`. ///Content-Enconding of the data, such as `utf-8`.
String contentEnconding; String contentEnconding;
CustomSchemeResponse({@required this.data, @required this.contentType, this.contentEnconding = 'utf-8'}); CustomSchemeResponse(
{@required this.data,
@required this.contentType,
this.contentEnconding = 'utf-8'});
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {
...@@ -157,11 +168,11 @@ class CustomSchemeResponse { ...@@ -157,11 +168,11 @@ class CustomSchemeResponse {
/// ///
///To receive notifications of these messages, use the [onConsoleMessage] event. ///To receive notifications of these messages, use the [onConsoleMessage] event.
class ConsoleMessage { class ConsoleMessage {
String message; String message;
ConsoleMessageLevel messageLevel; ConsoleMessageLevel messageLevel;
ConsoleMessage({this.message = "", this.messageLevel = ConsoleMessageLevel.LOG}); ConsoleMessage(
{this.message = "", this.messageLevel = ConsoleMessageLevel.LOG});
} }
///WebHistory class. ///WebHistory class.
...@@ -170,6 +181,7 @@ class ConsoleMessage { ...@@ -170,6 +181,7 @@ class ConsoleMessage {
class WebHistory { class WebHistory {
///List of all [WebHistoryItem]s. ///List of all [WebHistoryItem]s.
List<WebHistoryItem> list; List<WebHistoryItem> list;
///Index of the current [WebHistoryItem]. ///Index of the current [WebHistoryItem].
int currentIndex; int currentIndex;
...@@ -182,16 +194,21 @@ class WebHistory { ...@@ -182,16 +194,21 @@ class WebHistory {
class WebHistoryItem { class WebHistoryItem {
///Original url of this history item. ///Original url of this history item.
String originalUrl; String originalUrl;
///Document title of this history item. ///Document title of this history item.
String title; String title;
///Url of this history item. ///Url of this history item.
String url; String url;
///0-based position index in the back-forward [WebHistory.list]. ///0-based position index in the back-forward [WebHistory.list].
int index; int index;
///Position offset respect to the currentIndex of the back-forward [WebHistory.list]. ///Position offset respect to the currentIndex of the back-forward [WebHistory.list].
int offset; int offset;
WebHistoryItem({this.originalUrl, this.title, this.url, this.index, this.offset}); WebHistoryItem(
{this.originalUrl, this.title, this.url, this.index, this.offset});
} }
///GeolocationPermissionPromptResponse class. ///GeolocationPermissionPromptResponse class.
...@@ -200,19 +217,18 @@ class WebHistoryItem { ...@@ -200,19 +217,18 @@ class WebHistoryItem {
class GeolocationPermissionShowPromptResponse { class GeolocationPermissionShowPromptResponse {
///The origin for which permissions are set. ///The origin for which permissions are set.
String origin; String origin;
///Whether or not the origin should be allowed to use the Geolocation API. ///Whether or not the origin should be allowed to use the Geolocation API.
bool allow; bool allow;
///Whether the permission should be retained beyond the lifetime of a page currently being displayed by a WebView ///Whether the permission should be retained beyond the lifetime of a page currently being displayed by a WebView
bool retain; bool retain;
GeolocationPermissionShowPromptResponse({this.origin, this.allow, this.retain}); GeolocationPermissionShowPromptResponse(
{this.origin, this.allow, this.retain});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {"origin": origin, "allow": allow, "retain": retain};
"origin": origin,
"allow": allow,
"retain": retain
};
} }
} }
...@@ -234,14 +250,21 @@ class JsAlertResponseAction { ...@@ -234,14 +250,21 @@ class JsAlertResponseAction {
class JsAlertResponse { class JsAlertResponse {
///Message to be displayed in the window. ///Message to be displayed in the window.
String message; String message;
///Title of the confirm button. ///Title of the confirm button.
String confirmButtonTitle; String confirmButtonTitle;
///Whether the client will handle the alert dialog. ///Whether the client will handle the alert dialog.
bool handledByClient; bool handledByClient;
///Action used to confirm that the user hit confirm button. ///Action used to confirm that the user hit confirm button.
JsAlertResponseAction action; JsAlertResponseAction action;
JsAlertResponse({this.message = "", this.handledByClient = false, this.confirmButtonTitle = "", this.action = JsAlertResponseAction.CONFIRM}); JsAlertResponse(
{this.message = "",
this.handledByClient = false,
this.confirmButtonTitle = "",
this.action = JsAlertResponseAction.CONFIRM});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
...@@ -272,16 +295,25 @@ class JsConfirmResponseAction { ...@@ -272,16 +295,25 @@ class JsConfirmResponseAction {
class JsConfirmResponse { class JsConfirmResponse {
///Message to be displayed in the window. ///Message to be displayed in the window.
String message; String message;
///Title of the confirm button. ///Title of the confirm button.
String confirmButtonTitle; String confirmButtonTitle;
///Title of the cancel button. ///Title of the cancel button.
String cancelButtonTitle; String cancelButtonTitle;
///Whether the client will handle the confirm dialog. ///Whether the client will handle the confirm dialog.
bool handledByClient; bool handledByClient;
///Action used to confirm that the user hit confirm or cancel button. ///Action used to confirm that the user hit confirm or cancel button.
JsConfirmResponseAction action; JsConfirmResponseAction action;
JsConfirmResponse({this.message = "", this.handledByClient = false, this.confirmButtonTitle = "", this.cancelButtonTitle = "", this.action = JsConfirmResponseAction.CANCEL}); JsConfirmResponse(
{this.message = "",
this.handledByClient = false,
this.confirmButtonTitle = "",
this.cancelButtonTitle = "",
this.action = JsConfirmResponseAction.CANCEL});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
...@@ -313,20 +345,33 @@ class JsPromptResponseAction { ...@@ -313,20 +345,33 @@ class JsPromptResponseAction {
class JsPromptResponse { class JsPromptResponse {
///Message to be displayed in the window. ///Message to be displayed in the window.
String message; String message;
///The default value displayed in the prompt dialog. ///The default value displayed in the prompt dialog.
String defaultValue; String defaultValue;
///Title of the confirm button. ///Title of the confirm button.
String confirmButtonTitle; String confirmButtonTitle;
///Title of the cancel button. ///Title of the cancel button.
String cancelButtonTitle; String cancelButtonTitle;
///Whether the client will handle the prompt dialog. ///Whether the client will handle the prompt dialog.
bool handledByClient; bool handledByClient;
///Value of the prompt dialog. ///Value of the prompt dialog.
String value; String value;
///Action used to confirm that the user hit confirm or cancel button. ///Action used to confirm that the user hit confirm or cancel button.
JsPromptResponseAction action; JsPromptResponseAction action;
JsPromptResponse({this.message = "", this.defaultValue = "", this.handledByClient = false, this.confirmButtonTitle = "", this.cancelButtonTitle = "", this.value, this.action = JsPromptResponseAction.CANCEL}); JsPromptResponse(
{this.message = "",
this.defaultValue = "",
this.handledByClient = false,
this.confirmButtonTitle = "",
this.cancelButtonTitle = "",
this.value,
this.action = JsPromptResponseAction.CANCEL});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
...@@ -350,9 +395,10 @@ class SafeBrowsingThreat { ...@@ -350,9 +395,10 @@ class SafeBrowsingThreat {
return SafeBrowsingThreat._internal(value); return SafeBrowsingThreat._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "SAFE_BROWSING_THREAT_MALWARE"; return "SAFE_BROWSING_THREAT_MALWARE";
case 2: case 2:
...@@ -367,11 +413,16 @@ class SafeBrowsingThreat { ...@@ -367,11 +413,16 @@ class SafeBrowsingThreat {
} }
} }
static const SAFE_BROWSING_THREAT_UNKNOWN = const SafeBrowsingThreat._internal(0); static const SAFE_BROWSING_THREAT_UNKNOWN =
static const SAFE_BROWSING_THREAT_MALWARE = const SafeBrowsingThreat._internal(1); const SafeBrowsingThreat._internal(0);
static const SAFE_BROWSING_THREAT_PHISHING = const SafeBrowsingThreat._internal(2); static const SAFE_BROWSING_THREAT_MALWARE =
static const SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE = const SafeBrowsingThreat._internal(3); const SafeBrowsingThreat._internal(1);
static const SAFE_BROWSING_THREAT_BILLING = const SafeBrowsingThreat._internal(4); static const SAFE_BROWSING_THREAT_PHISHING =
const SafeBrowsingThreat._internal(2);
static const SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE =
const SafeBrowsingThreat._internal(3);
static const SAFE_BROWSING_THREAT_BILLING =
const SafeBrowsingThreat._internal(4);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -387,10 +438,13 @@ class SafeBrowsingResponseAction { ...@@ -387,10 +438,13 @@ class SafeBrowsingResponseAction {
///Act as if the user clicked the "back to safety" button. ///Act as if the user clicked the "back to safety" button.
static const BACK_TO_SAFETY = const SafeBrowsingResponseAction._internal(0); static const BACK_TO_SAFETY = const SafeBrowsingResponseAction._internal(0);
///Act as if the user clicked the "visit this unsafe site" button. ///Act as if the user clicked the "visit this unsafe site" button.
static const PROCEED = const SafeBrowsingResponseAction._internal(1); static const PROCEED = const SafeBrowsingResponseAction._internal(1);
///Display the default interstitial. ///Display the default interstitial.
static const SHOW_INTERSTITIAL = const SafeBrowsingResponseAction._internal(2); static const SHOW_INTERSTITIAL =
const SafeBrowsingResponseAction._internal(2);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -403,16 +457,16 @@ class SafeBrowsingResponseAction { ...@@ -403,16 +457,16 @@ class SafeBrowsingResponseAction {
class SafeBrowsingResponse { 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.getSafeBrowsingPrivacyPolicyUrl].
bool report; bool report;
///Indicate the [SafeBrowsingResponseAction] to take when hitting a malicious URL. ///Indicate the [SafeBrowsingResponseAction] to take when hitting a malicious URL.
SafeBrowsingResponseAction action; SafeBrowsingResponseAction action;
SafeBrowsingResponse({this.report = true, this.action = SafeBrowsingResponseAction.SHOW_INTERSTITIAL}); SafeBrowsingResponse(
{this.report = true,
this.action = SafeBrowsingResponseAction.SHOW_INTERSTITIAL});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {"report": report, "action": action?.toValue()};
"report": report,
"action": action?.toValue()
};
} }
} }
...@@ -424,10 +478,13 @@ class HttpAuthResponseAction { ...@@ -424,10 +478,13 @@ class HttpAuthResponseAction {
///Instructs the WebView to cancel the authentication request. ///Instructs the WebView to cancel the authentication request.
static const CANCEL = const HttpAuthResponseAction._internal(0); static const CANCEL = const HttpAuthResponseAction._internal(0);
///Instructs the WebView to proceed with the authentication with the given credentials. ///Instructs the WebView to proceed with the authentication with the given credentials.
static const PROCEED = const HttpAuthResponseAction._internal(1); static const PROCEED = const HttpAuthResponseAction._internal(1);
///Uses the credentials stored for the current host. ///Uses the credentials stored for the current host.
static const USE_SAVED_HTTP_AUTH_CREDENTIALS = const HttpAuthResponseAction._internal(2); static const USE_SAVED_HTTP_AUTH_CREDENTIALS =
const HttpAuthResponseAction._internal(2);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -439,14 +496,21 @@ class HttpAuthResponseAction { ...@@ -439,14 +496,21 @@ class HttpAuthResponseAction {
class HttpAuthResponse { class HttpAuthResponse {
///Represents the username used for the authentication if the [action] corresponds to [HttpAuthResponseAction.PROCEED] ///Represents the username used for the authentication if the [action] corresponds to [HttpAuthResponseAction.PROCEED]
String username; String username;
///Represents the password used for the authentication if the [action] corresponds to [HttpAuthResponseAction.PROCEED] ///Represents the password used for the authentication if the [action] corresponds to [HttpAuthResponseAction.PROCEED]
String password; String password;
///Indicate if the given credentials need to be saved permanently. ///Indicate if the given credentials need to be saved permanently.
bool permanentPersistence; bool permanentPersistence;
///Indicate the [HttpAuthResponseAction] to take in response of the authentication challenge. ///Indicate the [HttpAuthResponseAction] to take in response of the authentication challenge.
HttpAuthResponseAction action; HttpAuthResponseAction action;
HttpAuthResponse({this.username = "", this.password = "", this.permanentPersistence = false, this.action = HttpAuthResponseAction.CANCEL}); HttpAuthResponse(
{this.username = "",
this.password = "",
this.permanentPersistence = false,
this.action = HttpAuthResponseAction.CANCEL});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
...@@ -463,26 +527,34 @@ class HttpAuthResponse { ...@@ -463,26 +527,34 @@ class HttpAuthResponse {
class HttpAuthChallenge { class HttpAuthChallenge {
///A count of previous failed authentication attempts. ///A count of previous failed authentication attempts.
int previousFailureCount; int previousFailureCount;
///The protection space requiring authentication. ///The protection space requiring authentication.
ProtectionSpace protectionSpace; ProtectionSpace protectionSpace;
HttpAuthChallenge({@required this.previousFailureCount, @required this.protectionSpace}): assert(previousFailureCount != null && protectionSpace != null); HttpAuthChallenge(
{@required this.previousFailureCount, @required this.protectionSpace})
: assert(previousFailureCount != null && protectionSpace != null);
} }
///ProtectionSpace class represents a protection space requiring authentication. ///ProtectionSpace class represents a protection space requiring authentication.
class ProtectionSpace { class ProtectionSpace {
///The hostname of the server. ///The hostname of the server.
String host; String host;
///The protocol of the server - e.g. "http", "ftp", "https". ///The protocol of the server - e.g. "http", "ftp", "https".
String protocol; String protocol;
///A string indicating a protocol-specific subdivision of a single host. ///A string indicating a protocol-specific subdivision of a single host.
///For http and https, this maps to the realm string in http authentication challenges. ///For http and https, this maps to the realm string in http authentication challenges.
///For many other protocols it is unused. ///For many other protocols it is unused.
String realm; String realm;
///The port of the server. ///The port of the server.
int port; int port;
ProtectionSpace({@required this.host, @required this.protocol, this.realm, this.port}): assert(host != null && protocol != null); ProtectionSpace(
{@required this.host, @required this.protocol, this.realm, this.port})
: assert(host != null && protocol != null);
} }
///HttpAuthCredential represents the credentials of an http authentication. ///HttpAuthCredential represents the credentials of an http authentication.
...@@ -490,10 +562,12 @@ class ProtectionSpace { ...@@ -490,10 +562,12 @@ class ProtectionSpace {
class HttpAuthCredential { class HttpAuthCredential {
///Represents the username. ///Represents the username.
String username; String username;
///Represents the password. ///Represents the password.
String password; String password;
HttpAuthCredential({@required this.username, @required this.password}): assert(username != null && password != null); HttpAuthCredential({@required this.username, @required this.password})
: assert(username != null && password != null);
} }
///ServerTrustAuthResponseAction class used by [ServerTrustAuthResponse] class. ///ServerTrustAuthResponseAction class used by [ServerTrustAuthResponse] class.
...@@ -504,6 +578,7 @@ class ServerTrustAuthResponseAction { ...@@ -504,6 +578,7 @@ class ServerTrustAuthResponseAction {
///Instructs the WebView to cancel the authentication challenge. ///Instructs the WebView to cancel the authentication challenge.
static const CANCEL = const ServerTrustAuthResponseAction._internal(0); static const CANCEL = const ServerTrustAuthResponseAction._internal(0);
///Instructs the WebView to proceed with the authentication challenge. ///Instructs the WebView to proceed with the authentication challenge.
static const PROCEED = const ServerTrustAuthResponseAction._internal(1); static const PROCEED = const ServerTrustAuthResponseAction._internal(1);
...@@ -521,9 +596,7 @@ class ServerTrustAuthResponse { ...@@ -521,9 +596,7 @@ class ServerTrustAuthResponse {
ServerTrustAuthResponse({this.action = ServerTrustAuthResponseAction.CANCEL}); ServerTrustAuthResponse({this.action = ServerTrustAuthResponseAction.CANCEL});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {"action": action?.toValue()};
"action": action?.toValue()
};
} }
} }
...@@ -532,18 +605,26 @@ class ServerTrustAuthResponse { ...@@ -532,18 +605,26 @@ class ServerTrustAuthResponse {
class ServerTrustChallenge { class ServerTrustChallenge {
///The protection space requiring authentication. ///The protection space requiring authentication.
ProtectionSpace protectionSpace; ProtectionSpace protectionSpace;
///The primary error associated to the server SSL certificate. ///The primary error associated to the server SSL certificate.
/// ///
///**NOTE**: on iOS this value is always -1. ///**NOTE**: on iOS this value is always -1.
int error; int error;
///The message associated to the [error]. ///The message associated to the [error].
/// ///
///**NOTE**: on iOS this value is always an empty string. ///**NOTE**: on iOS this value is always an empty string.
String message; String message;
///The `X509Certificate` used to create the server SSL certificate. ///The `X509Certificate` used to create the server SSL certificate.
Uint8List serverCertificate; Uint8List serverCertificate;
ServerTrustChallenge({@required this.protectionSpace, @required this.error, this.message, this.serverCertificate}): assert(protectionSpace != null && error != null); ServerTrustChallenge(
{@required this.protectionSpace,
@required this.error,
this.message,
this.serverCertificate})
: assert(protectionSpace != null && error != null);
} }
///ClientCertResponseAction class used by [ClientCertResponse] class. ///ClientCertResponseAction class used by [ClientCertResponse] class.
...@@ -554,8 +635,10 @@ class ClientCertResponseAction { ...@@ -554,8 +635,10 @@ class ClientCertResponseAction {
///Cancel this request. ///Cancel this request.
static const CANCEL = const ClientCertResponseAction._internal(0); static const CANCEL = const ClientCertResponseAction._internal(0);
///Proceed with the specified certificate. ///Proceed with the specified certificate.
static const PROCEED = const ClientCertResponseAction._internal(1); static const PROCEED = const ClientCertResponseAction._internal(1);
///Ignore the request for now. ///Ignore the request for now.
static const IGNORE = const ClientCertResponseAction._internal(2); static const IGNORE = const ClientCertResponseAction._internal(2);
...@@ -569,14 +652,21 @@ class ClientCertResponseAction { ...@@ -569,14 +652,21 @@ class ClientCertResponseAction {
class ClientCertResponse { class ClientCertResponse {
///The file path of the certificate to use. ///The file path of the certificate to use.
String certificatePath; String certificatePath;
///The certificate password. ///The certificate password.
String certificatePassword; String certificatePassword;
///An Android-specific property used by Java [KeyStore](https://developer.android.com/reference/java/security/KeyStore) class to get the instance. ///An Android-specific property used by Java [KeyStore](https://developer.android.com/reference/java/security/KeyStore) class to get the instance.
String androidKeyStoreType; String androidKeyStoreType;
///Indicate the [ClientCertResponseAction] to take in response of the client certificate challenge. ///Indicate the [ClientCertResponseAction] to take in response of the client certificate challenge.
ClientCertResponseAction action; ClientCertResponseAction action;
ClientCertResponse({this.certificatePath, this.certificatePassword = "", this.androidKeyStoreType = "PKCS12", this.action = ClientCertResponseAction.CANCEL}) { ClientCertResponse(
{this.certificatePath,
this.certificatePassword = "",
this.androidKeyStoreType = "PKCS12",
this.action = ClientCertResponseAction.CANCEL}) {
if (this.action == ClientCertResponseAction.PROCEED) if (this.action == ClientCertResponseAction.PROCEED)
assert(certificatePath != null && certificatePath.isNotEmpty); assert(certificatePath != null && certificatePath.isNotEmpty);
} }
...@@ -597,21 +687,26 @@ class ClientCertChallenge { ...@@ -597,21 +687,26 @@ class ClientCertChallenge {
///The protection space requiring authentication. ///The protection space requiring authentication.
ProtectionSpace protectionSpace; ProtectionSpace protectionSpace;
ClientCertChallenge({@required this.protectionSpace}): assert(protectionSpace != null); ClientCertChallenge({@required this.protectionSpace})
: assert(protectionSpace != null);
} }
///Favicon class represents a favicon of a website. It is used by [InAppWebViewController.getFavicons] method. ///Favicon class represents a favicon of a website. It is used by [InAppWebViewController.getFavicons] method.
class Favicon { class Favicon {
///The url of the favicon image. ///The url of the favicon image.
String url; String url;
///The relationship between the current web page and the favicon image. ///The relationship between the current web page and the favicon image.
String rel; String rel;
///The width of the favicon image. ///The width of the favicon image.
int width; int width;
///The height of the favicon image. ///The height of the favicon image.
int height; int height;
Favicon({@required this.url, this.rel, this.width, this.height}): assert(url != null); Favicon({@required this.url, this.rel, this.width, this.height})
: assert(url != null);
String toString() { String toString() {
return "url: $url, rel: $rel, width: $width, height: $height"; return "url: $url, rel: $rel, width: $width, height: $height";
...@@ -627,10 +722,11 @@ class AndroidInAppWebViewCacheMode { ...@@ -627,10 +722,11 @@ class AndroidInAppWebViewCacheMode {
return AndroidInAppWebViewCacheMode._internal(value); return AndroidInAppWebViewCacheMode._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "LOAD_CACHE_ELSE_NETWORK"; return "LOAD_CACHE_ELSE_NETWORK";
case 2: case 2:
...@@ -646,12 +742,17 @@ class AndroidInAppWebViewCacheMode { ...@@ -646,12 +742,17 @@ class AndroidInAppWebViewCacheMode {
///Default cache usage mode. If the navigation type doesn't impose any specific behavior, ///Default cache usage mode. If the navigation type doesn't impose any specific behavior,
///use cached resources when they are available and not expired, otherwise load resources from the network. ///use cached resources when they are available and not expired, otherwise load resources from the network.
static const LOAD_DEFAULT = const AndroidInAppWebViewCacheMode._internal(-1); static const LOAD_DEFAULT = const AndroidInAppWebViewCacheMode._internal(-1);
///Use cached resources when they are available, even if they have expired. Otherwise load resources from the network. ///Use cached resources when they are available, even if they have expired. Otherwise load resources from the network.
static const LOAD_CACHE_ELSE_NETWORK = const AndroidInAppWebViewCacheMode._internal(1); static const LOAD_CACHE_ELSE_NETWORK =
const AndroidInAppWebViewCacheMode._internal(1);
///Don't use the cache, load from the network. ///Don't use the cache, load from the network.
static const LOAD_NO_CACHE = const AndroidInAppWebViewCacheMode._internal(2); static const LOAD_NO_CACHE = const AndroidInAppWebViewCacheMode._internal(2);
///Don't use the network, load from the cache. ///Don't use the network, load from the cache.
static const LOAD_CACHE_ONLY = const AndroidInAppWebViewCacheMode._internal(3); static const LOAD_CACHE_ONLY =
const AndroidInAppWebViewCacheMode._internal(3);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -670,10 +771,11 @@ class AndroidInAppWebViewModeMenuItem { ...@@ -670,10 +771,11 @@ class AndroidInAppWebViewModeMenuItem {
return AndroidInAppWebViewModeMenuItem._internal(value); return AndroidInAppWebViewModeMenuItem._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "MENU_ITEM_SHARE"; return "MENU_ITEM_SHARE";
case 2: case 2:
...@@ -687,13 +789,20 @@ class AndroidInAppWebViewModeMenuItem { ...@@ -687,13 +789,20 @@ class AndroidInAppWebViewModeMenuItem {
} }
///No menu items should be disabled. ///No menu items should be disabled.
static const MENU_ITEM_NONE = const AndroidInAppWebViewModeMenuItem._internal(0); static const MENU_ITEM_NONE =
const AndroidInAppWebViewModeMenuItem._internal(0);
///Disable menu item "Share". ///Disable menu item "Share".
static const MENU_ITEM_SHARE = const AndroidInAppWebViewModeMenuItem._internal(1); static const MENU_ITEM_SHARE =
const AndroidInAppWebViewModeMenuItem._internal(1);
///Disable menu item "Web Search". ///Disable menu item "Web Search".
static const MENU_ITEM_WEB_SEARCH = const AndroidInAppWebViewModeMenuItem._internal(2); static const MENU_ITEM_WEB_SEARCH =
const AndroidInAppWebViewModeMenuItem._internal(2);
///Disable all the action mode menu items for text processing. ///Disable all the action mode menu items for text processing.
static const MENU_ITEM_PROCESS_TEXT = const AndroidInAppWebViewModeMenuItem._internal(4); static const MENU_ITEM_PROCESS_TEXT =
const AndroidInAppWebViewModeMenuItem._internal(4);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -712,10 +821,11 @@ class AndroidInAppWebViewForceDark { ...@@ -712,10 +821,11 @@ class AndroidInAppWebViewForceDark {
return AndroidInAppWebViewForceDark._internal(value); return AndroidInAppWebViewForceDark._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "FORCE_DARK_AUTO"; return "FORCE_DARK_AUTO";
case 2: case 2:
...@@ -729,8 +839,11 @@ class AndroidInAppWebViewForceDark { ...@@ -729,8 +839,11 @@ class AndroidInAppWebViewForceDark {
///Disable force dark, irrespective of the force dark mode of the WebView parent. ///Disable force dark, irrespective of the force dark mode of the WebView parent.
///In this mode, WebView content will always be rendered as-is, regardless of whether native views are being automatically darkened. ///In this mode, WebView content will always be rendered as-is, regardless of whether native views are being automatically darkened.
static const FORCE_DARK_OFF = const AndroidInAppWebViewForceDark._internal(0); static const FORCE_DARK_OFF = const AndroidInAppWebViewForceDark._internal(0);
///Enable force dark dependent on the state of the WebView parent view. ///Enable force dark dependent on the state of the WebView parent view.
static const FORCE_DARK_AUTO = const AndroidInAppWebViewForceDark._internal(1); static const FORCE_DARK_AUTO =
const AndroidInAppWebViewForceDark._internal(1);
///Unconditionally enable force dark. In this mode WebView content will always be rendered so as to emulate a dark theme. ///Unconditionally enable force dark. In this mode WebView content will always be rendered so as to emulate a dark theme.
static const FORCE_DARK_ON = const AndroidInAppWebViewForceDark._internal(2); static const FORCE_DARK_ON = const AndroidInAppWebViewForceDark._internal(2);
...@@ -745,19 +858,25 @@ class AndroidInAppWebViewLayoutAlgorithm { ...@@ -745,19 +858,25 @@ class AndroidInAppWebViewLayoutAlgorithm {
final String _value; final String _value;
const AndroidInAppWebViewLayoutAlgorithm._internal(this._value); const AndroidInAppWebViewLayoutAlgorithm._internal(this._value);
static AndroidInAppWebViewLayoutAlgorithm fromValue(String value) { static AndroidInAppWebViewLayoutAlgorithm fromValue(String value) {
return (["NORMAL", "TEXT_AUTOSIZING"].contains(value)) ? AndroidInAppWebViewLayoutAlgorithm._internal(value) : null; return (["NORMAL", "TEXT_AUTOSIZING"].contains(value))
? AndroidInAppWebViewLayoutAlgorithm._internal(value)
: null;
} }
String toValue() => _value; String toValue() => _value;
@override @override
String toString() => _value; String toString() => _value;
///NORMAL means no rendering changes. This is the recommended choice for maximum compatibility across different platforms and Android versions. ///NORMAL means no rendering changes. This is the recommended choice for maximum compatibility across different platforms and Android versions.
static const NORMAL = const AndroidInAppWebViewLayoutAlgorithm._internal("NORMAL"); static const NORMAL =
const AndroidInAppWebViewLayoutAlgorithm._internal("NORMAL");
///TEXT_AUTOSIZING boosts font size of paragraphs based on heuristics to make the text readable when viewing a wide-viewport layout in the overview mode. ///TEXT_AUTOSIZING boosts font size of paragraphs based on heuristics to make the text readable when viewing a wide-viewport layout in the overview mode.
///It is recommended to enable zoom support [AndroidInAppWebViewOptions.supportZoom] when using this mode. ///It is recommended to enable zoom support [AndroidInAppWebViewOptions.supportZoom] when using this mode.
/// ///
///**NOTE**: available on Android 19+. ///**NOTE**: available on Android 19+.
static const TEXT_AUTOSIZING = const AndroidInAppWebViewLayoutAlgorithm._internal("TEXT_AUTOSIZING"); static const TEXT_AUTOSIZING =
const AndroidInAppWebViewLayoutAlgorithm._internal("TEXT_AUTOSIZING");
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -776,10 +895,11 @@ class AndroidInAppWebViewMixedContentMode { ...@@ -776,10 +895,11 @@ class AndroidInAppWebViewMixedContentMode {
return AndroidInAppWebViewMixedContentMode._internal(value); return AndroidInAppWebViewMixedContentMode._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "MIXED_CONTENT_NEVER_ALLOW"; return "MIXED_CONTENT_NEVER_ALLOW";
case 2: case 2:
...@@ -792,16 +912,21 @@ class AndroidInAppWebViewMixedContentMode { ...@@ -792,16 +912,21 @@ class AndroidInAppWebViewMixedContentMode {
///In this mode, the WebView will allow a secure origin to load content from any other origin, even if that origin is insecure. ///In this mode, the WebView will allow a secure origin to load content from any other origin, even if that origin is insecure.
///This is the least secure mode of operation for the WebView, and where possible apps should not set this mode. ///This is the least secure mode of operation for the WebView, and where possible apps should not set this mode.
static const MIXED_CONTENT_ALWAYS_ALLOW = const AndroidInAppWebViewMixedContentMode._internal(0); static const MIXED_CONTENT_ALWAYS_ALLOW =
const AndroidInAppWebViewMixedContentMode._internal(0);
///In this mode, the WebView will not allow a secure origin to load content from an insecure origin. ///In this mode, the WebView will not allow a secure origin to load content from an insecure origin.
///This is the preferred and most secure mode of operation for the WebView and apps are strongly advised to use this mode. ///This is the preferred and most secure mode of operation for the WebView and apps are strongly advised to use this mode.
static const MIXED_CONTENT_NEVER_ALLOW = const AndroidInAppWebViewMixedContentMode._internal(1); static const MIXED_CONTENT_NEVER_ALLOW =
const AndroidInAppWebViewMixedContentMode._internal(1);
///In this mode, the WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content. ///In this mode, the WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content.
///Some insecure content may be allowed to be loaded by a secure origin and other types of content will be blocked. ///Some insecure content may be allowed to be loaded by a secure origin and other types of content will be blocked.
///The types of content are allowed or blocked may change release to release and are not explicitly defined. ///The types of content are allowed or blocked may change release to release and are not explicitly defined.
///This mode is intended to be used by apps that are not in control of the content that they render but desire to operate in a reasonably secure environment. ///This mode is intended to be used by apps that are not in control of the content that they render but desire to operate in a reasonably secure environment.
///For highest security, apps are recommended to use [AndroidInAppWebViewMixedContentMode.MIXED_CONTENT_NEVER_ALLOW]. ///For highest security, apps are recommended to use [AndroidInAppWebViewMixedContentMode.MIXED_CONTENT_NEVER_ALLOW].
static const MIXED_CONTENT_COMPATIBILITY_MODE = const AndroidInAppWebViewMixedContentMode._internal(2); static const MIXED_CONTENT_COMPATIBILITY_MODE =
const AndroidInAppWebViewMixedContentMode._internal(2);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -818,10 +943,11 @@ class IosInAppWebViewSelectionGranularity { ...@@ -818,10 +943,11 @@ class IosInAppWebViewSelectionGranularity {
return IosInAppWebViewSelectionGranularity._internal(value); return IosInAppWebViewSelectionGranularity._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "CHARACTER"; return "CHARACTER";
case 0: case 0:
...@@ -832,8 +958,10 @@ class IosInAppWebViewSelectionGranularity { ...@@ -832,8 +958,10 @@ class IosInAppWebViewSelectionGranularity {
///Selection granularity varies automatically based on the selection. ///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. ///Selection endpoints can be placed at any character boundary.
static const CHARACTER = const IosInAppWebViewSelectionGranularity._internal(1); static const CHARACTER =
const IosInAppWebViewSelectionGranularity._internal(1);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -848,31 +976,61 @@ class IosInAppWebViewDataDetectorTypes { ...@@ -848,31 +976,61 @@ class IosInAppWebViewDataDetectorTypes {
final String _value; final String _value;
const IosInAppWebViewDataDetectorTypes._internal(this._value); const IosInAppWebViewDataDetectorTypes._internal(this._value);
static IosInAppWebViewDataDetectorTypes fromValue(String value) { static IosInAppWebViewDataDetectorTypes fromValue(String value) {
return (["NONE", "PHONE_NUMBER", "LINK", "ADDRESS", "CALENDAR_EVENT", "TRACKING_NUMBER", return ([
"TRACKING_NUMBER", "FLIGHT_NUMBER", "LOOKUP_SUGGESTION", "SPOTLIGHT_SUGGESTION", "ALL"].contains(value)) ? IosInAppWebViewDataDetectorTypes._internal(value) : null; "NONE",
"PHONE_NUMBER",
"LINK",
"ADDRESS",
"CALENDAR_EVENT",
"TRACKING_NUMBER",
"TRACKING_NUMBER",
"FLIGHT_NUMBER",
"LOOKUP_SUGGESTION",
"SPOTLIGHT_SUGGESTION",
"ALL"
].contains(value))
? IosInAppWebViewDataDetectorTypes._internal(value)
: null;
} }
String toValue() => _value; String toValue() => _value;
@override @override
String toString() => _value; String toString() => _value;
///No detection is performed. ///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. ///Phone numbers are detected and turned into links.
static const PHONE_NUMBER = const IosInAppWebViewDataDetectorTypes._internal("PHONE_NUMBER"); static const PHONE_NUMBER =
const IosInAppWebViewDataDetectorTypes._internal("PHONE_NUMBER");
///URLs in text are detected and turned into links. ///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. ///Addresses are detected and turned into links.
static const ADDRESS = const IosInAppWebViewDataDetectorTypes._internal("ADDRESS"); static const ADDRESS =
const IosInAppWebViewDataDetectorTypes._internal("ADDRESS");
///Dates and times that are in the future are detected and turned into links. ///Dates and times that are in the future are detected and turned into links.
static const CALENDAR_EVENT = const IosInAppWebViewDataDetectorTypes._internal("CALENDAR_EVENT"); static const CALENDAR_EVENT =
const IosInAppWebViewDataDetectorTypes._internal("CALENDAR_EVENT");
///Tracking numbers are detected and turned into links. ///Tracking numbers are detected and turned into links.
static const TRACKING_NUMBER = const IosInAppWebViewDataDetectorTypes._internal("TRACKING_NUMBER"); static const TRACKING_NUMBER =
const IosInAppWebViewDataDetectorTypes._internal("TRACKING_NUMBER");
///Flight numbers are detected and turned into links. ///Flight numbers are detected and turned into links.
static const FLIGHT_NUMBER = const IosInAppWebViewDataDetectorTypes._internal("FLIGHT_NUMBER"); static const FLIGHT_NUMBER =
const IosInAppWebViewDataDetectorTypes._internal("FLIGHT_NUMBER");
///Lookup suggestions are detected and turned into links. ///Lookup suggestions are detected and turned into links.
static const LOOKUP_SUGGESTION = const IosInAppWebViewDataDetectorTypes._internal("LOOKUP_SUGGESTION"); static const LOOKUP_SUGGESTION =
const IosInAppWebViewDataDetectorTypes._internal("LOOKUP_SUGGESTION");
///Spotlight suggestions are detected and turned into links. ///Spotlight suggestions are detected and turned into links.
static const SPOTLIGHT_SUGGESTION = const IosInAppWebViewDataDetectorTypes._internal("SPOTLIGHT_SUGGESTION"); static const 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. ///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");
...@@ -891,10 +1049,11 @@ class InAppWebViewUserPreferredContentMode { ...@@ -891,10 +1049,11 @@ class InAppWebViewUserPreferredContentMode {
return InAppWebViewUserPreferredContentMode._internal(value); return InAppWebViewUserPreferredContentMode._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "MOBILE"; return "MOBILE";
case 2: case 2:
...@@ -906,11 +1065,15 @@ class InAppWebViewUserPreferredContentMode { ...@@ -906,11 +1065,15 @@ class InAppWebViewUserPreferredContentMode {
} }
///The recommended content mode for the current platform. ///The recommended content mode for the current platform.
static const RECOMMENDED = const InAppWebViewUserPreferredContentMode._internal(0); static const RECOMMENDED =
const InAppWebViewUserPreferredContentMode._internal(0);
///Represents content targeting mobile browsers. ///Represents content targeting mobile browsers.
static const MOBILE = const InAppWebViewUserPreferredContentMode._internal(1); static const MOBILE = const InAppWebViewUserPreferredContentMode._internal(1);
///Represents content targeting desktop browsers. ///Represents content targeting desktop browsers.
static const DESKTOP = const InAppWebViewUserPreferredContentMode._internal(2); static const DESKTOP =
const InAppWebViewUserPreferredContentMode._internal(2);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -927,10 +1090,11 @@ class IosWebViewOptionsPresentationStyle { ...@@ -927,10 +1090,11 @@ class IosWebViewOptionsPresentationStyle {
return IosWebViewOptionsPresentationStyle._internal(value); return IosWebViewOptionsPresentationStyle._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "PAGE_SHEET"; return "PAGE_SHEET";
case 2: case 2:
...@@ -956,27 +1120,43 @@ class IosWebViewOptionsPresentationStyle { ...@@ -956,27 +1120,43 @@ class IosWebViewOptionsPresentationStyle {
} }
///A presentation style in which the presented view covers the screen. ///A presentation style in which the presented view covers the screen.
static const FULL_SCREEN = const IosWebViewOptionsPresentationStyle._internal(0); static const FULL_SCREEN =
const IosWebViewOptionsPresentationStyle._internal(0);
///A presentation style that partially covers the underlying content. ///A presentation style that partially covers the underlying content.
static const PAGE_SHEET = const IosWebViewOptionsPresentationStyle._internal(1); static const PAGE_SHEET =
const IosWebViewOptionsPresentationStyle._internal(1);
///A presentation style that displays the content centered in the screen. ///A presentation style that displays the content centered in the screen.
static const FORM_SHEET = const IosWebViewOptionsPresentationStyle._internal(2); static const FORM_SHEET =
const IosWebViewOptionsPresentationStyle._internal(2);
///A presentation style where the content is displayed over another view controller’s content. ///A presentation style where the content is displayed over another view controller’s content.
static const CURRENT_CONTEXT = const IosWebViewOptionsPresentationStyle._internal(3); static const CURRENT_CONTEXT =
const IosWebViewOptionsPresentationStyle._internal(3);
///A custom view presentation style that is managed by a custom presentation controller and one or more custom animator objects. ///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. ///A view presentation style in which the presented view covers the screen.
static const OVER_FULL_SCREEN = const IosWebViewOptionsPresentationStyle._internal(5); static const OVER_FULL_SCREEN =
const IosWebViewOptionsPresentationStyle._internal(5);
///A presentation style where the content is displayed over another view controller’s content. ///A presentation style where the content is displayed over another view controller’s content.
static const OVER_CURRENT_CONTEXT = const IosWebViewOptionsPresentationStyle._internal(6); static const OVER_CURRENT_CONTEXT =
const IosWebViewOptionsPresentationStyle._internal(6);
///A presentation style where the content is displayed in a popover view. ///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. ///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. ///The default presentation style chosen by the system.
/// ///
///**NOTE**: available on iOS 13.0+. ///**NOTE**: available on iOS 13.0+.
static const AUTOMATIC = const IosWebViewOptionsPresentationStyle._internal(9); static const AUTOMATIC =
const IosWebViewOptionsPresentationStyle._internal(9);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -993,10 +1173,11 @@ class IosWebViewOptionsTransitionStyle { ...@@ -993,10 +1173,11 @@ class IosWebViewOptionsTransitionStyle {
return IosWebViewOptionsTransitionStyle._internal(value); return IosWebViewOptionsTransitionStyle._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "FLIP_HORIZONTAL"; return "FLIP_HORIZONTAL";
case 2: case 2:
...@@ -1011,18 +1192,25 @@ class IosWebViewOptionsTransitionStyle { ...@@ -1011,18 +1192,25 @@ class IosWebViewOptionsTransitionStyle {
///When the view controller is presented, its view slides up from the bottom of the screen. ///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. ///On dismissal, the view slides back down. This is the default transition style.
static const COVER_VERTICAL = const IosWebViewOptionsTransitionStyle._internal(0); static const COVER_VERTICAL =
const IosWebViewOptionsTransitionStyle._internal(0);
///When the view controller is presented, the current view initiates a horizontal 3D flip from right-to-left, ///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. ///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. ///On dismissal, the flip occurs from left-to-right, returning to the original view.
static const FLIP_HORIZONTAL = const IosWebViewOptionsTransitionStyle._internal(1); static const FLIP_HORIZONTAL =
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. ///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. ///On dismissal, a similar type of cross-fade is used to return to the original view.
static const CROSS_DISSOLVE = const IosWebViewOptionsTransitionStyle._internal(2); static const CROSS_DISSOLVE =
const IosWebViewOptionsTransitionStyle._internal(2);
///When the view controller is presented, one corner of the current view curls up to reveal the presented view underneath. ///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. ///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. ///A view controller presented using this transition is itself prevented from presenting any additional view controllers.
static const PARTIAL_CURL = const IosWebViewOptionsTransitionStyle._internal(3); static const PARTIAL_CURL =
const IosWebViewOptionsTransitionStyle._internal(3);
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -1041,10 +1229,11 @@ class IosSafariOptionsDismissButtonStyle { ...@@ -1041,10 +1229,11 @@ class IosSafariOptionsDismissButtonStyle {
return IosSafariOptionsDismissButtonStyle._internal(value); return IosSafariOptionsDismissButtonStyle._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "CLOSE"; return "CLOSE";
case 2: case 2:
...@@ -1057,8 +1246,10 @@ class IosSafariOptionsDismissButtonStyle { ...@@ -1057,8 +1246,10 @@ class IosSafariOptionsDismissButtonStyle {
///Makes the button title the localized string "Done". ///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". ///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". ///Makes the button title the localized string "Cancel".
static const CANCEL = const IosSafariOptionsDismissButtonStyle._internal(2); static const CANCEL = const IosSafariOptionsDismissButtonStyle._internal(2);
...@@ -1072,36 +1263,50 @@ class IosSafariOptionsDismissButtonStyle { ...@@ -1072,36 +1263,50 @@ class IosSafariOptionsDismissButtonStyle {
class InAppWebViewWidgetOptions { class InAppWebViewWidgetOptions {
///Cross-platform options. ///Cross-platform options.
InAppWebViewOptions inAppWebViewOptions; InAppWebViewOptions inAppWebViewOptions;
///Android-specific options. ///Android-specific options.
AndroidInAppWebViewOptions androidInAppWebViewOptions; AndroidInAppWebViewOptions androidInAppWebViewOptions;
///iOS-specific options. ///iOS-specific options.
IosInAppWebViewOptions iosInAppWebViewOptions; IosInAppWebViewOptions iosInAppWebViewOptions;
InAppWebViewWidgetOptions({this.inAppWebViewOptions, this.androidInAppWebViewOptions, this.iosInAppWebViewOptions}); InAppWebViewWidgetOptions(
{this.inAppWebViewOptions,
this.androidInAppWebViewOptions,
this.iosInAppWebViewOptions});
} }
///InAppBrowserClassOptions class represents the options that can be used for an [InAppBrowser] WebView. ///InAppBrowserClassOptions class represents the options that can be used for an [InAppBrowser] WebView.
class InAppBrowserClassOptions { class InAppBrowserClassOptions {
///Cross-platform options. ///Cross-platform options.
InAppBrowserOptions inAppBrowserOptions; InAppBrowserOptions inAppBrowserOptions;
///Android-specific options. ///Android-specific options.
AndroidInAppBrowserOptions androidInAppBrowserOptions; AndroidInAppBrowserOptions androidInAppBrowserOptions;
///iOS-specific options. ///iOS-specific options.
IosInAppBrowserOptions iosInAppBrowserOptions; IosInAppBrowserOptions iosInAppBrowserOptions;
///WebView options. ///WebView options.
InAppWebViewWidgetOptions inAppWebViewWidgetOptions; InAppWebViewWidgetOptions inAppWebViewWidgetOptions;
InAppBrowserClassOptions({this.inAppBrowserOptions, this.androidInAppBrowserOptions, this.iosInAppBrowserOptions, this.inAppWebViewWidgetOptions}); InAppBrowserClassOptions(
{this.inAppBrowserOptions,
this.androidInAppBrowserOptions,
this.iosInAppBrowserOptions,
this.inAppWebViewWidgetOptions});
} }
///ChromeSafariBrowserClassOptions class represents the options that can be used for an [ChromeSafariBrowser] window. ///ChromeSafariBrowserClassOptions class represents the options that can be used for an [ChromeSafariBrowser] window.
class ChromeSafariBrowserClassOptions { class ChromeSafariBrowserClassOptions {
///Android-specific options. ///Android-specific options.
AndroidChromeCustomTabsOptions androidChromeCustomTabsOptions; AndroidChromeCustomTabsOptions androidChromeCustomTabsOptions;
///iOS-specific options. ///iOS-specific options.
IosSafariOptions iosSafariOptions; IosSafariOptions iosSafariOptions;
ChromeSafariBrowserClassOptions({this.androidChromeCustomTabsOptions, this.iosSafariOptions}); ChromeSafariBrowserClassOptions(
{this.androidChromeCustomTabsOptions, this.iosSafariOptions});
} }
///AjaxRequestAction class used by [AjaxRequest] class. ///AjaxRequestAction class used by [AjaxRequest] class.
...@@ -1112,6 +1317,7 @@ class AjaxRequestAction { ...@@ -1112,6 +1317,7 @@ class AjaxRequestAction {
///Aborts the current [AjaxRequest]. ///Aborts the current [AjaxRequest].
static const ABORT = const AjaxRequestAction._internal(0); static const ABORT = const AjaxRequestAction._internal(0);
///Proceeds with the current [AjaxRequest]. ///Proceeds with the current [AjaxRequest].
static const PROCEED = const AjaxRequestAction._internal(1); static const PROCEED = const AjaxRequestAction._internal(1);
...@@ -1136,24 +1342,34 @@ class AjaxRequestEventType { ...@@ -1136,24 +1342,34 @@ class AjaxRequestEventType {
final String _value; final String _value;
const AjaxRequestEventType._internal(this._value); const AjaxRequestEventType._internal(this._value);
static AjaxRequestEventType fromValue(String value) { static AjaxRequestEventType fromValue(String value) {
return (["loadstart", "load", "loadend", "progress", "error", "abort"].contains(value)) ? AjaxRequestEventType._internal(value) : null; return (["loadstart", "load", "loadend", "progress", "error", "abort"]
.contains(value))
? AjaxRequestEventType._internal(value)
: null;
} }
String toValue() => _value; String toValue() => _value;
String toString() => _value; String toString() => _value;
///The LOADSTART event is fired when a request has started to load data. ///The LOADSTART event is fired when a request has started to load data.
static const LOADSTART = const AjaxRequestEventType._internal("loadstart"); static const LOADSTART = const AjaxRequestEventType._internal("loadstart");
///The LOAD event is fired when an `XMLHttpRequest` transaction completes successfully. ///The LOAD event is fired when an `XMLHttpRequest` transaction completes successfully.
static const LOAD = const AjaxRequestEventType._internal("load"); static const LOAD = const AjaxRequestEventType._internal("load");
///The LOADEND event is fired when a request has completed, whether successfully (after [AjaxRequestEventType.LOAD]) or ///The LOADEND event is fired when a request has completed, whether successfully (after [AjaxRequestEventType.LOAD]) or
///unsuccessfully (after [AjaxRequestEventType.ABORT] or [AjaxRequestEventType.ERROR]). ///unsuccessfully (after [AjaxRequestEventType.ABORT] or [AjaxRequestEventType.ERROR]).
static const LOADEND = const AjaxRequestEventType._internal("loadend"); static const LOADEND = const AjaxRequestEventType._internal("loadend");
///The PROGRESS event is fired periodically when a request receives more data. ///The PROGRESS event is fired periodically when a request receives more data.
static const PROGRESS = const AjaxRequestEventType._internal("progress"); static const PROGRESS = const AjaxRequestEventType._internal("progress");
///The ERROR event is fired when the request encountered an error. ///The ERROR event is fired when the request encountered an error.
static const ERROR = const AjaxRequestEventType._internal("error"); static const ERROR = const AjaxRequestEventType._internal("error");
///The ABORT event is fired when a request has been aborted. ///The ABORT event is fired when a request has been aborted.
static const ABORT = const AjaxRequestEventType._internal("abort"); static const ABORT = const AjaxRequestEventType._internal("abort");
///The TIMEOUT event is fired when progression is terminated due to preset time expiring. ///The TIMEOUT event is fired when progression is terminated due to preset time expiring.
static const TIMEOUT = const AjaxRequestEventType._internal("timeout"); static const TIMEOUT = const AjaxRequestEventType._internal("timeout");
...@@ -1167,13 +1383,16 @@ class AjaxRequestEventType { ...@@ -1167,13 +1383,16 @@ class AjaxRequestEventType {
class AjaxRequestEvent { class AjaxRequestEvent {
///Event type. ///Event type.
AjaxRequestEventType type; AjaxRequestEventType type;
///Is a Boolean flag indicating if the total work to be done, and the amount of work already done, by the underlying process is calculable. ///Is a Boolean flag indicating if the total work to be done, and the amount of work already done, by the underlying process is calculable.
///In other words, it tells if the progress is measurable or not. ///In other words, it tells if the progress is measurable or not.
bool lengthComputable; bool lengthComputable;
///Is an integer representing the amount of work already performed by the underlying process. ///Is an integer representing the amount of work already performed by the underlying process.
///The ratio of work done can be calculated with the property and [AjaxRequestEvent.total]. ///The ratio of work done can be calculated with the property and [AjaxRequestEvent.total].
///When downloading a resource using HTTP, this only represent the part of the content itself, not headers and other overhead. ///When downloading a resource using HTTP, this only represent the part of the content itself, not headers and other overhead.
int loaded; int loaded;
///Is an integer representing the total amount of work that the underlying process is in the progress of performing. ///Is an integer representing the total amount of work that the underlying process is in the progress of performing.
///When downloading a resource using HTTP, this only represent the content itself, not headers and other overhead. ///When downloading a resource using HTTP, this only represent the content itself, not headers and other overhead.
int total; int total;
...@@ -1190,10 +1409,11 @@ class AjaxRequestReadyState { ...@@ -1190,10 +1409,11 @@ class AjaxRequestReadyState {
return AjaxRequestReadyState._internal(value); return AjaxRequestReadyState._internal(value);
return null; return null;
} }
int toValue() => _value; int toValue() => _value;
@override @override
String toString() { String toString() {
switch(_value) { switch (_value) {
case 1: case 1:
return "OPENED"; return "OPENED";
case 2: case 2:
...@@ -1210,12 +1430,16 @@ class AjaxRequestReadyState { ...@@ -1210,12 +1430,16 @@ class AjaxRequestReadyState {
///Client has been created. `XMLHttpRequest.open()` not called yet. ///Client has been created. `XMLHttpRequest.open()` not called yet.
static const UNSENT = const AjaxRequestReadyState._internal(0); static const UNSENT = const AjaxRequestReadyState._internal(0);
///`XMLHttpRequest.open()` has been called. ///`XMLHttpRequest.open()` has been called.
static const OPENED = const AjaxRequestReadyState._internal(1); static const OPENED = const AjaxRequestReadyState._internal(1);
///`XMLHttpRequest.send()` has been called, and [AjaxRequest.headers] and [AjaxRequest.status] are available. ///`XMLHttpRequest.send()` has been called, and [AjaxRequest.headers] and [AjaxRequest.status] are available.
static const HEADERS_RECEIVED = const AjaxRequestReadyState._internal(2); static const HEADERS_RECEIVED = const AjaxRequestReadyState._internal(2);
///Downloading; [AjaxRequest.responseText] holds partial data. ///Downloading; [AjaxRequest.responseText] holds partial data.
static const LOADING = const AjaxRequestReadyState._internal(3); static const LOADING = const AjaxRequestReadyState._internal(3);
///The operation is complete. ///The operation is complete.
static const DONE = const AjaxRequestReadyState._internal(4); static const DONE = const AjaxRequestReadyState._internal(4);
...@@ -1254,56 +1478,91 @@ class AjaxRequestHeaders { ...@@ -1254,56 +1478,91 @@ class AjaxRequestHeaders {
class AjaxRequest { class AjaxRequest {
///Data passed as a parameter to the `XMLHttpRequest.send()` method. ///Data passed as a parameter to the `XMLHttpRequest.send()` method.
dynamic data; dynamic data;
///The HTTP request method of the `XMLHttpRequest` request. ///The HTTP request method of the `XMLHttpRequest` request.
String method; String method;
///The URL of the `XMLHttpRequest` request. ///The URL of the `XMLHttpRequest` request.
String url; String url;
///An optional Boolean parameter, defaulting to true, indicating whether or not the request is performed asynchronously. ///An optional Boolean parameter, defaulting to true, indicating whether or not the request is performed asynchronously.
bool isAsync; bool isAsync;
///The optional user name to use for authentication purposes; by default, this is the null value. ///The optional user name to use for authentication purposes; by default, this is the null value.
String user; String user;
///The optional password to use for authentication purposes; by default, this is the null value. ///The optional password to use for authentication purposes; by default, this is the null value.
String password; String password;
///The XMLHttpRequest.withCredentials property is a Boolean that indicates whether or not cross-site Access-Control requests ///The XMLHttpRequest.withCredentials property is a Boolean that indicates whether or not cross-site Access-Control requests
///should be made using credentials such as cookies, authorization headers or TLS client certificates. ///should be made using credentials such as cookies, authorization headers or TLS client certificates.
///Setting withCredentials has no effect on same-site requests. ///Setting withCredentials has no effect on same-site requests.
///In addition, this flag is also used to indicate when cookies are to be ignored in the response. The default is false. ///In addition, this flag is also used to indicate when cookies are to be ignored in the response. The default is false.
bool withCredentials; bool withCredentials;
///The HTTP request headers. ///The HTTP request headers.
AjaxRequestHeaders headers; AjaxRequestHeaders headers;
///The state of the `XMLHttpRequest` request. ///The state of the `XMLHttpRequest` request.
AjaxRequestReadyState readyState; AjaxRequestReadyState readyState;
///The numerical HTTP [status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) of the `XMLHttpRequest`'s response. ///The numerical HTTP [status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) of the `XMLHttpRequest`'s response.
int status; int status;
///The serialized URL of the response or the empty string if the URL is null. ///The serialized URL of the response or the empty string if the URL is null.
///If the URL is returned, any URL fragment present in the URL will be stripped away. ///If the URL is returned, any URL fragment present in the URL will be stripped away.
///The value of responseURL will be the final URL obtained after any redirects. ///The value of responseURL will be the final URL obtained after any redirects.
String responseURL; String responseURL;
///It is an enumerated string value specifying the type of data contained in the response. ///It is an enumerated string value specifying the type of data contained in the response.
///It also lets the author change the [response type](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType). ///It also lets the author change the [response type](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType).
///If an empty string is set as the value of responseType, the default value of text is used. ///If an empty string is set as the value of responseType, the default value of text is used.
String responseType; String responseType;
///The response's body content. The content-type depends on the [AjaxRequest.reponseType]. ///The response's body content. The content-type depends on the [AjaxRequest.reponseType].
dynamic response; dynamic response;
///The text received from a server following a request being sent. ///The text received from a server following a request being sent.
String responseText; String responseText;
///The HTML or XML string retrieved by the request or null if the request was unsuccessful, has not yet been sent, or if the data can't be parsed as XML or HTML. ///The HTML or XML string retrieved by the request or null if the request was unsuccessful, has not yet been sent, or if the data can't be parsed as XML or HTML.
String responseXML; String responseXML;
///A String containing the response's status message as returned by the HTTP server. ///A String containing the response's status message as returned by the HTTP server.
///Unlike [AjaxRequest.status] which indicates a numerical status code, this property contains the text of the response status, such as "OK" or "Not Found". ///Unlike [AjaxRequest.status] which indicates a numerical status code, this property contains the text of the response status, such as "OK" or "Not Found".
///If the request's readyState is in [AjaxRequestReadyState.UNSENT] or [AjaxRequestReadyState.OPENED] state, the value of statusText will be an empty string. ///If the request's readyState is in [AjaxRequestReadyState.UNSENT] or [AjaxRequestReadyState.OPENED] state, the value of statusText will be an empty string.
///If the server response doesn't explicitly specify a status text, statusText will assume the default value "OK". ///If the server response doesn't explicitly specify a status text, statusText will assume the default value "OK".
String statusText; String statusText;
///All the response headers or returns null if no response has been received. If a network error happened, an empty string is returned. ///All the response headers or returns null if no response has been received. If a network error happened, an empty string is returned.
Map<dynamic, dynamic> responseHeaders; Map<dynamic, dynamic> responseHeaders;
///Event type of the `XMLHttpRequest` request. ///Event type of the `XMLHttpRequest` request.
AjaxRequestEvent event; AjaxRequestEvent event;
///Indicates the [AjaxRequestAction] that can be used to control the `XMLHttpRequest` request. ///Indicates the [AjaxRequestAction] that can be used to control the `XMLHttpRequest` request.
AjaxRequestAction action; AjaxRequestAction action;
AjaxRequest({this.data, this.method, this.url, this.isAsync, this.user, this.password, AjaxRequest(
this.withCredentials, this.headers, this.readyState, this.status, this.responseURL, this.responseType, {this.data,
this.response, this.responseText, this.responseXML, this.statusText, this.responseHeaders, this.event, this.action = AjaxRequestAction.PROCEED}); this.method,
this.url,
this.isAsync,
this.user,
this.password,
this.withCredentials,
this.headers,
this.readyState,
this.status,
this.responseURL,
this.responseType,
this.response,
this.responseText,
this.responseXML,
this.statusText,
this.responseHeaders,
this.event,
this.action = AjaxRequestAction.PROCEED});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
...@@ -1341,6 +1600,7 @@ class FetchRequestAction { ...@@ -1341,6 +1600,7 @@ class FetchRequestAction {
///Aborts the fetch request. ///Aborts the fetch request.
static const ABORT = const FetchRequestAction._internal(0); static const ABORT = const FetchRequestAction._internal(0);
///Proceeds with the fetch request. ///Proceeds with the fetch request.
static const PROCEED = const FetchRequestAction._internal(1); static const PROCEED = const FetchRequestAction._internal(1);
...@@ -1358,9 +1618,7 @@ class FetchRequestCredential { ...@@ -1358,9 +1618,7 @@ class FetchRequestCredential {
FetchRequestCredential({this.type}); FetchRequestCredential({this.type});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {"type": type};
"type": type
};
} }
} }
...@@ -1369,7 +1627,7 @@ class FetchRequestCredentialDefault extends FetchRequestCredential { ...@@ -1369,7 +1627,7 @@ class FetchRequestCredentialDefault extends FetchRequestCredential {
///The value of the credentials. ///The value of the credentials.
String value; String value;
FetchRequestCredentialDefault({type, this.value}): super(type: type); FetchRequestCredentialDefault({type, this.value}) : super(type: type);
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
...@@ -1383,16 +1641,22 @@ class FetchRequestCredentialDefault extends FetchRequestCredential { ...@@ -1383,16 +1641,22 @@ class FetchRequestCredentialDefault extends FetchRequestCredential {
class FetchRequestFederatedCredential extends FetchRequestCredential { class FetchRequestFederatedCredential extends FetchRequestCredential {
///Credential's identifier. ///Credential's identifier.
dynamic id; dynamic id;
///The name associated with a credential. It should be a human-readable, public name. ///The name associated with a credential. It should be a human-readable, public name.
String name; String name;
///Credential's federated identity protocol. ///Credential's federated identity protocol.
String protocol; String protocol;
///Credential's federated identity provider. ///Credential's federated identity provider.
String provider; String provider;
///URL pointing to an image for an icon. This image is intended for display in a credential chooser. The URL must be accessible without authentication. ///URL pointing to an image for an icon. This image is intended for display in a credential chooser. The URL must be accessible without authentication.
String iconURL; String iconURL;
FetchRequestFederatedCredential({type, this.id, this.name, this.protocol, this.provider, this.iconURL}): super(type: type); FetchRequestFederatedCredential(
{type, this.id, this.name, this.protocol, this.provider, this.iconURL})
: super(type: type);
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
...@@ -1410,14 +1674,19 @@ class FetchRequestFederatedCredential extends FetchRequestCredential { ...@@ -1410,14 +1674,19 @@ class FetchRequestFederatedCredential extends FetchRequestCredential {
class FetchRequestPasswordCredential extends FetchRequestCredential { class FetchRequestPasswordCredential extends FetchRequestCredential {
///Credential's identifier. ///Credential's identifier.
dynamic id; dynamic id;
///The name associated with a credential. It should be a human-readable, public name. ///The name associated with a credential. It should be a human-readable, public name.
String name; String name;
///The password of the credential. ///The password of the credential.
String password; String password;
///URL pointing to an image for an icon. This image is intended for display in a credential chooser. The URL must be accessible without authentication. ///URL pointing to an image for an icon. This image is intended for display in a credential chooser. The URL must be accessible without authentication.
String iconURL; String iconURL;
FetchRequestPasswordCredential({type, this.id, this.name, this.password, this.iconURL}): super(type: type); FetchRequestPasswordCredential(
{type, this.id, this.name, this.password, this.iconURL})
: super(type: type);
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
...@@ -1434,33 +1703,56 @@ class FetchRequestPasswordCredential extends FetchRequestCredential { ...@@ -1434,33 +1703,56 @@ class FetchRequestPasswordCredential extends FetchRequestCredential {
class FetchRequest { class FetchRequest {
///The URL of the request. ///The URL of the request.
String url; String url;
///The HTTP request method used of the request. ///The HTTP request method used of the request.
String method; String method;
///The HTTP request headers. ///The HTTP request headers.
Map<String, dynamic> headers; Map<String, dynamic> headers;
///Body of the request. ///Body of the request.
Uint8List body; Uint8List body;
///The mode used by the request. ///The mode used by the request.
String mode; String mode;
///The request credentials used by the request. ///The request credentials used by the request.
FetchRequestCredential credentials; FetchRequestCredential credentials;
///The cache mode used by the request. ///The cache mode used by the request.
String cache; String cache;
///The redirect mode used by the request. ///The redirect mode used by the request.
String redirect; String redirect;
///A String specifying no-referrer, client, or a URL. ///A String specifying no-referrer, client, or a URL.
String referrer; String referrer;
///The value of the referer HTTP header. ///The value of the referer HTTP header.
String referrerPolicy; String referrerPolicy;
///Contains the subresource integrity value of the request. ///Contains the subresource integrity value of the request.
String integrity; String integrity;
///The keepalive option used to allow the request to outlive the page. ///The keepalive option used to allow the request to outlive the page.
bool keepalive; bool keepalive;
///Indicates the [FetchRequestAction] that can be used to control the request. ///Indicates the [FetchRequestAction] that can be used to control the request.
FetchRequestAction action; FetchRequestAction action;
FetchRequest({this.url, this.method, this.headers, this.body, this.mode, this.credentials, FetchRequest(
this.cache, this.redirect, this.referrer, this.referrerPolicy, this.integrity, this.keepalive, {this.url,
this.method,
this.headers,
this.body,
this.mode,
this.credentials,
this.cache,
this.redirect,
this.referrer,
this.referrerPolicy,
this.integrity,
this.keepalive,
this.action = FetchRequestAction.PROCEED}); this.action = FetchRequestAction.PROCEED});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
...@@ -1485,16 +1777,27 @@ class FetchRequest { ...@@ -1485,16 +1777,27 @@ class FetchRequest {
return this.toMap(); return this.toMap();
} }
static FetchRequestCredential createFetchRequestCredentialFromMap(credentialsMap) { static FetchRequestCredential createFetchRequestCredentialFromMap(
credentialsMap) {
if (credentialsMap != null) { if (credentialsMap != null) {
if (credentialsMap["type"] == "default") { if (credentialsMap["type"] == "default") {
return FetchRequestCredentialDefault(type: credentialsMap["type"], value: credentialsMap["value"]); return FetchRequestCredentialDefault(
type: credentialsMap["type"], value: credentialsMap["value"]);
} else if (credentialsMap["type"] == "federated") { } else if (credentialsMap["type"] == "federated") {
return FetchRequestFederatedCredential(type: credentialsMap["type"], id: credentialsMap["id"], name: credentialsMap["name"], return FetchRequestFederatedCredential(
protocol: credentialsMap["protocol"], provider: credentialsMap["provider"], iconURL: credentialsMap["iconURL"]); type: credentialsMap["type"],
id: credentialsMap["id"],
name: credentialsMap["name"],
protocol: credentialsMap["protocol"],
provider: credentialsMap["provider"],
iconURL: credentialsMap["iconURL"]);
} else if (credentialsMap["type"] == "password") { } else if (credentialsMap["type"] == "password") {
return FetchRequestPasswordCredential(type: credentialsMap["type"], id: credentialsMap["id"], name: credentialsMap["name"], return FetchRequestPasswordCredential(
password: credentialsMap["password"], iconURL: credentialsMap["iconURL"]); type: credentialsMap["type"],
id: credentialsMap["id"],
name: credentialsMap["name"],
password: credentialsMap["password"],
iconURL: credentialsMap["iconURL"]);
} }
} }
return null; return null;
...@@ -1506,20 +1809,38 @@ class ContentBlockerTriggerResourceType { ...@@ -1506,20 +1809,38 @@ class ContentBlockerTriggerResourceType {
final String _value; final String _value;
const ContentBlockerTriggerResourceType._internal(this._value); const ContentBlockerTriggerResourceType._internal(this._value);
static ContentBlockerTriggerResourceType fromValue(String value) { static ContentBlockerTriggerResourceType fromValue(String value) {
return (["document", "image", "style-sheet", "script", "font", return ([
"media", "svg-document", "raw"].contains(value)) ? ContentBlockerTriggerResourceType._internal(value) : null; "document",
"image",
"style-sheet",
"script",
"font",
"media",
"svg-document",
"raw"
].contains(value))
? ContentBlockerTriggerResourceType._internal(value)
: null;
} }
String toValue() => _value; String toValue() => _value;
@override @override
String toString() => _value; String toString() => _value;
static const DOCUMENT = const ContentBlockerTriggerResourceType._internal('document'); static const DOCUMENT =
static const IMAGE = const ContentBlockerTriggerResourceType._internal('image'); const ContentBlockerTriggerResourceType._internal('document');
static const STYLE_SHEET = const ContentBlockerTriggerResourceType._internal('style-sheet'); static const IMAGE =
static const SCRIPT = const ContentBlockerTriggerResourceType._internal('script'); const ContentBlockerTriggerResourceType._internal('image');
static const STYLE_SHEET =
const ContentBlockerTriggerResourceType._internal('style-sheet');
static const SCRIPT =
const ContentBlockerTriggerResourceType._internal('script');
static const FONT = const ContentBlockerTriggerResourceType._internal('font'); static const FONT = const ContentBlockerTriggerResourceType._internal('font');
static const MEDIA = const ContentBlockerTriggerResourceType._internal('media'); static const MEDIA =
static const SVG_DOCUMENT = const ContentBlockerTriggerResourceType._internal('svg-document'); const ContentBlockerTriggerResourceType._internal('media');
static const SVG_DOCUMENT =
const ContentBlockerTriggerResourceType._internal('svg-document');
///Any untyped load ///Any untyped load
static const RAW = const ContentBlockerTriggerResourceType._internal('raw'); static const RAW = const ContentBlockerTriggerResourceType._internal('raw');
...@@ -1529,22 +1850,27 @@ class ContentBlockerTriggerResourceType { ...@@ -1529,22 +1850,27 @@ class ContentBlockerTriggerResourceType {
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///ContentBlockerTriggerLoadType class represents the possible load type for a [ContentBlockerTrigger]. ///ContentBlockerTriggerLoadType class represents the possible load type for a [ContentBlockerTrigger].
class ContentBlockerTriggerLoadType { class ContentBlockerTriggerLoadType {
final String _value; final String _value;
const ContentBlockerTriggerLoadType._internal(this._value); const ContentBlockerTriggerLoadType._internal(this._value);
static ContentBlockerTriggerLoadType fromValue(String value) { static ContentBlockerTriggerLoadType fromValue(String value) {
return (["first-party", "third-party"].contains(value)) ? ContentBlockerTriggerLoadType._internal(value) : null; return (["first-party", "third-party"].contains(value))
? ContentBlockerTriggerLoadType._internal(value)
: null;
} }
String toValue() => _value; String toValue() => _value;
@override @override
String toString() => _value; String toString() => _value;
///FIRST_PARTY is triggered only if the resource has the same scheme, domain, and port as the main page resource. ///FIRST_PARTY is triggered only if the resource has the same scheme, domain, and port as the main page resource.
static const FIRST_PARTY = const ContentBlockerTriggerLoadType._internal('first-party'); static const FIRST_PARTY =
const ContentBlockerTriggerLoadType._internal('first-party');
///THIRD_PARTY is triggered if the resource is not from the same domain as the main page resource. ///THIRD_PARTY is triggered if the resource is not from the same domain as the main page resource.
static const THIRD_PARTY = const ContentBlockerTriggerLoadType._internal('third-party'); static const THIRD_PARTY =
const ContentBlockerTriggerLoadType._internal('third-party');
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -1557,20 +1883,27 @@ class ContentBlockerActionType { ...@@ -1557,20 +1883,27 @@ class ContentBlockerActionType {
final String _value; final String _value;
const ContentBlockerActionType._internal(this._value); const ContentBlockerActionType._internal(this._value);
static ContentBlockerActionType fromValue(String value) { static ContentBlockerActionType fromValue(String value) {
return (["block", "css-display-none", "make-https"].contains(value)) ? ContentBlockerActionType._internal(value) : null; return (["block", "css-display-none", "make-https"].contains(value))
? ContentBlockerActionType._internal(value)
: null;
} }
String toValue() => _value; String toValue() => _value;
@override @override
String toString() => _value; String toString() => _value;
///Stops loading of the resource. If the resource was cached, the cache is ignored. ///Stops loading of the resource. If the resource was cached, the cache is ignored.
static const BLOCK = const ContentBlockerActionType._internal('block'); static const BLOCK = const ContentBlockerActionType._internal('block');
///Hides elements of the page based on a CSS selector. A selector field contains the selector list. Any matching element has its display property set to none, which hides it. ///Hides elements of the page based on a CSS selector. A selector field contains the selector list. Any matching element has its display property set to none, which hides it.
/// ///
///**NOTE**: on Android, JavaScript must be enabled. ///**NOTE**: on Android, JavaScript must be enabled.
static const CSS_DISPLAY_NONE = const ContentBlockerActionType._internal('css-display-none'); static const CSS_DISPLAY_NONE =
const ContentBlockerActionType._internal('css-display-none');
///Changes a URL from http to https. URLs with a specified (nondefault) port and links using other protocols are unaffected. ///Changes a URL from http to https. URLs with a specified (nondefault) port and links using other protocols are unaffected.
static const MAKE_HTTPS = const ContentBlockerActionType._internal('make-https'); static const MAKE_HTTPS =
const ContentBlockerActionType._internal('make-https');
bool operator ==(value) => value == _value; bool operator ==(value) => value == _value;
...@@ -1582,6 +1915,7 @@ class ContentBlockerActionType { ...@@ -1582,6 +1915,7 @@ class ContentBlockerActionType {
class Cookie { class Cookie {
///The name; ///The name;
String name; String name;
///The value; ///The value;
dynamic value; dynamic value;
...@@ -1596,6 +1930,7 @@ class PermissionRequestResponseAction { ...@@ -1596,6 +1930,7 @@ class PermissionRequestResponseAction {
///Denies the request. ///Denies the request.
static const DENY = const PermissionRequestResponseAction._internal(0); static const DENY = const PermissionRequestResponseAction._internal(0);
///Grants origin the permission to access the given resources. ///Grants origin the permission to access the given resources.
static const GRANT = const PermissionRequestResponseAction._internal(1); static const GRANT = const PermissionRequestResponseAction._internal(1);
...@@ -1609,15 +1944,15 @@ class PermissionRequestResponseAction { ...@@ -1609,15 +1944,15 @@ class PermissionRequestResponseAction {
class PermissionRequestResponse { class PermissionRequestResponse {
///Resources granted to be accessed by origin. ///Resources granted to be accessed by origin.
List<String> resources; List<String> resources;
///Indicate the [PermissionRequestResponseAction] to take in response of a permission request. ///Indicate the [PermissionRequestResponseAction] to take in response of a permission request.
PermissionRequestResponseAction action; PermissionRequestResponseAction action;
PermissionRequestResponse({this.resources = const [], this.action = PermissionRequestResponseAction.DENY}); PermissionRequestResponse(
{this.resources = const [],
this.action = PermissionRequestResponseAction.DENY});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {"resources": resources, "action": action?.toValue()};
"resources": resources,
"action": action?.toValue()
};
} }
} }
...@@ -4,6 +4,7 @@ import 'content_blocker.dart'; ...@@ -4,6 +4,7 @@ import 'content_blocker.dart';
import 'types.dart'; import 'types.dart';
class AndroidOptions {} class AndroidOptions {}
class IosOptions {} class IosOptions {}
class WebViewOptions { class WebViewOptions {
...@@ -37,84 +38,129 @@ class ChromeSafariBrowserOptions { ...@@ -37,84 +38,129 @@ class ChromeSafariBrowserOptions {
} }
///This class represents all the cross-platform WebView options available. ///This class represents all the cross-platform WebView options available.
class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOptions, IosOptions { class InAppWebViewOptions
implements WebViewOptions, BrowserOptions, AndroidOptions, IosOptions {
///Set to `true` to be able to listen at the [shouldOverrideUrlLoading] event. The default value is `false`. ///Set to `true` to be able to listen at the [shouldOverrideUrlLoading] event. The default value is `false`.
bool useShouldOverrideUrlLoading; bool useShouldOverrideUrlLoading;
///Set to `true` to be able to listen at the [onLoadResource] event. The default value is `false`. ///Set to `true` to be able to listen at the [onLoadResource] event. The default value is `false`.
bool useOnLoadResource; bool useOnLoadResource;
///Set to `true` to be able to listen at the [onDownloadStart] event. The default value is `false`. ///Set to `true` to be able to listen at the [onDownloadStart] event. The default value is `false`.
bool useOnDownloadStart; bool useOnDownloadStart;
///Set to `true` to be able to listen at the [onTargetBlank] event. The default value is `false`. ///Set to `true` to be able to listen at the [onTargetBlank] event. The default value is `false`.
bool useOnTargetBlank; bool useOnTargetBlank;
///Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`. ///Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`.
bool clearCache; bool clearCache;
///Sets the user-agent for the WebView. ///Sets the user-agent for the WebView.
/// ///
///**NOTE**: available on iOS 9.0+. ///**NOTE**: available on iOS 9.0+.
String userAgent; String userAgent;
///Append to the existing user-agent. Setting userAgent will override this. ///Append to the existing user-agent. Setting userAgent will override this.
/// ///
///**NOTE**: available on Android 17+ and on iOS 9.0+. ///**NOTE**: available on Android 17+ and on iOS 9.0+.
String applicationNameForUserAgent; String applicationNameForUserAgent;
///Set to `true` to enable JavaScript. The default value is `true`. ///Set to `true` to enable JavaScript. The default value is `true`.
bool javaScriptEnabled; bool javaScriptEnabled;
///Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application. ///Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application.
///This flag can be enabled in order to facilitate debugging of web layouts and JavaScript code running inside WebViews. The default is `false`. ///This flag can be enabled in order to facilitate debugging of web layouts and JavaScript code running inside WebViews. The default is `false`.
/// ///
///**NOTE**: on iOS the debugging mode is always enabled. ///**NOTE**: on iOS the debugging mode is always enabled.
bool debuggingEnabled; bool debuggingEnabled;
///Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`. ///Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`.
bool javaScriptCanOpenWindowsAutomatically; bool javaScriptCanOpenWindowsAutomatically;
///Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`. ///Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`.
/// ///
///**NOTE**: available on iOS 10.0+. ///**NOTE**: available on iOS 10.0+.
bool mediaPlaybackRequiresUserGesture; bool mediaPlaybackRequiresUserGesture;
///Sets the minimum font size. The default value is `8` for Android, `0` for iOS. ///Sets the minimum font size. The default value is `8` for Android, `0` for iOS.
int minimumFontSize; int minimumFontSize;
///Define whether the vertical scrollbar should be drawn or not. The default value is `true`. ///Define whether the vertical scrollbar should be drawn or not. The default value is `true`.
bool verticalScrollBarEnabled; bool verticalScrollBarEnabled;
///Define whether the horizontal scrollbar should be drawn or not. The default value is `true`. ///Define whether the horizontal scrollbar should be drawn or not. The default value is `true`.
bool horizontalScrollBarEnabled; bool horizontalScrollBarEnabled;
///List of custom schemes that the WebView must handle. Use the [onLoadResourceCustomScheme] event to intercept resource requests with custom scheme. ///List of custom schemes that the WebView must handle. Use the [onLoadResourceCustomScheme] event to intercept resource requests with custom scheme.
/// ///
///**NOTE**: available on iOS 11.0+. ///**NOTE**: available on iOS 11.0+.
List<String> resourceCustomSchemes; List<String> resourceCustomSchemes;
///List of [ContentBlocker] that are a set of rules used to block content in the browser window. ///List of [ContentBlocker] that are a set of rules used to block content in the browser window.
/// ///
///**NOTE**: available on iOS 11.0+. ///**NOTE**: available on iOS 11.0+.
List<ContentBlocker> contentBlockers; List<ContentBlocker> contentBlockers;
///Sets the content mode that the WebView needs to use when loading and rendering a webpage. The default value is [InAppWebViewUserPreferredContentMode.RECOMMENDED]. ///Sets the content mode that the WebView needs to use when loading and rendering a webpage. The default value is [InAppWebViewUserPreferredContentMode.RECOMMENDED].
/// ///
///**NOTE**: available on iOS 13.0+. ///**NOTE**: available on iOS 13.0+.
InAppWebViewUserPreferredContentMode preferredContentMode; InAppWebViewUserPreferredContentMode preferredContentMode;
///Set to `true` to be able to listen at the [shouldInterceptAjaxRequest] event. The default value is `false`. ///Set to `true` to be able to listen at the [shouldInterceptAjaxRequest] event. The default value is `false`.
bool useShouldInterceptAjaxRequest; bool useShouldInterceptAjaxRequest;
///Set to `true` to be able to listen at the [shouldInterceptFetchRequest] event. The default value is `false`. ///Set to `true` to be able to listen at the [shouldInterceptFetchRequest] event. The default value is `false`.
bool useShouldInterceptFetchRequest; bool useShouldInterceptFetchRequest;
///Set to `true` to open a browser window with incognito mode. The default value is `false`. ///Set to `true` to open a browser window with incognito mode. The default value is `false`.
/// ///
///**NOTE**: available on iOS 9.0+. ///**NOTE**: available on iOS 9.0+.
bool incognito; bool incognito;
///Sets whether WebView should use browser caching. The default value is `true`. ///Sets whether WebView should use browser caching. The default value is `true`.
/// ///
///**NOTE**: available on iOS 9.0+. ///**NOTE**: available on iOS 9.0+.
bool cacheEnabled; bool cacheEnabled;
///Set to `true` to make the background of the WebView transparent. If your app has a dark theme, this can prevent a white flash on initialization. The default value is `false`. ///Set to `true` to make the background of the WebView transparent. If your app has a dark theme, this can prevent a white flash on initialization. The default value is `false`.
bool transparentBackground; bool transparentBackground;
///Set to `true` to disable vertical scroll. The default value is `false`. ///Set to `true` to disable vertical scroll. The default value is `false`.
bool disableVerticalScroll; bool disableVerticalScroll;
///Set to `true` to disable horizontal scroll. The default value is `false`. ///Set to `true` to disable horizontal scroll. The default value is `false`.
bool disableHorizontalScroll; bool disableHorizontalScroll;
InAppWebViewOptions({this.useShouldOverrideUrlLoading = false, this.useOnLoadResource = false, this.useOnDownloadStart = false, this.useOnTargetBlank = false, InAppWebViewOptions(
this.clearCache = false, this.userAgent = "", this.applicationNameForUserAgent = "", this.javaScriptEnabled = true, this.debuggingEnabled = false, this.javaScriptCanOpenWindowsAutomatically = false, {this.useShouldOverrideUrlLoading = false,
this.mediaPlaybackRequiresUserGesture = true, this.minimumFontSize, this.verticalScrollBarEnabled = true, this.horizontalScrollBarEnabled = true, this.useOnLoadResource = false,
this.resourceCustomSchemes = const [], this.contentBlockers = const [], this.preferredContentMode = InAppWebViewUserPreferredContentMode.RECOMMENDED, this.useOnDownloadStart = false,
this.useShouldInterceptAjaxRequest = false, this.useShouldInterceptFetchRequest = false, this.incognito = false, this.cacheEnabled = true, this.transparentBackground = false, this.useOnTargetBlank = false,
this.disableVerticalScroll = false, this.disableHorizontalScroll = false}) { this.clearCache = false,
this.userAgent = "",
this.applicationNameForUserAgent = "",
this.javaScriptEnabled = true,
this.debuggingEnabled = false,
this.javaScriptCanOpenWindowsAutomatically = false,
this.mediaPlaybackRequiresUserGesture = true,
this.minimumFontSize,
this.verticalScrollBarEnabled = true,
this.horizontalScrollBarEnabled = true,
this.resourceCustomSchemes = const [],
this.contentBlockers = const [],
this.preferredContentMode =
InAppWebViewUserPreferredContentMode.RECOMMENDED,
this.useShouldInterceptAjaxRequest = false,
this.useShouldInterceptFetchRequest = false,
this.incognito = false,
this.cacheEnabled = true,
this.transparentBackground = false,
this.disableVerticalScroll = false,
this.disableHorizontalScroll = false}) {
if (this.minimumFontSize == null) if (this.minimumFontSize == null)
this.minimumFontSize = Platform.isAndroid ? 8 : 0; this.minimumFontSize = Platform.isAndroid ? 8 : 0;
assert(!this.resourceCustomSchemes.contains("http") && !this.resourceCustomSchemes.contains("https")); assert(!this.resourceCustomSchemes.contains("http") &&
!this.resourceCustomSchemes.contains("https"));
} }
@override @override
...@@ -134,7 +180,8 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti ...@@ -134,7 +180,8 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
"applicationNameForUserAgent": applicationNameForUserAgent, "applicationNameForUserAgent": applicationNameForUserAgent,
"javaScriptEnabled": javaScriptEnabled, "javaScriptEnabled": javaScriptEnabled,
"debuggingEnabled": debuggingEnabled, "debuggingEnabled": debuggingEnabled,
"javaScriptCanOpenWindowsAutomatically": javaScriptCanOpenWindowsAutomatically, "javaScriptCanOpenWindowsAutomatically":
javaScriptCanOpenWindowsAutomatically,
"mediaPlaybackRequiresUserGesture": mediaPlaybackRequiresUserGesture, "mediaPlaybackRequiresUserGesture": mediaPlaybackRequiresUserGesture,
"verticalScrollBarEnabled": verticalScrollBarEnabled, "verticalScrollBarEnabled": verticalScrollBarEnabled,
"horizontalScrollBarEnabled": horizontalScrollBarEnabled, "horizontalScrollBarEnabled": horizontalScrollBarEnabled,
...@@ -151,15 +198,14 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti ...@@ -151,15 +198,14 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
}; };
} }
@override
static InAppWebViewOptions fromMap(Map<String, dynamic> map) { static InAppWebViewOptions fromMap(Map<String, dynamic> map) {
List<ContentBlocker> contentBlockers = []; List<ContentBlocker> contentBlockers = [];
List<dynamic> contentBlockersMapList = map["contentBlockers"]; List<dynamic> contentBlockersMapList = map["contentBlockers"];
if (contentBlockersMapList != null) { if (contentBlockersMapList != null) {
contentBlockersMapList.forEach((contentBlocker) { contentBlockersMapList.forEach((contentBlocker) {
contentBlockers.add(ContentBlocker.fromMap( contentBlockers.add(ContentBlocker.fromMap(
Map<dynamic, Map<dynamic, dynamic>>.from(Map<dynamic, dynamic>.from(contentBlocker)) Map<dynamic, Map<dynamic, dynamic>>.from(
)); Map<dynamic, dynamic>.from(contentBlocker))));
}); });
} }
...@@ -173,15 +219,22 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti ...@@ -173,15 +219,22 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
options.applicationNameForUserAgent = map["applicationNameForUserAgent"]; options.applicationNameForUserAgent = map["applicationNameForUserAgent"];
options.javaScriptEnabled = map["javaScriptEnabled"]; options.javaScriptEnabled = map["javaScriptEnabled"];
options.debuggingEnabled = map["debuggingEnabled"]; options.debuggingEnabled = map["debuggingEnabled"];
options.javaScriptCanOpenWindowsAutomatically = map["javaScriptCanOpenWindowsAutomatically"]; options.javaScriptCanOpenWindowsAutomatically =
options.mediaPlaybackRequiresUserGesture = map["mediaPlaybackRequiresUserGesture"]; map["javaScriptCanOpenWindowsAutomatically"];
options.mediaPlaybackRequiresUserGesture =
map["mediaPlaybackRequiresUserGesture"];
options.verticalScrollBarEnabled = map["verticalScrollBarEnabled"]; options.verticalScrollBarEnabled = map["verticalScrollBarEnabled"];
options.horizontalScrollBarEnabled = map["horizontalScrollBarEnabled"]; options.horizontalScrollBarEnabled = map["horizontalScrollBarEnabled"];
options.resourceCustomSchemes = List<String>.from(map["resourceCustomSchemes"] ?? []); options.resourceCustomSchemes =
List<String>.from(map["resourceCustomSchemes"] ?? []);
options.contentBlockers = contentBlockers; options.contentBlockers = contentBlockers;
options.preferredContentMode = InAppWebViewUserPreferredContentMode.fromValue(map["preferredContentMode"]); options.preferredContentMode =
options.useShouldInterceptAjaxRequest = map["useShouldInterceptAjaxRequest"]; InAppWebViewUserPreferredContentMode.fromValue(
options.useShouldInterceptFetchRequest = map["useShouldInterceptFetchRequest"]; map["preferredContentMode"]);
options.useShouldInterceptAjaxRequest =
map["useShouldInterceptAjaxRequest"];
options.useShouldInterceptFetchRequest =
map["useShouldInterceptFetchRequest"];
options.incognito = map["incognito"]; options.incognito = map["incognito"];
options.cacheEnabled = map["cacheEnabled"]; options.cacheEnabled = map["cacheEnabled"];
options.transparentBackground = map["transparentBackground"]; options.transparentBackground = map["transparentBackground"];
...@@ -192,92 +245,124 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti ...@@ -192,92 +245,124 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
} }
///This class represents all the Android-only WebView options available. ///This class represents all the Android-only WebView options available.
class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOptions { class AndroidInAppWebViewOptions
implements WebViewOptions, BrowserOptions, AndroidOptions {
///Sets the text zoom of the page in percent. The default value is `100`. ///Sets the text zoom of the page in percent. The default value is `100`.
int textZoom; int textZoom;
///Set to `true` to have the session cookie cache cleared before the new window is opened. ///Set to `true` to have the session cookie cache cleared before the new window is opened.
bool clearSessionCache; bool clearSessionCache;
///Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `false`. ///Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `false`.
bool builtInZoomControls; bool builtInZoomControls;
///Set to `true` if the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. The default value is `false`. ///Set to `true` if the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. The default value is `false`.
bool displayZoomControls; bool displayZoomControls;
///Set to `false` if the WebView should not support zooming using its on-screen zoom controls and gestures. The default value is `true`. ///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; 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 `false`.
bool databaseEnabled; bool databaseEnabled;
///Set to `true` if you want the DOM storage API is enabled. The default value is `false`. ///Set to `true` if you want the DOM storage API is enabled. The default value is `false`.
bool domStorageEnabled; bool domStorageEnabled;
///Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. ///Set to `true` if the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport.
///When the value of the setting is false, the layout width is always set to the width of the WebView control in device-independent (CSS) pixels. ///When the value of the setting is false, the layout width is always set to the width of the WebView control in device-independent (CSS) pixels.
///When the value is true and the page contains the viewport meta tag, the value of the width specified in the tag is used. ///When the value is true and the page contains the viewport meta tag, the value of the width specified in the tag is used.
///If the page does not contain the tag or does not provide a width, then a wide viewport will be used. The default value is `true`. ///If the page does not contain the tag or does not provide a width, then a wide viewport will be used. The default value is `true`.
bool useWideViewPort; bool useWideViewPort;
///Sets whether Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links. ///Sets whether Safe Browsing is enabled. Safe Browsing allows WebView to protect against malware and phishing attacks by verifying the links.
///Safe Browsing is enabled by default for devices which support it. ///Safe Browsing is enabled by default for devices which support it.
/// ///
///**NOTE**: available on Android 26+. ///**NOTE**: available on Android 26+.
bool safeBrowsingEnabled; bool safeBrowsingEnabled;
///Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin. ///Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin.
/// ///
///**NOTE**: available on Android 21+. ///**NOTE**: available on Android 21+.
AndroidInAppWebViewMixedContentMode mixedContentMode; AndroidInAppWebViewMixedContentMode mixedContentMode;
///Enables or disables content URL access within WebView. Content URL access allows WebView to load content from a content provider installed in the system. The default value is `true`. ///Enables or disables content URL access within WebView. Content URL access allows WebView to load content from a content provider installed in the system. The default value is `true`.
bool allowContentAccess; bool allowContentAccess;
///Enables or disables file access within WebView. Note that this enables or disables file system access only. ///Enables or disables file access within WebView. Note that this enables or disables file system access only.
///Assets and resources are still accessible using \file:///android_asset` and `file:///android_res`. The default value is `true`. ///Assets and resources are still accessible using \file:///android_asset` and `file:///android_res`. The default value is `true`.
bool allowFileAccess; bool allowFileAccess;
///Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from other file scheme URLs. ///Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from other file scheme URLs.
///Note that the value of this setting is ignored if the value of [allowFileAccessFromFileURLs] is `true`. ///Note that the value of this setting is ignored if the value of [allowFileAccessFromFileURLs] is `true`.
///Note too, that this setting affects only JavaScript access to file scheme resources. The default value is `false`. ///Note too, that this setting affects only JavaScript access to file scheme resources. The default value is `false`.
bool allowFileAccessFromFileURLs; bool allowFileAccessFromFileURLs;
///Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from any origin. ///Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from any origin.
///Note that this setting affects only JavaScript access to file scheme resources. ///Note that this setting affects only JavaScript access to file scheme resources.
///This includes access to content from other file scheme URLs. The default value is `false`. ///This includes access to content from other file scheme URLs. The default value is `false`.
bool allowUniversalAccessFromFileURLs; bool allowUniversalAccessFromFileURLs;
///Sets the path to the Application Caches files. In order for the Application Caches API to be enabled, this option must be set a path to which the application can write. ///Sets the path to the Application Caches files. In order for the Application Caches API to be enabled, this option must be set a path to which the application can write.
///This option is used one time: repeated calls are ignored. ///This option is used one time: repeated calls are ignored.
String appCachePath; String appCachePath;
///Sets whether the WebView should not load image resources from the network (resources accessed via http and https URI schemes). The default value is `false`. ///Sets whether the WebView should not load image resources from the network (resources accessed via http and https URI schemes). The default value is `false`.
bool blockNetworkImage; bool blockNetworkImage;
///Sets whether the WebView should not load resources from the network. The default value is `false`. ///Sets whether the WebView should not load resources from the network. The default value is `false`.
bool blockNetworkLoads; bool blockNetworkLoads;
///Overrides the way the cache is used. The way the cache is used is based on the navigation type. For a normal page load, the cache is checked and content is re-validated as needed. ///Overrides the way the cache is used. The way the cache is used is based on the navigation type. For a normal page load, the cache is checked and content is re-validated as needed.
///When navigating back, content is not revalidated, instead the content is just retrieved from the cache. The default value is [AndroidInAppWebViewCacheMode.LOAD_DEFAULT]. ///When navigating back, content is not revalidated, instead the content is just retrieved from the cache. The default value is [AndroidInAppWebViewCacheMode.LOAD_DEFAULT].
AndroidInAppWebViewCacheMode cacheMode; AndroidInAppWebViewCacheMode cacheMode;
///Sets the cursive font family name. The default value is `"cursive"`. ///Sets the cursive font family name. The default value is `"cursive"`.
String cursiveFontFamily; String cursiveFontFamily;
///Sets the default fixed font size. The default value is `16`. ///Sets the default fixed font size. The default value is `16`.
int defaultFixedFontSize; int defaultFixedFontSize;
///Sets the default font size. The default value is `16`. ///Sets the default font size. The default value is `16`.
int defaultFontSize; int defaultFontSize;
///Sets the default text encoding name to use when decoding html pages. The default value is `"UTF-8"`. ///Sets the default text encoding name to use when decoding html pages. The default value is `"UTF-8"`.
String defaultTextEncodingName; String defaultTextEncodingName;
///Disables the action mode menu items according to menuItems flag. ///Disables the action mode menu items according to menuItems flag.
/// ///
///**NOTE**: available on Android 24+. ///**NOTE**: available on Android 24+.
AndroidInAppWebViewModeMenuItem disabledActionModeMenuItems; AndroidInAppWebViewModeMenuItem disabledActionModeMenuItems;
///Sets the fantasy font family name. The default value is `"fantasy"`. ///Sets the fantasy font family name. The default value is `"fantasy"`.
String fantasyFontFamily; String fantasyFontFamily;
///Sets the fixed font family name. The default value is `"monospace"`. ///Sets the fixed font family name. The default value is `"monospace"`.
String fixedFontFamily; String fixedFontFamily;
///Set the force dark mode for this WebView. The default value is [AndroidInAppWebViewForceDark.FORCE_DARK_OFF]. ///Set the force dark mode for this WebView. The default value is [AndroidInAppWebViewForceDark.FORCE_DARK_OFF].
/// ///
///**NOTE**: available on Android 29+. ///**NOTE**: available on Android 29+.
AndroidInAppWebViewForceDark forceDark; AndroidInAppWebViewForceDark forceDark;
///Sets whether Geolocation API is enabled. The default value is `true`. ///Sets whether Geolocation API is enabled. The default value is `true`.
bool geolocationEnabled; bool geolocationEnabled;
///Sets the underlying layout algorithm. This will cause a re-layout of the WebView. ///Sets the underlying layout algorithm. This will cause a re-layout of the WebView.
AndroidInAppWebViewLayoutAlgorithm layoutAlgorithm; AndroidInAppWebViewLayoutAlgorithm layoutAlgorithm;
///Sets whether the WebView loads pages in overview mode, that is, zooms out the content to fit on screen by width. ///Sets whether the WebView loads pages in overview mode, that is, zooms out the content to fit on screen by width.
///This setting is taken into account when the content width is greater than the width of the WebView control, for example, when [useWideViewPort] is enabled. ///This setting is taken into account when the content width is greater than the width of the WebView control, for example, when [useWideViewPort] is enabled.
///The default value is `false`. ///The default value is `false`.
bool loadWithOverviewMode; bool loadWithOverviewMode;
///Sets whether the WebView should load image resources. Note that this method controls loading of all images, including those embedded using the data URI scheme. ///Sets whether the WebView should load image resources. Note that this method controls loading of all images, including those embedded using the data URI scheme.
///Note that if the value of this setting is changed from false to true, all images resources referenced by content currently displayed by the WebView are loaded automatically. ///Note that if the value of this setting is changed from false to true, all images resources referenced by content currently displayed by the WebView are loaded automatically.
///The default value is `true`. ///The default value is `true`.
bool loadsImagesAutomatically; bool loadsImagesAutomatically;
///Sets the minimum logical font size. The default is `8`. ///Sets the minimum logical font size. The default is `8`.
int minimumLogicalFontSize; int minimumLogicalFontSize;
///Sets the initial scale for this WebView. 0 means default. The behavior for the default scale depends on the state of [useWideViewPort] and [loadWithOverviewMode]. ///Sets the initial scale for this WebView. 0 means default. The behavior for the default scale depends on the state of [useWideViewPort] and [loadWithOverviewMode].
///If the content fits into the WebView control by width, then the zoom is set to 100%. For wide content, the behavior depends on the state of [loadWithOverviewMode]. ///If the content fits into the WebView control by width, then the zoom is set to 100%. For wide content, the behavior depends on the state of [loadWithOverviewMode].
///If its value is true, the content will be zoomed out to be fit by width into the WebView control, otherwise not. ///If its value is true, the content will be zoomed out to be fit by width into the WebView control, otherwise not.
...@@ -285,43 +370,82 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr ...@@ -285,43 +370,82 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr
///Please note that unlike the scale properties in the viewport meta tag, this method doesn't take the screen density into account. ///Please note that unlike the scale properties in the viewport meta tag, this method doesn't take the screen density into account.
///The default is `0`. ///The default is `0`.
int initialScale; int initialScale;
///Tells the WebView whether it needs to set a node. The default value is `true`. ///Tells the WebView whether it needs to set a node. The default value is `true`.
bool needInitialFocus; bool needInitialFocus;
///Sets whether this WebView should raster tiles when it is offscreen but attached to a window. ///Sets whether this WebView should raster tiles when it is offscreen but attached to a window.
///Turning this on can avoid rendering artifacts when animating an offscreen WebView on-screen. ///Turning this on can avoid rendering artifacts when animating an offscreen WebView on-screen.
///Offscreen WebViews in this mode use more memory. The default value is `false`. ///Offscreen WebViews in this mode use more memory. The default value is `false`.
/// ///
///**NOTE**: available on Android 23+. ///**NOTE**: available on Android 23+.
bool offscreenPreRaster; bool offscreenPreRaster;
///Sets the sans-serif font family name. The default value is `"sans-serif"`. ///Sets the sans-serif font family name. The default value is `"sans-serif"`.
String sansSerifFontFamily; String sansSerifFontFamily;
///Sets the serif font family name. The default value is `"sans-serif"`. ///Sets the serif font family name. The default value is `"sans-serif"`.
String serifFontFamily; String serifFontFamily;
///Sets the standard font family name. The default value is `"sans-serif"`. ///Sets the standard font family name. The default value is `"sans-serif"`.
String standardFontFamily; String standardFontFamily;
///Sets whether the WebView should save form data. In Android O, the platform has implemented a fully functional Autofill feature to store form data. ///Sets whether the WebView should save form data. In Android O, the platform has implemented a fully functional Autofill feature to store form data.
///Therefore, the Webview form data save feature is disabled. Note that the feature will continue to be supported on older versions of Android as before. ///Therefore, the Webview form data save feature is disabled. Note that the feature will continue to be supported on older versions of Android as before.
bool saveFormData; bool saveFormData;
///Boolean value to enable third party cookies in the WebView. ///Boolean value to enable third party cookies in the WebView.
///Used on Android Lollipop and above only as third party cookies are enabled by default on Android Kitkat and below and on iOS. ///Used on Android Lollipop and above only as third party cookies are enabled by default on Android Kitkat and below and on iOS.
///The default value is `true`. ///The default value is `true`.
/// ///
///**NOTE**: available on Android 21+. ///**NOTE**: available on Android 21+.
bool thirdPartyCookiesEnabled; bool thirdPartyCookiesEnabled;
///Boolean value to enable Hardware Acceleration in the WebView. ///Boolean value to enable Hardware Acceleration in the WebView.
///The default value is `true`. ///The default value is `true`.
bool hardwareAcceleration; bool hardwareAcceleration;
AndroidInAppWebViewOptions({this.textZoom = 100, this.clearSessionCache = false, this.builtInZoomControls = false, this.displayZoomControls = false, this.supportZoom = true, this.databaseEnabled = false, AndroidInAppWebViewOptions(
this.domStorageEnabled = false, this.useWideViewPort = true, this.safeBrowsingEnabled = true, this.mixedContentMode, {this.textZoom = 100,
this.allowContentAccess = true, this.allowFileAccess = true, this.allowFileAccessFromFileURLs = false, this.allowUniversalAccessFromFileURLs = false, this.clearSessionCache = false,
this.appCachePath, this.blockNetworkImage = false, this.blockNetworkLoads = false, this.cacheMode = AndroidInAppWebViewCacheMode.LOAD_DEFAULT, this.builtInZoomControls = false,
this.cursiveFontFamily = "cursive", this.defaultFixedFontSize = 16, this.defaultFontSize = 16, this.defaultTextEncodingName = "UTF-8", this.displayZoomControls = false,
this.disabledActionModeMenuItems, this.fantasyFontFamily = "fantasy", this.fixedFontFamily = "monospace", this.forceDark = AndroidInAppWebViewForceDark.FORCE_DARK_OFF, this.supportZoom = true,
this.geolocationEnabled = true, this.layoutAlgorithm, this.loadWithOverviewMode = true, this.loadsImagesAutomatically = true, this.databaseEnabled = false,
this.minimumLogicalFontSize = 8, this.needInitialFocus = true, this.offscreenPreRaster = false, this.sansSerifFontFamily = "sans-serif", this.serifFontFamily = "sans-serif", this.domStorageEnabled = false,
this.standardFontFamily = "sans-serif", this.saveFormData = true, this.thirdPartyCookiesEnabled = true, this.hardwareAcceleration = true, this.initialScale = 0 this.useWideViewPort = true,
}); this.safeBrowsingEnabled = true,
this.mixedContentMode,
this.allowContentAccess = true,
this.allowFileAccess = true,
this.allowFileAccessFromFileURLs = false,
this.allowUniversalAccessFromFileURLs = false,
this.appCachePath,
this.blockNetworkImage = false,
this.blockNetworkLoads = false,
this.cacheMode = AndroidInAppWebViewCacheMode.LOAD_DEFAULT,
this.cursiveFontFamily = "cursive",
this.defaultFixedFontSize = 16,
this.defaultFontSize = 16,
this.defaultTextEncodingName = "UTF-8",
this.disabledActionModeMenuItems,
this.fantasyFontFamily = "fantasy",
this.fixedFontFamily = "monospace",
this.forceDark = AndroidInAppWebViewForceDark.FORCE_DARK_OFF,
this.geolocationEnabled = true,
this.layoutAlgorithm,
this.loadWithOverviewMode = true,
this.loadsImagesAutomatically = true,
this.minimumLogicalFontSize = 8,
this.needInitialFocus = true,
this.offscreenPreRaster = false,
this.sansSerifFontFamily = "sans-serif",
this.serifFontFamily = "sans-serif",
this.standardFontFamily = "sans-serif",
this.saveFormData = true,
this.thirdPartyCookiesEnabled = true,
this.hardwareAcceleration = true,
this.initialScale = 0});
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
...@@ -369,7 +493,6 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr ...@@ -369,7 +493,6 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr
}; };
} }
@override
static AndroidInAppWebViewOptions fromMap(Map<String, dynamic> map) { static AndroidInAppWebViewOptions fromMap(Map<String, dynamic> map) {
AndroidInAppWebViewOptions options = new AndroidInAppWebViewOptions(); AndroidInAppWebViewOptions options = new AndroidInAppWebViewOptions();
options.textZoom = map["textZoom"]; options.textZoom = map["textZoom"];
...@@ -381,25 +504,32 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr ...@@ -381,25 +504,32 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr
options.domStorageEnabled = map["domStorageEnabled"]; options.domStorageEnabled = map["domStorageEnabled"];
options.useWideViewPort = map["useWideViewPort"]; options.useWideViewPort = map["useWideViewPort"];
options.safeBrowsingEnabled = map["safeBrowsingEnabled"]; options.safeBrowsingEnabled = map["safeBrowsingEnabled"];
options.mixedContentMode = AndroidInAppWebViewMixedContentMode.fromValue(map["mixedContentMode"]); options.mixedContentMode =
AndroidInAppWebViewMixedContentMode.fromValue(map["mixedContentMode"]);
options.allowContentAccess = map["allowContentAccess"]; options.allowContentAccess = map["allowContentAccess"];
options.allowFileAccess = map["allowFileAccess"]; options.allowFileAccess = map["allowFileAccess"];
options.allowFileAccessFromFileURLs = map["allowFileAccessFromFileURLs"]; options.allowFileAccessFromFileURLs = map["allowFileAccessFromFileURLs"];
options.allowUniversalAccessFromFileURLs = map["allowUniversalAccessFromFileURLs"]; options.allowUniversalAccessFromFileURLs =
map["allowUniversalAccessFromFileURLs"];
options.appCachePath = map["appCachePath"]; options.appCachePath = map["appCachePath"];
options.blockNetworkImage = map["blockNetworkImage"]; options.blockNetworkImage = map["blockNetworkImage"];
options.blockNetworkLoads = map["blockNetworkLoads"]; options.blockNetworkLoads = map["blockNetworkLoads"];
options.cacheMode = AndroidInAppWebViewCacheMode.fromValue(map["cacheMode"]); options.cacheMode =
AndroidInAppWebViewCacheMode.fromValue(map["cacheMode"]);
options.cursiveFontFamily = map["cursiveFontFamily"]; options.cursiveFontFamily = map["cursiveFontFamily"];
options.defaultFixedFontSize = map["defaultFixedFontSize"]; options.defaultFixedFontSize = map["defaultFixedFontSize"];
options.defaultFontSize = map["defaultFontSize"]; options.defaultFontSize = map["defaultFontSize"];
options.defaultTextEncodingName = map["defaultTextEncodingName"]; options.defaultTextEncodingName = map["defaultTextEncodingName"];
options.disabledActionModeMenuItems = AndroidInAppWebViewModeMenuItem.fromValue(map["disabledActionModeMenuItems"]); options.disabledActionModeMenuItems =
AndroidInAppWebViewModeMenuItem.fromValue(
map["disabledActionModeMenuItems"]);
options.fantasyFontFamily = map["fantasyFontFamily"]; options.fantasyFontFamily = map["fantasyFontFamily"];
options.fixedFontFamily = map["fixedFontFamily"]; options.fixedFontFamily = map["fixedFontFamily"];
options.forceDark = AndroidInAppWebViewForceDark.fromValue(map["forceDark"]); options.forceDark =
AndroidInAppWebViewForceDark.fromValue(map["forceDark"]);
options.geolocationEnabled = map["geolocationEnabled"]; options.geolocationEnabled = map["geolocationEnabled"];
options.layoutAlgorithm = AndroidInAppWebViewLayoutAlgorithm.fromValue(map["layoutAlgorithm"]); options.layoutAlgorithm =
AndroidInAppWebViewLayoutAlgorithm.fromValue(map["layoutAlgorithm"]);
options.loadWithOverviewMode = map["loadWithOverviewMode"]; options.loadWithOverviewMode = map["loadWithOverviewMode"];
options.loadsImagesAutomatically = map["loadsImagesAutomatically"]; options.loadsImagesAutomatically = map["loadsImagesAutomatically"];
options.minimumLogicalFontSize = map["minimumLogicalFontSize"]; options.minimumLogicalFontSize = map["minimumLogicalFontSize"];
...@@ -417,57 +547,79 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr ...@@ -417,57 +547,79 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr
} }
///This class represents all the iOS-only WebView options available. ///This class represents all the iOS-only WebView options available.
class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptions { 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`. ///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; bool disallowOverScroll;
///Set to `true` to allow a viewport meta tag to either disable or restrict the range of user scaling. The default value is `false`. ///Set to `true` to allow a viewport meta tag to either disable or restrict the range of user scaling. The default value is `false`.
bool enableViewportScale; bool enableViewportScale;
///Set to `true` if you want the WebView suppresses content rendering until it is fully loaded into memory. The default value is `false`. ///Set to `true` if you want the WebView suppresses content rendering until it is fully loaded into memory. The default value is `false`.
bool suppressesIncrementalRendering; bool suppressesIncrementalRendering;
///Set to `true` to allow AirPlay. The default value is `true`. ///Set to `true` to allow AirPlay. The default value is `true`.
bool allowsAirPlayForMediaPlayback; bool allowsAirPlayForMediaPlayback;
///Set to `true` to allow the horizontal swipe gestures trigger back-forward list navigations. The default value is `true`. ///Set to `true` to allow the horizontal swipe gestures trigger back-forward list navigations. The default value is `true`.
bool allowsBackForwardNavigationGestures; bool allowsBackForwardNavigationGestures;
///Set to `true` to allow that pressing on a link displays a preview of the destination for the link. The default value is `true`. ///Set to `true` to allow that pressing on a link displays a preview of the destination for the link. The default value is `true`.
/// ///
///**NOTE**: available on iOS 9.0+. ///**NOTE**: available on iOS 9.0+.
bool allowsLinkPreview; bool allowsLinkPreview;
///Set to `true` if you want that the WebView should always allow scaling of the webpage, regardless of the author's intent. ///Set to `true` if you want that the WebView should always allow scaling of the webpage, regardless of the author's intent.
///The ignoresViewportScaleLimits property overrides the `user-scalable` HTML property in a webpage. The default value is `false`. ///The ignoresViewportScaleLimits property overrides the `user-scalable` HTML property in a webpage. The default value is `false`.
bool ignoresViewportScaleLimits; bool ignoresViewportScaleLimits;
///Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls. ///Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls.
///For this to work, add the `webkit-playsinline` attribute to any `<video>` elements. The default value is `false`. ///For this to work, add the `webkit-playsinline` attribute to any `<video>` elements. The default value is `false`.
bool allowsInlineMediaPlayback; bool allowsInlineMediaPlayback;
///Set to `true` to allow HTML5 videos play picture-in-picture. The default value is `true`. ///Set to `true` to allow HTML5 videos play picture-in-picture. The default value is `true`.
/// ///
///**NOTE**: available on iOS 9.0+. ///**NOTE**: available on iOS 9.0+.
bool allowsPictureInPictureMediaPlayback; bool allowsPictureInPictureMediaPlayback;
///A Boolean value indicating whether warnings should be shown for suspected fraudulent content such as phishing or malware. ///A Boolean value indicating whether warnings should be shown for suspected fraudulent content such as phishing or malware.
///According to the official documentation, this feature is currently available in the following region: China. ///According to the official documentation, this feature is currently available in the following region: China.
///The default value is `true`. ///The default value is `true`.
/// ///
///**NOTE**: available on iOS 13.0+. ///**NOTE**: available on iOS 13.0+.
bool isFraudulentWebsiteWarningEnabled; bool isFraudulentWebsiteWarningEnabled;
///The level of granularity with which the user can interactively select content in the web view. ///The level of granularity with which the user can interactively select content in the web view.
///The default value is [IosInAppWebViewSelectionGranularity.DYNAMIC] ///The default value is [IosInAppWebViewSelectionGranularity.DYNAMIC]
IosInAppWebViewSelectionGranularity selectionGranularity; IosInAppWebViewSelectionGranularity selectionGranularity;
///Specifying a dataDetectoryTypes value adds interactivity to web content that matches the value. ///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]. ///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]. ///The default value is [IosInAppWebViewDataDetectorTypes.NONE].
/// ///
///**NOTE**: available on iOS 10.0+. ///**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. ///Set `true` if shared cookies from `HTTPCookieStorage.shared` should used for every load request in the WebView.
///The default value is `false`. ///The default value is `false`.
/// ///
///**NOTE**: available on iOS 11.0+. ///**NOTE**: available on iOS 11.0+.
bool sharedCookiesEnabled; bool sharedCookiesEnabled;
IosInAppWebViewOptions({this.disallowOverScroll = false, this.enableViewportScale = false, this.suppressesIncrementalRendering = false, this.allowsAirPlayForMediaPlayback = true, IosInAppWebViewOptions(
this.allowsBackForwardNavigationGestures = true, this.allowsLinkPreview = true, this.ignoresViewportScaleLimits = false, this.allowsInlineMediaPlayback = false, {this.disallowOverScroll = false,
this.allowsPictureInPictureMediaPlayback = true, this.isFraudulentWebsiteWarningEnabled = true, this.enableViewportScale = false,
this.selectionGranularity = IosInAppWebViewSelectionGranularity.DYNAMIC, this.dataDetectorTypes = const [IosInAppWebViewDataDetectorTypes.NONE], this.sharedCookiesEnabled = false this.suppressesIncrementalRendering = false,
}); this.allowsAirPlayForMediaPlayback = true,
this.allowsBackForwardNavigationGestures = true,
this.allowsLinkPreview = true,
this.ignoresViewportScaleLimits = false,
this.allowsInlineMediaPlayback = false,
this.allowsPictureInPictureMediaPlayback = true,
this.isFraudulentWebsiteWarningEnabled = true,
this.selectionGranularity = IosInAppWebViewSelectionGranularity.DYNAMIC,
this.dataDetectorTypes = const [IosInAppWebViewDataDetectorTypes.NONE],
this.sharedCookiesEnabled = false});
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
...@@ -481,11 +633,13 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio ...@@ -481,11 +633,13 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio
"enableViewportScale": enableViewportScale, "enableViewportScale": enableViewportScale,
"suppressesIncrementalRendering": suppressesIncrementalRendering, "suppressesIncrementalRendering": suppressesIncrementalRendering,
"allowsAirPlayForMediaPlayback": allowsAirPlayForMediaPlayback, "allowsAirPlayForMediaPlayback": allowsAirPlayForMediaPlayback,
"allowsBackForwardNavigationGestures": allowsBackForwardNavigationGestures, "allowsBackForwardNavigationGestures":
allowsBackForwardNavigationGestures,
"allowsLinkPreview": allowsLinkPreview, "allowsLinkPreview": allowsLinkPreview,
"ignoresViewportScaleLimits": ignoresViewportScaleLimits, "ignoresViewportScaleLimits": ignoresViewportScaleLimits,
"allowsInlineMediaPlayback": allowsInlineMediaPlayback, "allowsInlineMediaPlayback": allowsInlineMediaPlayback,
"allowsPictureInPictureMediaPlayback": allowsPictureInPictureMediaPlayback, "allowsPictureInPictureMediaPlayback":
allowsPictureInPictureMediaPlayback,
"isFraudulentWebsiteWarningEnabled": isFraudulentWebsiteWarningEnabled, "isFraudulentWebsiteWarningEnabled": isFraudulentWebsiteWarningEnabled,
"selectionGranularity": selectionGranularity.toValue(), "selectionGranularity": selectionGranularity.toValue(),
"dataDetectorTypes": dataDetectorTypesList, "dataDetectorTypes": dataDetectorTypesList,
...@@ -493,26 +647,34 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio ...@@ -493,26 +647,34 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio
}; };
} }
@override
static IosInAppWebViewOptions fromMap(Map<String, dynamic> map) { static IosInAppWebViewOptions fromMap(Map<String, dynamic> map) {
List<IosInAppWebViewDataDetectorTypes> dataDetectorTypes = []; List<IosInAppWebViewDataDetectorTypes> dataDetectorTypes = [];
List<String> dataDetectorTypesList = List<String>.from(map["dataDetectorTypes"] ?? []); List<String> dataDetectorTypesList =
List<String>.from(map["dataDetectorTypes"] ?? []);
dataDetectorTypesList.forEach((dataDetectorType) { dataDetectorTypesList.forEach((dataDetectorType) {
dataDetectorTypes.add(IosInAppWebViewDataDetectorTypes.fromValue(dataDetectorType)); dataDetectorTypes
.add(IosInAppWebViewDataDetectorTypes.fromValue(dataDetectorType));
}); });
IosInAppWebViewOptions options = new IosInAppWebViewOptions(); IosInAppWebViewOptions options = new IosInAppWebViewOptions();
options.disallowOverScroll = map["disallowOverScroll"]; options.disallowOverScroll = map["disallowOverScroll"];
options.enableViewportScale = map["enableViewportScale"]; options.enableViewportScale = map["enableViewportScale"];
options.suppressesIncrementalRendering = map["suppressesIncrementalRendering"]; options.suppressesIncrementalRendering =
options.allowsAirPlayForMediaPlayback = map["allowsAirPlayForMediaPlayback"]; map["suppressesIncrementalRendering"];
options.allowsBackForwardNavigationGestures = map["allowsBackForwardNavigationGestures"]; options.allowsAirPlayForMediaPlayback =
map["allowsAirPlayForMediaPlayback"];
options.allowsBackForwardNavigationGestures =
map["allowsBackForwardNavigationGestures"];
options.allowsLinkPreview = map["allowsLinkPreview"]; options.allowsLinkPreview = map["allowsLinkPreview"];
options.ignoresViewportScaleLimits = map["ignoresViewportScaleLimits"]; options.ignoresViewportScaleLimits = map["ignoresViewportScaleLimits"];
options.allowsInlineMediaPlayback = map["allowsInlineMediaPlayback"]; options.allowsInlineMediaPlayback = map["allowsInlineMediaPlayback"];
options.allowsPictureInPictureMediaPlayback = map["allowsPictureInPictureMediaPlayback"]; options.allowsPictureInPictureMediaPlayback =
options.isFraudulentWebsiteWarningEnabled = map["isFraudulentWebsiteWarningEnabled"]; map["allowsPictureInPictureMediaPlayback"];
options.selectionGranularity = IosInAppWebViewSelectionGranularity.fromValue(map["selectionGranularity"]); options.isFraudulentWebsiteWarningEnabled =
map["isFraudulentWebsiteWarningEnabled"];
options.selectionGranularity =
IosInAppWebViewSelectionGranularity.fromValue(
map["selectionGranularity"]);
options.dataDetectorTypes = dataDetectorTypes; options.dataDetectorTypes = dataDetectorTypes;
options.sharedCookiesEnabled = map["sharedCookiesEnabled"]; options.sharedCookiesEnabled = map["sharedCookiesEnabled"];
return options; return options;
...@@ -520,18 +682,26 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio ...@@ -520,18 +682,26 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio
} }
///This class represents all the cross-platform [InAppBrowser] options available. ///This class represents all the cross-platform [InAppBrowser] options available.
class InAppBrowserOptions implements BrowserOptions, AndroidOptions, IosOptions { class InAppBrowserOptions
implements BrowserOptions, AndroidOptions, IosOptions {
///Set to `true` to create the browser and load the page, but not show it. Omit or set to `false` to have the browser open and load normally. ///Set to `true` to create the browser and load the page, but not show it. Omit or set to `false` to have the browser open and load normally.
///The default value is `false`. ///The default value is `false`.
bool hidden; bool hidden;
///Set to `false` to hide the toolbar at the top of the WebView. The default value is `true`. ///Set to `false` to hide the toolbar at the top of the WebView. The default value is `true`.
bool toolbarTop; bool toolbarTop;
///Set the custom background color of the toolbar at the top. ///Set the custom background color of the toolbar at the top.
String toolbarTopBackgroundColor; String toolbarTopBackgroundColor;
///Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`. ///Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`.
bool hideUrlBar; bool hideUrlBar;
InAppBrowserOptions({this.hidden = false, this.toolbarTop = true, this.toolbarTopBackgroundColor = "", this.hideUrlBar = false}); InAppBrowserOptions(
{this.hidden = false,
this.toolbarTop = true,
this.toolbarTopBackgroundColor = "",
this.hideUrlBar = false});
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
...@@ -543,7 +713,6 @@ class InAppBrowserOptions implements BrowserOptions, AndroidOptions, IosOptions ...@@ -543,7 +713,6 @@ class InAppBrowserOptions implements BrowserOptions, AndroidOptions, IosOptions
}; };
} }
@override
static InAppBrowserOptions fromMap(Map<String, dynamic> map) { static InAppBrowserOptions fromMap(Map<String, dynamic> map) {
InAppBrowserOptions options = new InAppBrowserOptions(); InAppBrowserOptions options = new InAppBrowserOptions();
options.hidden = map["hidden"]; options.hidden = map["hidden"];
...@@ -558,14 +727,21 @@ class InAppBrowserOptions implements BrowserOptions, AndroidOptions, IosOptions ...@@ -558,14 +727,21 @@ class InAppBrowserOptions implements BrowserOptions, AndroidOptions, IosOptions
class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions { class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
///Set to `true` if you want the title should be displayed. The default value is `false`. ///Set to `true` if you want the title should be displayed. The default value is `false`.
bool hideTitleBar; bool hideTitleBar;
///Set the action bar's title. ///Set the action bar's title.
String toolbarTopFixedTitle; String toolbarTopFixedTitle;
///Set to `false` to not close the InAppBrowser when the user click on the back button and the WebView cannot go back to the history. The default value is `true`. ///Set to `false` to not close the InAppBrowser when the user click on the back button and the WebView cannot go back to the history. The default value is `true`.
bool closeOnCannotGoBack; bool closeOnCannotGoBack;
///Set to `false` to hide the progress bar at the bottom of the toolbar at the top. The default value is `true`. ///Set to `false` to hide the progress bar at the bottom of the toolbar at the top. The default value is `true`.
bool progressBar; bool progressBar;
AndroidInAppBrowserOptions({this.hideTitleBar = true, this.toolbarTopFixedTitle = "", this.closeOnCannotGoBack = true, this.progressBar = true}); AndroidInAppBrowserOptions(
{this.hideTitleBar = true,
this.toolbarTopFixedTitle = "",
this.closeOnCannotGoBack = true,
this.progressBar = true});
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
...@@ -577,7 +753,6 @@ class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions { ...@@ -577,7 +753,6 @@ class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
}; };
} }
@override
static AndroidInAppBrowserOptions fromMap(Map<String, dynamic> map) { static AndroidInAppBrowserOptions fromMap(Map<String, dynamic> map) {
AndroidInAppBrowserOptions options = new AndroidInAppBrowserOptions(); AndroidInAppBrowserOptions options = new AndroidInAppBrowserOptions();
options.hideTitleBar = map["hideTitleBar"]; options.hideTitleBar = map["hideTitleBar"];
...@@ -592,24 +767,37 @@ class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions { ...@@ -592,24 +767,37 @@ class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
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`. ///Set to `false` to hide the toolbar at the bottom of the WebView. The default value is `true`.
bool toolbarBottom; bool toolbarBottom;
///Set the custom background color of the toolbar at the bottom. ///Set the custom background color of the toolbar at the bottom.
String toolbarBottomBackgroundColor; String toolbarBottomBackgroundColor;
///Set to `true` to set the toolbar at the bottom translucent. The default value is `true`. ///Set to `true` to set the toolbar at the bottom translucent. The default value is `true`.
bool toolbarBottomTranslucent; bool toolbarBottomTranslucent;
///Set the custom text for the close button. ///Set the custom text for the close button.
String closeButtonCaption; String closeButtonCaption;
///Set the custom color for the close button. ///Set the custom color for the close button.
String closeButtonColor; String closeButtonColor;
///Set the custom modal presentation style when presenting the WebView. The default value is [IosWebViewOptionsPresentationStyle.FULL_SCREEN]. ///Set the custom modal presentation style when presenting the WebView. The default value is [IosWebViewOptionsPresentationStyle.FULL_SCREEN].
IosWebViewOptionsPresentationStyle presentationStyle; IosWebViewOptionsPresentationStyle presentationStyle;
///Set to the custom transition style when presenting the WebView. The default value is [IosWebViewOptionsTransitionStyle.COVER_VERTICAL]. ///Set to the custom transition style when presenting the WebView. The default value is [IosWebViewOptionsTransitionStyle.COVER_VERTICAL].
IosWebViewOptionsTransitionStyle transitionStyle; IosWebViewOptionsTransitionStyle transitionStyle;
///Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`. ///Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`.
bool spinner; bool spinner;
IosInAppBrowserOptions({this.toolbarBottom = true, this.toolbarBottomBackgroundColor = "", this.toolbarBottomTranslucent = true, this.closeButtonCaption = "", IosInAppBrowserOptions(
this.closeButtonColor = "", this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN, {this.toolbarBottom = true,
this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL, this.spinner = true}); this.toolbarBottomBackgroundColor = "",
this.toolbarBottomTranslucent = true,
this.closeButtonCaption = "",
this.closeButtonColor = "",
this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN,
this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL,
this.spinner = true});
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
...@@ -625,7 +813,6 @@ class IosInAppBrowserOptions implements BrowserOptions, IosOptions { ...@@ -625,7 +813,6 @@ class IosInAppBrowserOptions implements BrowserOptions, IosOptions {
}; };
} }
@override
static IosInAppBrowserOptions fromMap(Map<String, dynamic> map) { static IosInAppBrowserOptions fromMap(Map<String, dynamic> map) {
IosInAppBrowserOptions options = new IosInAppBrowserOptions(); IosInAppBrowserOptions options = new IosInAppBrowserOptions();
options.toolbarBottom = map["toolbarBottom"]; options.toolbarBottom = map["toolbarBottom"];
...@@ -633,27 +820,39 @@ class IosInAppBrowserOptions implements BrowserOptions, IosOptions { ...@@ -633,27 +820,39 @@ class IosInAppBrowserOptions implements BrowserOptions, IosOptions {
options.toolbarBottomTranslucent = map["toolbarBottomTranslucent"]; options.toolbarBottomTranslucent = map["toolbarBottomTranslucent"];
options.closeButtonCaption = map["closeButtonCaption"]; options.closeButtonCaption = map["closeButtonCaption"];
options.closeButtonColor = map["closeButtonColor"]; options.closeButtonColor = map["closeButtonColor"];
options.presentationStyle = IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]); options.presentationStyle =
options.transitionStyle = IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]); IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
options.transitionStyle =
IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
options.spinner = map["spinner"]; options.spinner = map["spinner"];
return options; return options;
} }
} }
///This class represents all the Android-only [ChromeSafariBrowser] options available. ///This class represents all the Android-only [ChromeSafariBrowser] options available.
class AndroidChromeCustomTabsOptions implements ChromeSafariBrowserOptions, AndroidOptions { class AndroidChromeCustomTabsOptions
implements ChromeSafariBrowserOptions, AndroidOptions {
///Set to `false` if you don't want the default share button. The default value is `true`. ///Set to `false` if you don't want the default share button. The default value is `true`.
bool addShareButton; bool addShareButton;
///Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`. ///Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`.
bool showTitle; bool showTitle;
///Set the custom background color of the toolbar. ///Set the custom background color of the toolbar.
String toolbarBackgroundColor; String toolbarBackgroundColor;
///Set to `true` to enable the url bar to hide as the user scrolls down on the page. The default value is `false`. ///Set to `true` to enable the url bar to hide as the user scrolls down on the page. The default value is `false`.
bool enableUrlBarHiding; bool enableUrlBarHiding;
///Set to `true` to enable Instant Apps. The default value is `false`. ///Set to `true` to enable Instant Apps. The default value is `false`.
bool instantAppsEnabled; bool instantAppsEnabled;
AndroidChromeCustomTabsOptions({this.addShareButton = true, this.showTitle = true, this.toolbarBackgroundColor = "", this.enableUrlBarHiding = false, this.instantAppsEnabled = false}); AndroidChromeCustomTabsOptions(
{this.addShareButton = true,
this.showTitle = true,
this.toolbarBackgroundColor = "",
this.enableUrlBarHiding = false,
this.instantAppsEnabled = false});
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
...@@ -666,9 +865,9 @@ class AndroidChromeCustomTabsOptions implements ChromeSafariBrowserOptions, Andr ...@@ -666,9 +865,9 @@ class AndroidChromeCustomTabsOptions implements ChromeSafariBrowserOptions, Andr
}; };
} }
@override
static AndroidChromeCustomTabsOptions fromMap(Map<String, dynamic> map) { static AndroidChromeCustomTabsOptions fromMap(Map<String, dynamic> map) {
AndroidChromeCustomTabsOptions options = new AndroidChromeCustomTabsOptions(); AndroidChromeCustomTabsOptions options =
new AndroidChromeCustomTabsOptions();
options.addShareButton = map["addShareButton"]; options.addShareButton = map["addShareButton"];
options.showTitle = map["showTitle"]; options.showTitle = map["showTitle"];
options.toolbarBackgroundColor = map["toolbarBackgroundColor"]; options.toolbarBackgroundColor = map["toolbarBackgroundColor"];
...@@ -682,27 +881,38 @@ class AndroidChromeCustomTabsOptions implements ChromeSafariBrowserOptions, Andr ...@@ -682,27 +881,38 @@ class AndroidChromeCustomTabsOptions implements ChromeSafariBrowserOptions, Andr
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`. ///Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`.
bool entersReaderIfAvailable; bool entersReaderIfAvailable;
///Set to `true` to enable bar collapsing. The default value is `false`. ///Set to `true` to enable bar collapsing. The default value is `false`.
bool barCollapsingEnabled; 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+. ///**NOTE**: available on iOS 11.0+.
IosSafariOptionsDismissButtonStyle dismissButtonStyle; IosSafariOptionsDismissButtonStyle dismissButtonStyle;
///Set the custom background color of the navigation bar and the toolbar. ///Set the custom background color of the navigation bar and the toolbar.
/// ///
///**NOTE**: available on iOS 10.0+. ///**NOTE**: available on iOS 10.0+.
String preferredBarTintColor; String preferredBarTintColor;
///Set the custom color of the control buttons on the navigation bar and the toolbar. ///Set the custom color of the control buttons on the navigation bar and the toolbar.
/// ///
///**NOTE**: available on iOS 10.0+. ///**NOTE**: available on iOS 10.0+.
String preferredControlTintColor; String preferredControlTintColor;
///Set the custom modal presentation style when presenting the WebView. The default value is [IosWebViewOptionsPresentationStyle.FULL_SCREEN]. ///Set the custom modal presentation style when presenting the WebView. The default value is [IosWebViewOptionsPresentationStyle.FULL_SCREEN].
IosWebViewOptionsPresentationStyle presentationStyle; IosWebViewOptionsPresentationStyle presentationStyle;
///Set to the custom transition style when presenting the WebView. The default value is [IosWebViewOptionsTransitionStyle.COVER_VERTICAL]. ///Set to the custom transition style when presenting the WebView. The default value is [IosWebViewOptionsTransitionStyle.COVER_VERTICAL].
IosWebViewOptionsTransitionStyle transitionStyle; IosWebViewOptionsTransitionStyle transitionStyle;
IosSafariOptions({this.entersReaderIfAvailable = false, this.barCollapsingEnabled = false, this.dismissButtonStyle = IosSafariOptionsDismissButtonStyle.DONE, IosSafariOptions(
this.preferredBarTintColor = "", this.preferredControlTintColor = "", this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN, {this.entersReaderIfAvailable = false,
this.barCollapsingEnabled = false,
this.dismissButtonStyle = IosSafariOptionsDismissButtonStyle.DONE,
this.preferredBarTintColor = "",
this.preferredControlTintColor = "",
this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN,
this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL}); this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL});
@override @override
...@@ -718,16 +928,18 @@ class IosSafariOptions implements ChromeSafariBrowserOptions, IosOptions { ...@@ -718,16 +928,18 @@ class IosSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
}; };
} }
@override
static IosSafariOptions fromMap(Map<String, dynamic> map) { static IosSafariOptions fromMap(Map<String, dynamic> map) {
IosSafariOptions options = new IosSafariOptions(); IosSafariOptions options = new IosSafariOptions();
options.entersReaderIfAvailable = map["entersReaderIfAvailable"]; options.entersReaderIfAvailable = map["entersReaderIfAvailable"];
options.barCollapsingEnabled = map["barCollapsingEnabled"]; options.barCollapsingEnabled = map["barCollapsingEnabled"];
options.dismissButtonStyle = IosSafariOptionsDismissButtonStyle.fromValue(map["dismissButtonStyle"]); options.dismissButtonStyle =
IosSafariOptionsDismissButtonStyle.fromValue(map["dismissButtonStyle"]);
options.preferredBarTintColor = map["preferredBarTintColor"]; options.preferredBarTintColor = map["preferredBarTintColor"];
options.preferredControlTintColor = map["preferredControlTintColor"]; options.preferredControlTintColor = map["preferredControlTintColor"];
options.presentationStyle = IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]); options.presentationStyle =
options.transitionStyle = IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]); IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
options.transitionStyle =
IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
return options; return options;
} }
} }
name: flutter_inappwebview name: flutter_inappwebview
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window. description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window.
version: 2.0.1 version: 2.0.1+1
author: Lorenzo Pichilli <pichillilorenzo@gmail.com> author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
homepage: https://github.com/pichillilorenzo/flutter_inappwebview homepage: https://github.com/pichillilorenzo/flutter_inappwebview
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment