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
This commit is contained in:
parent
a56b21282f
commit
ade4480c6d
|
@ -15,7 +15,25 @@
|
|||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<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$/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>
|
||||
<ignored path="$PROJECT_DIR$/.dart_tool/" />
|
||||
<ignored path="$PROJECT_DIR$/.idea/" />
|
||||
|
@ -35,12 +53,13 @@
|
|||
<component name="ExecutionTargetManager" SELECTED_TARGET="Pixel_3_XL_API_24" />
|
||||
<component name="FileEditorManager">
|
||||
<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">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="330">
|
||||
<caret line="22" column="92" selection-start-line="22" selection-start-column="92" selection-end-line="22" selection-end-column="92" />
|
||||
<state relative-caret-position="12735">
|
||||
<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>
|
||||
|
@ -51,33 +70,33 @@
|
|||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="255">
|
||||
<caret line="17" column="101" lean-forward="true" selection-start-line="17" selection-start-column="101" selection-end-line="17" selection-end-column="101" />
|
||||
<state relative-caret-position="30">
|
||||
<caret line="2" column="145" selection-start-line="2" selection-start-column="145" selection-end-line="2" selection-end-column="145" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
|
||||
<file pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state>
|
||||
<caret column="26" selection-start-column="6" selection-end-column="26" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="235">
|
||||
<caret line="1170" column="66" selection-start-line="1170" selection-start-column="66" selection-end-line="1170" selection-end-column="66" />
|
||||
<state relative-caret-position="304">
|
||||
<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#17#0" expanded="true" />
|
||||
<element signature="e#0#20#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$USER_HOME$/Downloads/in_app_webiew_example.screen.dart">
|
||||
<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>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
|
@ -90,13 +109,6 @@
|
|||
</component>
|
||||
<component name="FindInProjectRecents">
|
||||
<findStrings>
|
||||
<find>reload</find>
|
||||
<find>methods</find>
|
||||
<find>class</find>
|
||||
<find>HttpAuthCredentialDatabase</find>
|
||||
<find>###</find>
|
||||
<find>#####</find>
|
||||
<find>loadFile</find>
|
||||
<find>window.</find>
|
||||
<find>onLoadHttpError</find>
|
||||
<find>microphone</find>
|
||||
|
@ -117,9 +129,16 @@
|
|||
<find>[InAppBrowser]</find>
|
||||
<find>Response({</find>
|
||||
<find>flutter_inappbrowser</find>
|
||||
<find>flutterInAppBrowserPlatformReady</find>
|
||||
<find>InAppBrowser</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>
|
||||
<replaceStrings>
|
||||
<replace>activity.getPreferences(0)</replace>
|
||||
|
@ -142,13 +161,10 @@
|
|||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<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$/example/assets/index.html" />
|
||||
<option value="$PROJECT_DIR$/lib/src/types.dart" />
|
||||
<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$/ios/flutter_inappbrowser.podspec" />
|
||||
<option value="$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart" />
|
||||
|
@ -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_find_result_received_test.dart" />
|
||||
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_js_dialog_test.dart" />
|
||||
<option value="$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_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_test.dart" />
|
||||
|
@ -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_should_override_url_loading_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/InAppWebViewFlutterPlugin.h" />
|
||||
<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/http_auth_credentials_database.dart" />
|
||||
<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$/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" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds">
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<option name="x" value="-1" />
|
||||
<option name="y" value="23" />
|
||||
<option name="width" value="1920" />
|
||||
<option name="height" value="1057" />
|
||||
|
@ -248,6 +268,42 @@
|
|||
<item name="flutter_inappwebview" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappwebview" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappwebview" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="assets" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappwebview" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappwebview" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="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>
|
||||
<select />
|
||||
</subPane>
|
||||
|
@ -284,6 +340,10 @@
|
|||
<property name="show.migrate.to.gradle.popup" value="false" />
|
||||
</component>
|
||||
<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">
|
||||
<recent name="$PROJECT_DIR$/example/test_driver" />
|
||||
<recent name="$PROJECT_DIR$/example/test_assets" />
|
||||
|
@ -291,10 +351,6 @@
|
|||
<recent name="$PROJECT_DIR$/example/assets/images" />
|
||||
<recent name="$PROJECT_DIR$/android/libs" />
|
||||
</key>
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/example/assets/images" />
|
||||
<recent name="$PROJECT_DIR$/android/src/main/java" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
|
@ -412,8 +468,7 @@
|
|||
</todo-panel>
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="0" y="23" width="1920" height="1057" extended-state="0" />
|
||||
<editor active="true" />
|
||||
<frame x="-1" y="23" width="1920" height="1057" extended-state="6" />
|
||||
<layout>
|
||||
<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" />
|
||||
|
@ -434,7 +489,7 @@
|
|||
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
|
||||
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.50532484" side_tool="true" weight="0.35751295" />
|
||||
<window_info anchor="bottom" id="Version Control" order="9" />
|
||||
<window_info 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="Messages" order="12" sideWeight="0.4968051" weight="0.33782384" />
|
||||
<window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" />
|
||||
|
@ -464,55 +519,6 @@
|
|||
</ignored-roots>
|
||||
</component>
|
||||
<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">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="45">
|
||||
|
@ -562,13 +568,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_initial_file_test.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="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">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="30">
|
||||
|
@ -611,13 +610,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_error_test.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="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">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="30">
|
||||
|
@ -688,32 +680,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<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="-496">
|
||||
<folding>
|
||||
<element signature="e#1#40#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="32">
|
||||
<caret line="3" column="20" selection-start-line="3" selection-start-column="20" selection-end-line="3" selection-end-column="20" />
|
||||
<folding>
|
||||
<element signature="e#0#17#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="90">
|
||||
<caret line="6" column="8" selection-start-line="6" selection-start-column="8" selection-end-line="6" selection-end-column="8" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/in_app_webiew_example.screen.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="15">
|
||||
|
@ -721,13 +687,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="180">
|
||||
<caret line="12" column="32" selection-start-line="12" selection-start-column="32" selection-end-line="12" selection-end-column="32" />
|
||||
</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">
|
||||
|
@ -742,16 +701,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="182">
|
||||
<caret line="14" column="1" lean-forward="true" selection-start-line="14" selection-start-column="1" selection-end-line="14" selection-end-column="1" />
|
||||
<folding>
|
||||
<element signature="e#0#20#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="765">
|
||||
|
@ -759,16 +708,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="235">
|
||||
<caret line="1170" column="66" selection-start-line="1170" selection-start-column="66" selection-end-line="1170" selection-end-column="66" />
|
||||
<folding>
|
||||
<element signature="e#0#17#0" expanded="true" />
|
||||
</folding>
|
||||
</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">
|
||||
|
@ -804,31 +743,163 @@
|
|||
<entry file="file://$PROJECT_DIR$/android/src/main/AndroidManifest.xml">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
||||
<entry file="file://$PROJECT_DIR$/.git/description">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/.git/config">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="255">
|
||||
<caret line="17" column="101" lean-forward="true" selection-start-line="17" selection-start-column="101" selection-end-line="17" selection-end-column="101" />
|
||||
<state relative-caret-position="195">
|
||||
<caret line="13" lean-forward="true" selection-start-line="13" selection-end-line="13" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_on_load_error_test.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="357">
|
||||
<caret line="27" column="33" selection-start-line="27" selection-start-column="33" selection-end-line="27" selection-end-column="33" />
|
||||
<folding>
|
||||
<element signature="e#0#39#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="161">
|
||||
<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>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity-0.4.5+6/lib/connectivity.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="75">
|
||||
<caret line="11" column="5" selection-start-line="11" selection-start-column="5" selection-end-line="11" selection-end-column="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/test_driver/in_app_webview_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">
|
||||
<state relative-caret-position="96">
|
||||
<caret line="28" column="85" selection-start-line="28" selection-start-column="20" selection-end-line="28" selection-end-column="85" />
|
||||
<folding>
|
||||
<element signature="e#0#39#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="360">
|
||||
<caret line="24" column="24" selection-start-line="24" selection-start-column="24" selection-end-line="24" selection-end-column="24" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="161">
|
||||
<caret line="105" column="30" selection-start-line="105" selection-start-column="15" selection-end-line="105" selection-end-column="30" />
|
||||
<folding>
|
||||
<element signature="e#0#17#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state>
|
||||
<caret column="26" selection-start-column="6" selection-end-column="26" />
|
||||
<state relative-caret-position="165">
|
||||
<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>
|
||||
<element signature="e#0#20#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/src/channel_manager.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="225">
|
||||
<caret line="15" column="36" selection-start-line="15" selection-start-column="36" selection-end-line="15" selection-end-column="36" />
|
||||
<folding>
|
||||
<element signature="e#0#20#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/flutter_inappwebview.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="315">
|
||||
<caret line="21" column="29" lean-forward="true" selection-start-line="21" selection-start-column="29" selection-end-line="21" selection-end-column="29" />
|
||||
<folding>
|
||||
<element signature="e#0#1252#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="10620">
|
||||
<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>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/Downloads/in_app_webiew_example.screen.dart">
|
||||
<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 file="file://$PROJECT_DIR$/README.md">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="330">
|
||||
<caret line="22" column="92" selection-start-line="22" selection-start-column="92" selection-end-line="22" selection-end-column="92" />
|
||||
<state relative-caret-position="12735">
|
||||
<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>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="30">
|
||||
<caret line="2" column="145" selection-start-line="2" selection-start-column="145" selection-end-line="2" selection-end-column="145" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<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">
|
||||
<state relative-caret-position="304">
|
||||
<caret line="78" column="1" selection-start-line="78" selection-start-column="1" selection-end-line="78" selection-end-column="1" />
|
||||
<folding>
|
||||
<element signature="e#0#20#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
## 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
|
||||
|
||||
- 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
|
|||
- Dart sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||
- Flutter: ">=1.9.1+hotfix.5 <2.0.0"
|
||||
- Android: `minSdkVersion 17`
|
||||
- iOS: `--ios-language swift`
|
||||
- iOS: `--ios-language swift`, Xcode version `>= 11`
|
||||
|
||||
### Note for Android
|
||||
|
||||
|
@ -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).
|
||||
* `onReceivedHttpAuthRequest`: Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
|
||||
* `onReceivedServerTrustAuthRequest`: Event fired when the WebView need to perform server trust authentication (certificate validation).
|
||||
* `onReceivedClientCertRequest`: Notify the host application to handle 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.
|
||||
* `shouldInterceptAjaxRequest`: Event fired when an `XMLHttpRequest` is sent to a server.
|
||||
* `onAjaxReadyStateChange`: Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes.
|
||||
|
|
|
@ -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);
|
||||
if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) {
|
||||
alertDialogBuilder.setPositiveButton(confirmButtonTitle, clickListener);
|
||||
|
@ -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);
|
||||
if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) {
|
||||
alertDialogBuilder.setPositiveButton(confirmButtonTitle, confirmClickListener);
|
||||
|
@ -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);
|
||||
if (confirmButtonTitle != null && !confirmButtonTitle.isEmpty()) {
|
||||
alertDialogBuilder.setPositiveButton(confirmButtonTitle, confirmClickListener);
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
# This is a generated file; do not edit or check into version control.
|
||||
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
|
||||
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 "SYMROOT=${SOURCE_ROOT}/../build/ios"
|
||||
export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios"
|
||||
export "FLUTTER_BUILD_NAME=1.0.0"
|
||||
export "FLUTTER_BUILD_NUMBER=1"
|
||||
export "TRACK_WIDGET_CREATION=true"
|
||||
|
|
|
@ -268,6 +268,8 @@
|
|||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${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_inappwebview/flutter_inappwebview.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
|
||||
|
@ -275,6 +277,8 @@
|
|||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${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_inappwebview.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
|
||||
|
|
|
@ -22,6 +22,7 @@ dependencies:
|
|||
flutter_downloader: ^1.3.2
|
||||
path_provider: ^1.4.0
|
||||
permission_handler: ^3.3.0
|
||||
connectivity: ^0.4.5+6
|
||||
flutter_inappwebview:
|
||||
path: ../
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class InAppWebViewOnLoadErrorTestState extends WidgetTestState {
|
|||
Expanded(
|
||||
child: Container(
|
||||
child: InAppWebView(
|
||||
initialUrl: "http://not-existing-domain.org/",
|
||||
initialUrl: "https://not-existing-domain.org/",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewWidgetOptions(
|
||||
inAppWebViewOptions: InAppWebViewOptions(
|
||||
|
|
|
@ -6,7 +6,8 @@ import 'package:flutter/services.dart';
|
|||
import 'types.dart' show ListenerCallback;
|
||||
|
||||
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 final listeners = HashMap<String, ListenerCallback>();
|
||||
|
||||
|
@ -16,13 +17,12 @@ class ChannelManager {
|
|||
}
|
||||
|
||||
static void addListener(String key, ListenerCallback callback) {
|
||||
if (!initialized)
|
||||
init();
|
||||
if (!initialized) init();
|
||||
listeners.putIfAbsent(key, () => callback);
|
||||
}
|
||||
|
||||
static void init () {
|
||||
static void init() {
|
||||
channel.setMethodCallHandler(_handleMethod);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class ChromeSafariBrowser {
|
|||
bool _isOpened = false;
|
||||
|
||||
///Initialize the [ChromeSafariBrowser] instance with an [InAppBrowser] fallback instance or `null`.
|
||||
ChromeSafariBrowser ({bFallback}) {
|
||||
ChromeSafariBrowser({bFallback}) {
|
||||
uuid = uuidGenerator.v4();
|
||||
browserFallback = bFallback;
|
||||
ChannelManager.addListener(uuid, handleMethod);
|
||||
|
@ -28,7 +28,7 @@ class ChromeSafariBrowser {
|
|||
}
|
||||
|
||||
Future<dynamic> handleMethod(MethodCall call) async {
|
||||
switch(call.method) {
|
||||
switch (call.method) {
|
||||
case "onChromeSafariBrowserOpened":
|
||||
onOpened();
|
||||
break;
|
||||
|
@ -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.
|
||||
///
|
||||
///[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);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
|
||||
|
||||
|
@ -65,21 +69,33 @@ class ChromeSafariBrowser {
|
|||
|
||||
Map<String, dynamic> optionsFallbackMap = {};
|
||||
if (optionsFallback != null) {
|
||||
optionsFallbackMap.addAll(optionsFallback.inAppBrowserOptions?.toMap() ?? {});
|
||||
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
|
||||
optionsFallbackMap
|
||||
.addAll(optionsFallback.inAppBrowserOptions?.toMap() ?? {});
|
||||
optionsFallbackMap.addAll(optionsFallback
|
||||
.inAppWebViewWidgetOptions?.inAppWebViewOptions
|
||||
?.toMap() ??
|
||||
{});
|
||||
if (Platform.isAndroid) {
|
||||
optionsFallbackMap.addAll(optionsFallback.androidInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
|
||||
}
|
||||
else if (Platform.isIOS) {
|
||||
optionsFallbackMap.addAll(optionsFallback.iosInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
|
||||
optionsFallbackMap
|
||||
.addAll(optionsFallback.androidInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsFallbackMap.addAll(optionsFallback
|
||||
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsFallbackMap
|
||||
.addAll(optionsFallback.iosInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsFallbackMap.addAll(optionsFallback
|
||||
.inAppWebViewWidgetOptions?.iosInAppWebViewOptions
|
||||
?.toMap() ??
|
||||
{});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('uuid', () => uuid);
|
||||
args.putIfAbsent('uuidFallback', () => (browserFallback != null) ? browserFallback.uuid : '');
|
||||
args.putIfAbsent('uuidFallback',
|
||||
() => (browserFallback != null) ? browserFallback.uuid : '');
|
||||
args.putIfAbsent('url', () => url);
|
||||
args.putIfAbsent('headers', () => headersFallback);
|
||||
args.putIfAbsent('options', () => optionsMap);
|
||||
|
@ -91,19 +107,13 @@ class ChromeSafariBrowser {
|
|||
}
|
||||
|
||||
///Event fires when the [ChromeSafariBrowser] is opened.
|
||||
void onOpened() {
|
||||
|
||||
}
|
||||
void onOpened() {}
|
||||
|
||||
///Event fires when the [ChromeSafariBrowser] is loaded.
|
||||
void onLoaded() {
|
||||
|
||||
}
|
||||
void onLoaded() {}
|
||||
|
||||
///Event fires when the [ChromeSafariBrowser] is closed.
|
||||
void onClosed() {
|
||||
|
||||
}
|
||||
void onClosed() {}
|
||||
|
||||
///Returns `true` if the [ChromeSafariBrowser] instance is opened, otherwise `false`.
|
||||
bool isOpened() {
|
||||
|
@ -112,13 +122,17 @@ class ChromeSafariBrowser {
|
|||
|
||||
void throwIsAlreadyOpened({String message = ''}) {
|
||||
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 = ''}) {
|
||||
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';
|
|||
class ContentBlocker {
|
||||
///Trigger of the content blocker. The trigger tells to the WebView when to perform the corresponding action.
|
||||
ContentBlockerTrigger trigger;
|
||||
|
||||
///Action associated to the trigger. The action tells to the WebView what to do when the trigger is matched.
|
||||
ContentBlockerAction action;
|
||||
|
||||
ContentBlocker({@required this.trigger,@required this.action});
|
||||
ContentBlocker({@required this.trigger, @required this.action});
|
||||
|
||||
Map<String, Map<String, dynamic>> toMap() {
|
||||
return {
|
||||
"trigger": trigger.toMap(),
|
||||
"action": action.toMap()
|
||||
};
|
||||
return {"trigger": trigger.toMap(), "action": action.toMap()};
|
||||
}
|
||||
|
||||
static ContentBlocker fromMap(Map<dynamic, Map<dynamic, dynamic>> map) {
|
||||
return ContentBlocker(
|
||||
trigger: ContentBlockerTrigger.fromMap(
|
||||
Map<String, dynamic>.from(map["trigger"])
|
||||
),
|
||||
Map<String, dynamic>.from(map["trigger"])),
|
||||
action: ContentBlockerAction.fromMap(
|
||||
Map<String, dynamic>.from(map["action"])
|
||||
)
|
||||
);
|
||||
Map<String, dynamic>.from(map["action"])));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,29 +37,42 @@ class ContentBlocker {
|
|||
class ContentBlockerTrigger {
|
||||
///A regular expression pattern to match the URL against.
|
||||
String urlFilter;
|
||||
|
||||
///Used only by iOS. A Boolean value. The default value is false.
|
||||
bool urlFilterIsCaseSensitive;
|
||||
|
||||
///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.
|
||||
List<ContentBlockerTriggerResourceType> resourceType;
|
||||
|
||||
///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].
|
||||
List<String> ifDomain;
|
||||
|
||||
///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].
|
||||
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.
|
||||
List<ContentBlockerTriggerLoadType> loadType;
|
||||
|
||||
///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].
|
||||
List<String> ifTopUrl;
|
||||
|
||||
///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].
|
||||
List<String> unlessTopUrl;
|
||||
|
||||
ContentBlockerTrigger({@required String urlFilter, 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 []}) {
|
||||
ContentBlockerTrigger(
|
||||
{@required String urlFilter,
|
||||
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;
|
||||
assert(this.urlFilter != null);
|
||||
this.resourceType = resourceType;
|
||||
|
@ -101,7 +109,9 @@ class ContentBlockerTrigger {
|
|||
};
|
||||
|
||||
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
|
||||
.forEach(map.remove);
|
||||
|
||||
|
@ -112,7 +122,8 @@ class ContentBlockerTrigger {
|
|||
List<ContentBlockerTriggerResourceType> resourceType = [];
|
||||
List<ContentBlockerTriggerLoadType> loadType = [];
|
||||
|
||||
List<String> resourceTypeStringList = List<String>.from(map["resource-type"] ?? []);
|
||||
List<String> resourceTypeStringList =
|
||||
List<String>.from(map["resource-type"] ?? []);
|
||||
resourceTypeStringList.forEach((type) {
|
||||
resourceType.add(ContentBlockerTriggerResourceType.fromValue(type));
|
||||
});
|
||||
|
@ -130,8 +141,7 @@ class ContentBlockerTrigger {
|
|||
resourceType: resourceType,
|
||||
loadType: loadType,
|
||||
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 {
|
|||
class ContentBlockerAction {
|
||||
///Type of the action.
|
||||
ContentBlockerActionType type;
|
||||
|
||||
///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.
|
||||
String selector;
|
||||
|
||||
ContentBlockerAction({@required ContentBlockerActionType type, String selector}) {
|
||||
ContentBlockerAction(
|
||||
{@required ContentBlockerActionType type, String selector}) {
|
||||
this.type = type;
|
||||
assert(this.type != null);
|
||||
if (this.type == ContentBlockerActionType.CSS_DISPLAY_NONE) {
|
||||
|
@ -157,13 +169,12 @@ class ContentBlockerAction {
|
|||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
Map<String, dynamic> map = {
|
||||
"type": type.toValue(),
|
||||
"selector": selector
|
||||
};
|
||||
Map<String, dynamic> map = {"type": type.toValue(), "selector": selector};
|
||||
|
||||
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
|
||||
.forEach(map.remove);
|
||||
|
||||
|
@ -173,7 +184,6 @@ class ContentBlockerAction {
|
|||
static ContentBlockerAction fromMap(Map<String, dynamic> map) {
|
||||
return ContentBlockerAction(
|
||||
type: ContentBlockerActionType.fromValue(map["type"]),
|
||||
selector: map["selector"]
|
||||
);
|
||||
selector: map["selector"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ import 'types.dart';
|
|||
///**NOTE for iOS**: available from iOS 11.0+.
|
||||
class CookieManager {
|
||||
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.
|
||||
static CookieManager instance() {
|
||||
|
@ -23,21 +24,22 @@ class CookieManager {
|
|||
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.
|
||||
///
|
||||
///The default value of [path] is `"/"`.
|
||||
///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,
|
||||
String domain,
|
||||
String path = "/",
|
||||
int expiresDate,
|
||||
int maxAge,
|
||||
bool isSecure }) async {
|
||||
if (domain == null)
|
||||
domain = _getDomainName(url);
|
||||
Future<void> setCookie(
|
||||
{@required String url,
|
||||
@required String name,
|
||||
@required String value,
|
||||
String domain,
|
||||
String path = "/",
|
||||
int expiresDate,
|
||||
int maxAge,
|
||||
bool isSecure}) async {
|
||||
if (domain == null) domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(name != null && name.isNotEmpty);
|
||||
|
@ -64,17 +66,20 @@ class CookieManager {
|
|||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
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>>();
|
||||
List<Cookie> cookies = [];
|
||||
for(var i = 0; i < cookieListMap.length; i++) {
|
||||
cookies.add(Cookie(name: cookieListMap[i]["name"], value: cookieListMap[i]["value"]));
|
||||
for (var i = 0; i < cookieListMap.length; i++) {
|
||||
cookies.add(Cookie(
|
||||
name: cookieListMap[i]["name"], value: cookieListMap[i]["value"]));
|
||||
}
|
||||
return cookies;
|
||||
}
|
||||
|
||||
///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(name != null && name.isNotEmpty);
|
||||
|
||||
|
@ -82,7 +87,7 @@ class CookieManager {
|
|||
args.putIfAbsent('url', () => url);
|
||||
List<dynamic> cookies = await _channel.invokeMethod('getCookies', args);
|
||||
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>();
|
||||
if (cookies[i]["name"] == name)
|
||||
return Cookie(name: cookies[i]["name"], value: cookies[i]["value"]);
|
||||
|
@ -94,9 +99,12 @@ class CookieManager {
|
|||
///
|
||||
///The default value of [path] is `"/"`.
|
||||
///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 {
|
||||
if (domain == null || domain.isEmpty)
|
||||
domain = _getDomainName(url);
|
||||
Future<void> deleteCookie(
|
||||
{@required String url,
|
||||
@required String name,
|
||||
String domain = "",
|
||||
String path = "/"}) async {
|
||||
if (domain == null || domain.isEmpty) domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(name != null && name.isNotEmpty);
|
||||
|
@ -115,9 +123,9 @@ class CookieManager {
|
|||
///
|
||||
///The default value of [path] is `"/"`.
|
||||
///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 {
|
||||
if (domain == null || domain.isEmpty)
|
||||
domain = _getDomainName(url);
|
||||
Future<void> deleteCookies(
|
||||
{@required String url, String domain = "", String path = "/"}) async {
|
||||
if (domain == null || domain.isEmpty) domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(domain != null && url.isNotEmpty);
|
||||
|
@ -139,8 +147,7 @@ class CookieManager {
|
|||
String _getDomainName(String url) {
|
||||
Uri uri = Uri.parse(url);
|
||||
String domain = uri.host;
|
||||
if (domain == null)
|
||||
return "";
|
||||
if (domain == null) return "";
|
||||
return domain.startsWith("www.") ? domain.substring(4) : domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ import 'package:flutter/services.dart';
|
|||
///doesn't offer the same functionalities as iOS `URLCredentialStorage`.
|
||||
class HttpAuthCredentialDatabase {
|
||||
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.
|
||||
static HttpAuthCredentialDatabase instance() {
|
||||
|
@ -24,44 +25,57 @@ class HttpAuthCredentialDatabase {
|
|||
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.
|
||||
///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`.
|
||||
Future<List<Map<String, dynamic>>> getAllAuthCredentials() async {
|
||||
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 = [];
|
||||
for (Map<dynamic, dynamic> map in allCredentials) {
|
||||
Map<dynamic, dynamic> protectionSpace = map["protectionSpace"];
|
||||
List<dynamic> credentials = map["credentials"];
|
||||
result.add({
|
||||
"protectionSpace": ProtectionSpace(host: protectionSpace["host"], protocol: protectionSpace["protocol"], realm: protectionSpace["realm"], port: protectionSpace["port"]),
|
||||
"credentials": credentials.map((credential) => HttpAuthCredential(username: credential["username"], password: credential["password"])).toList()
|
||||
"protectionSpace": ProtectionSpace(
|
||||
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;
|
||||
}
|
||||
|
||||
///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>{};
|
||||
args.putIfAbsent("host", () => protectionSpace.host);
|
||||
args.putIfAbsent("protocol", () => protectionSpace.protocol);
|
||||
args.putIfAbsent("realm", () => protectionSpace.realm);
|
||||
args.putIfAbsent("port", () => protectionSpace.port);
|
||||
List<dynamic> credentialList = await _channel.invokeMethod('getHttpAuthCredentials', args);
|
||||
List<dynamic> credentialList =
|
||||
await _channel.invokeMethod('getHttpAuthCredentials', args);
|
||||
List<HttpAuthCredential> credentials = [];
|
||||
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;
|
||||
}
|
||||
|
||||
///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>{};
|
||||
args.putIfAbsent("host", () => protectionSpace.host);
|
||||
args.putIfAbsent("protocol", () => protectionSpace.protocol);
|
||||
|
@ -73,7 +87,9 @@ class HttpAuthCredentialDatabase {
|
|||
}
|
||||
|
||||
///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>{};
|
||||
args.putIfAbsent("host", () => protectionSpace.host);
|
||||
args.putIfAbsent("protocol", () => protectionSpace.protocol);
|
||||
|
@ -85,7 +101,8 @@ class HttpAuthCredentialDatabase {
|
|||
}
|
||||
|
||||
///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>{};
|
||||
args.putIfAbsent("host", () => protectionSpace.host);
|
||||
args.putIfAbsent("protocol", () => protectionSpace.protocol);
|
||||
|
@ -99,4 +116,4 @@ class HttpAuthCredentialDatabase {
|
|||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('clearAllAuthCredentials', args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,23 +14,25 @@ import 'in_app_webview.dart' show InAppWebViewController;
|
|||
///
|
||||
///This class uses the native WebView of the platform.
|
||||
class InAppBrowser {
|
||||
|
||||
String uuid;
|
||||
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap = HashMap<String, JavaScriptHandlerCallback>();
|
||||
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
|
||||
HashMap<String, JavaScriptHandlerCallback>();
|
||||
bool _isOpened = false;
|
||||
|
||||
/// WebView Controller that can be used to access the [InAppWebView] API.
|
||||
InAppWebViewController webViewController;
|
||||
|
||||
///
|
||||
InAppBrowser () {
|
||||
InAppBrowser() {
|
||||
uuid = uuidGenerator.v4();
|
||||
ChannelManager.addListener(uuid, handleMethod);
|
||||
_isOpened = false;
|
||||
webViewController = new InAppWebViewController.fromInAppBrowser(uuid, ChannelManager.channel, this);
|
||||
webViewController = new InAppWebViewController.fromInAppBrowser(
|
||||
uuid, ChannelManager.channel, this);
|
||||
}
|
||||
|
||||
Future<dynamic> handleMethod(MethodCall call) async {
|
||||
switch(call.method) {
|
||||
switch (call.method) {
|
||||
case "onBrowserCreated":
|
||||
this._isOpened = true;
|
||||
onBrowserCreated();
|
||||
|
@ -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.
|
||||
///
|
||||
///[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);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
|
||||
|
||||
Map<String, dynamic> optionsMap = {};
|
||||
|
||||
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
|
||||
if (Platform.isAndroid) {
|
||||
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
|
||||
}
|
||||
else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options
|
||||
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
|
||||
{});
|
||||
}
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -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.
|
||||
///
|
||||
///[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);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!');
|
||||
|
||||
Map<String, dynamic> optionsMap = {};
|
||||
|
||||
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
|
||||
if (Platform.isAndroid) {
|
||||
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
|
||||
}
|
||||
else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options
|
||||
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
|
||||
{});
|
||||
}
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -149,20 +167,30 @@ class InAppBrowser {
|
|||
///The [encoding] parameter specifies the encoding of the data.
|
||||
///
|
||||
///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);
|
||||
|
||||
Map<String, dynamic> optionsMap = {};
|
||||
|
||||
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
|
||||
if (Platform.isAndroid) {
|
||||
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
|
||||
}
|
||||
else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options
|
||||
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
|
||||
{});
|
||||
}
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -233,14 +261,19 @@ class InAppBrowser {
|
|||
Map<String, dynamic> optionsMap = {};
|
||||
|
||||
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
|
||||
if (Platform.isAndroid) {
|
||||
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
|
||||
}
|
||||
else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options
|
||||
.inAppWebViewWidgetOptions?.androidInAppWebViewOptions
|
||||
?.toMap() ??
|
||||
{});
|
||||
} else if (Platform.isIOS) {
|
||||
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
|
||||
optionsMap.addAll(
|
||||
options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ??
|
||||
{});
|
||||
}
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -257,19 +290,27 @@ class InAppBrowser {
|
|||
args.putIfAbsent('uuid', () => uuid);
|
||||
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
|
||||
|
||||
InAppBrowserClassOptions inAppBrowserClassOptions = InAppBrowserClassOptions();
|
||||
Map<dynamic, dynamic> options = await ChannelManager.channel.invokeMethod('getOptions', args);
|
||||
InAppBrowserClassOptions inAppBrowserClassOptions =
|
||||
InAppBrowserClassOptions();
|
||||
Map<dynamic, dynamic> options =
|
||||
await ChannelManager.channel.invokeMethod('getOptions', args);
|
||||
if (options != null) {
|
||||
options = options.cast<String, dynamic>();
|
||||
inAppBrowserClassOptions.inAppBrowserOptions = InAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewWidgetOptions.inAppWebViewOptions = InAppWebViewOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppBrowserOptions =
|
||||
InAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewWidgetOptions.inAppWebViewOptions =
|
||||
InAppWebViewOptions.fromMap(options);
|
||||
if (Platform.isAndroid) {
|
||||
inAppBrowserClassOptions.androidInAppBrowserOptions = AndroidInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewWidgetOptions.androidInAppWebViewOptions = AndroidInAppWebViewOptions.fromMap(options);
|
||||
}
|
||||
else if (Platform.isIOS) {
|
||||
inAppBrowserClassOptions.iosInAppBrowserOptions = IosInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewWidgetOptions.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.androidInAppBrowserOptions =
|
||||
AndroidInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions
|
||||
.inAppWebViewWidgetOptions.androidInAppWebViewOptions =
|
||||
AndroidInAppWebViewOptions.fromMap(options);
|
||||
} else if (Platform.isIOS) {
|
||||
inAppBrowserClassOptions.iosInAppBrowserOptions =
|
||||
IosInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewWidgetOptions
|
||||
.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,29 +323,19 @@ class InAppBrowser {
|
|||
}
|
||||
|
||||
///Event fired when the [InAppBrowser] is created.
|
||||
void onBrowserCreated() {
|
||||
|
||||
}
|
||||
void onBrowserCreated() {}
|
||||
|
||||
///Event fired when the [InAppBrowser] window is closed.
|
||||
void onExit() {
|
||||
|
||||
}
|
||||
void onExit() {}
|
||||
|
||||
///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].
|
||||
void onLoadStop(String url) {
|
||||
|
||||
}
|
||||
void onLoadStop(String 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.
|
||||
///
|
||||
|
@ -315,51 +346,37 @@ class InAppBrowser {
|
|||
///[description] represents the description of the HTTP error. On iOS, it is always an empty string.
|
||||
///
|
||||
///**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.
|
||||
void onProgressChanged(int progress) {
|
||||
|
||||
}
|
||||
void onProgressChanged(int progress) {}
|
||||
|
||||
///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.
|
||||
///
|
||||
///**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.
|
||||
///
|
||||
///**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.
|
||||
///
|
||||
///[x] represents the current horizontal 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.
|
||||
///
|
||||
///[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`.
|
||||
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`.
|
||||
///
|
||||
|
@ -367,18 +384,15 @@ class InAppBrowser {
|
|||
///
|
||||
///[url] represents the url of the request.
|
||||
// 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"`.
|
||||
///
|
||||
///[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`.
|
||||
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.
|
||||
///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 {
|
|||
///
|
||||
///**NOTE**: available only on Android.
|
||||
// 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.
|
||||
///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.
|
||||
// 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.
|
||||
///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.
|
||||
// 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.
|
||||
///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
|
@ -416,9 +425,7 @@ class InAppBrowser {
|
|||
///[message] represents the message to be displayed in the alert dialog.
|
||||
///[defaultValue] represents the default value displayed in the prompt dialog.
|
||||
// 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.
|
||||
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
|
||||
|
@ -429,37 +436,33 @@ class InAppBrowser {
|
|||
///
|
||||
///**NOTE**: available only on Android.
|
||||
// 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.
|
||||
///
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [HttpAuthChallenge].
|
||||
// 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).
|
||||
///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].
|
||||
// ignore: missing_return
|
||||
Future<ServerTrustAuthResponse> onReceivedServerTrustAuthRequest(ServerTrustChallenge challenge) {
|
||||
Future<ServerTrustAuthResponse> onReceivedServerTrustAuthRequest(
|
||||
ServerTrustChallenge challenge) {}
|
||||
|
||||
}
|
||||
|
||||
///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]
|
||||
///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.
|
||||
///
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [ClientCertChallenge].
|
||||
// ignore: missing_return
|
||||
Future<ClientCertResponse> onReceivedClientCertRequest(ClientCertChallenge challenge) {
|
||||
|
||||
}
|
||||
Future<ClientCertResponse> onReceivedClientCertRequest(
|
||||
ClientCertChallenge challenge) {}
|
||||
|
||||
///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.
|
||||
|
@ -469,9 +472,8 @@ class InAppBrowser {
|
|||
///[numberOfMatches] represents how many matches have been found.
|
||||
///
|
||||
///[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.
|
||||
///It gives the host application a chance to take control over the request before sending it.
|
||||
|
@ -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`.
|
||||
// ignore: missing_return
|
||||
Future<AjaxRequest> shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) {
|
||||
|
||||
}
|
||||
Future<AjaxRequest> shouldInterceptAjaxRequest(AjaxRequest ajaxRequest) {}
|
||||
|
||||
///Event fired whenever the `readyState` attribute of an `XMLHttpRequest` changes.
|
||||
///It gives the host application a chance to abort the request.
|
||||
|
@ -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`.
|
||||
// ignore: missing_return
|
||||
Future<AjaxRequestAction> onAjaxReadyStateChange(AjaxRequest ajaxRequest) {
|
||||
|
||||
}
|
||||
Future<AjaxRequestAction> onAjaxReadyStateChange(AjaxRequest ajaxRequest) {}
|
||||
|
||||
///Event fired as an `XMLHttpRequest` progress.
|
||||
///It gives the host application a chance to abort the request.
|
||||
|
@ -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`.
|
||||
// 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).
|
||||
///It gives the host application a chance to take control over the request before sending it.
|
||||
|
@ -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`.
|
||||
// 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
|
||||
///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 {
|
|||
///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.
|
||||
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.
|
||||
///
|
||||
|
@ -534,20 +526,23 @@ class InAppBrowser {
|
|||
///[resources] represents the array of resources the web content wants to access.
|
||||
///
|
||||
///**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 = ''}) {
|
||||
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 = ''}) {
|
||||
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';
|
|||
///
|
||||
///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 {
|
||||
|
||||
HttpServer _server;
|
||||
int _port = 8080;
|
||||
|
||||
|
@ -28,7 +27,6 @@ class InAppLocalhostServer {
|
|||
///```
|
||||
///The `NSAllowsLocalNetworking` key is available since **iOS 10**.
|
||||
Future<void> start() async {
|
||||
|
||||
if (this._server != null) {
|
||||
throw Exception('Server already started on http://localhost:$_port');
|
||||
}
|
||||
|
@ -48,8 +46,7 @@ class InAppLocalhostServer {
|
|||
path += (path.endsWith('/')) ? 'index.html' : '';
|
||||
|
||||
try {
|
||||
body = (await rootBundle.load(path))
|
||||
.buffer.asUint8List();
|
||||
body = (await rootBundle.load(path)).buffer.asUint8List();
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
request.response.close();
|
||||
|
@ -57,14 +54,17 @@ class InAppLocalhostServer {
|
|||
}
|
||||
|
||||
var contentType = ['text', 'html'];
|
||||
if (!request.requestedUri.path.endsWith('/') && request.requestedUri.pathSegments.isNotEmpty) {
|
||||
var mimeType = lookupMimeType(request.requestedUri.path, headerBytes: body);
|
||||
if (!request.requestedUri.path.endsWith('/') &&
|
||||
request.requestedUri.pathSegments.isNotEmpty) {
|
||||
var mimeType =
|
||||
lookupMimeType(request.requestedUri.path, headerBytes: body);
|
||||
if (mimeType != null) {
|
||||
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.close();
|
||||
});
|
||||
|
@ -84,5 +84,4 @@ class InAppLocalhostServer {
|
|||
this._server = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,24 +16,31 @@ import 'types.dart';
|
|||
import 'in_app_browser.dart';
|
||||
import 'webview_options.dart';
|
||||
|
||||
const javaScriptHandlerForbiddenNames = ["onLoadResource", "shouldInterceptAjaxRequest", "onAjaxReadyStateChange", "onAjaxProgress", "shouldInterceptFetchRequest"];
|
||||
const javaScriptHandlerForbiddenNames = [
|
||||
"onLoadResource",
|
||||
"shouldInterceptAjaxRequest",
|
||||
"onAjaxReadyStateChange",
|
||||
"onAjaxProgress",
|
||||
"shouldInterceptFetchRequest"
|
||||
];
|
||||
|
||||
///InAppWebView Widget class.
|
||||
///
|
||||
///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree.
|
||||
class InAppWebView extends StatefulWidget {
|
||||
|
||||
///Event fired when the [InAppWebView] is created.
|
||||
final void Function(InAppWebViewController controller) onWebViewCreated;
|
||||
|
||||
///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].
|
||||
final void Function(InAppWebViewController controller, String url) onLoadStop;
|
||||
|
||||
///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.
|
||||
///
|
||||
|
@ -44,51 +51,63 @@ class InAppWebView extends StatefulWidget {
|
|||
///[description] represents the description of the HTTP error. On iOS, it is always an empty string.
|
||||
///
|
||||
///**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.
|
||||
final void Function(InAppWebViewController controller, int progress) onProgressChanged;
|
||||
final void Function(InAppWebViewController controller, int progress)
|
||||
onProgressChanged;
|
||||
|
||||
///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.
|
||||
///
|
||||
///**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.
|
||||
///
|
||||
///**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.
|
||||
///
|
||||
///[x] represents the current horizontal 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.
|
||||
///
|
||||
///[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`.
|
||||
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`.
|
||||
///
|
||||
///[scheme] represents the scheme of the url.
|
||||
///
|
||||
///[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"`.
|
||||
///
|
||||
///[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`.
|
||||
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.
|
||||
///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 {
|
|||
///[origin] represents the origin of the web content attempting to use the Geolocation API.
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
final Future<GeolocationPermissionShowPromptResponse> Function(InAppWebViewController controller, String origin) onGeolocationPermissionsShowPrompt;
|
||||
final Future<GeolocationPermissionShowPromptResponse> Function(
|
||||
InAppWebViewController controller, String origin)
|
||||
onGeolocationPermissionsShowPrompt;
|
||||
|
||||
///Event fired when javascript calls the `alert()` method to display an alert dialog.
|
||||
///If [JsAlertResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
///
|
||||
///[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.
|
||||
///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.
|
||||
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.
|
||||
///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
|
||||
|
@ -117,7 +140,8 @@ class InAppWebView extends StatefulWidget {
|
|||
///[message] represents the message to be displayed in the alert 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.
|
||||
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
|
||||
|
@ -127,26 +151,33 @@ class InAppWebView extends StatefulWidget {
|
|||
///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat].
|
||||
///
|
||||
///**NOTE**: available only on Android.
|
||||
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller, String url, SafeBrowsingThreat threatType) onSafeBrowsingHit;
|
||||
final Future<SafeBrowsingResponse> Function(InAppWebViewController controller,
|
||||
String url, SafeBrowsingThreat threatType) onSafeBrowsingHit;
|
||||
|
||||
///Event fired when the WebView received an HTTP authentication request. The default behavior is to cancel the request.
|
||||
///
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the [HttpAuthChallenge].
|
||||
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).
|
||||
///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].
|
||||
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]
|
||||
///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.
|
||||
///
|
||||
///[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.
|
||||
///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 {
|
|||
///[numberOfMatches] represents how many matches have been found.
|
||||
///
|
||||
///[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.
|
||||
///It gives the host application a chance to take control over the request before sending it.
|
||||
|
@ -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
|
||||
///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.
|
||||
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.
|
||||
///It gives the host application a chance to abort the request.
|
||||
|
@ -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
|
||||
///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.
|
||||
final Future<AjaxRequestAction> Function(InAppWebViewController controller, AjaxRequest ajaxRequest) onAjaxReadyStateChange;
|
||||
final Future<AjaxRequestAction> Function(
|
||||
InAppWebViewController controller, AjaxRequest ajaxRequest)
|
||||
onAjaxReadyStateChange;
|
||||
|
||||
///Event fired as an `XMLHttpRequest` progress.
|
||||
///It gives the host application a chance to abort the request.
|
||||
|
@ -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
|
||||
///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.
|
||||
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).
|
||||
///It gives the host application a chance to take control over the request before sending it.
|
||||
|
@ -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
|
||||
///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.
|
||||
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
|
||||
///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 {
|
|||
///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.
|
||||
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.
|
||||
///
|
||||
|
@ -221,18 +262,26 @@ class InAppWebView extends StatefulWidget {
|
|||
///[resources] represents the array of resources the web content wants to access.
|
||||
///
|
||||
///**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.
|
||||
final String initialUrl;
|
||||
|
||||
///Initial asset file that will be loaded. See [InAppWebView.loadFile()] for explanation.
|
||||
final String initialFile;
|
||||
|
||||
///Initial [InAppWebViewInitialData] that will be loaded.
|
||||
final InAppWebViewInitialData initialData;
|
||||
|
||||
///Initial headers that will be used.
|
||||
final Map<String, String> initialHeaders;
|
||||
|
||||
///Initial options that will be used.
|
||||
final InAppWebViewWidgetOptions initialOptions;
|
||||
|
||||
/// `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
|
||||
/// 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 {
|
|||
this.initialFile,
|
||||
this.initialData,
|
||||
this.initialHeaders = const {},
|
||||
this.initialOptions,
|
||||
@required this.initialOptions,
|
||||
this.onWebViewCreated,
|
||||
this.onLoadStart,
|
||||
this.onLoadStop,
|
||||
|
@ -285,17 +334,19 @@ class InAppWebView extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _InAppWebViewState extends State<InAppWebView> {
|
||||
|
||||
InAppWebViewController _controller;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Map<String, dynamic> initialOptions = {};
|
||||
initialOptions.addAll(widget.initialOptions.inAppWebViewOptions?.toMap() ?? {});
|
||||
initialOptions
|
||||
.addAll(widget.initialOptions.inAppWebViewOptions?.toMap() ?? {});
|
||||
if (Platform.isAndroid)
|
||||
initialOptions.addAll(widget.initialOptions.androidInAppWebViewOptions?.toMap() ?? {});
|
||||
initialOptions.addAll(
|
||||
widget.initialOptions.androidInAppWebViewOptions?.toMap() ?? {});
|
||||
else if (Platform.isIOS)
|
||||
initialOptions.addAll(widget.initialOptions.iosInAppWebViewOptions?.toMap() ?? {});
|
||||
initialOptions
|
||||
.addAll(widget.initialOptions.iosInAppWebViewOptions?.toMap() ?? {});
|
||||
|
||||
if (defaultTargetPlatform == TargetPlatform.android) {
|
||||
return AndroidView(
|
||||
|
@ -356,7 +407,7 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
}
|
||||
|
||||
@override
|
||||
void dispose(){
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
@ -373,10 +424,10 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
/// An [InAppWebViewController] instance can be obtained by setting the [InAppWebView.onWebViewCreated]
|
||||
/// callback for an [InAppWebView] widget.
|
||||
class InAppWebViewController {
|
||||
|
||||
InAppWebView _widget;
|
||||
MethodChannel _channel;
|
||||
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap = HashMap<String, JavaScriptHandlerCallback>();
|
||||
Map<String, JavaScriptHandlerCallback> javaScriptHandlersMap =
|
||||
HashMap<String, JavaScriptHandlerCallback>();
|
||||
// ignore: unused_field
|
||||
bool _isOpened = false;
|
||||
// ignore: unused_field
|
||||
|
@ -384,35 +435,34 @@ class InAppWebViewController {
|
|||
String _inAppBrowserUuid;
|
||||
InAppBrowser _inAppBrowser;
|
||||
|
||||
|
||||
InAppWebViewController(int id, InAppWebView widget) {
|
||||
this._id = id;
|
||||
this._channel = MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id');
|
||||
this._channel =
|
||||
MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id');
|
||||
this._channel.setMethodCallHandler(handleMethod);
|
||||
this._widget = widget;
|
||||
}
|
||||
|
||||
InAppWebViewController.fromInAppBrowser(String uuid, MethodChannel channel, InAppBrowser inAppBrowser) {
|
||||
InAppWebViewController.fromInAppBrowser(
|
||||
String uuid, MethodChannel channel, InAppBrowser inAppBrowser) {
|
||||
this._inAppBrowserUuid = uuid;
|
||||
this._channel = channel;
|
||||
this._inAppBrowser = inAppBrowser;
|
||||
}
|
||||
|
||||
Future<dynamic> handleMethod(MethodCall call) async {
|
||||
switch(call.method) {
|
||||
switch (call.method) {
|
||||
case "onLoadStart":
|
||||
String url = call.arguments["url"];
|
||||
if (_widget != null && _widget.onLoadStart != null)
|
||||
_widget.onLoadStart(this, url);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onLoadStart(url);
|
||||
else if (_inAppBrowser != null) _inAppBrowser.onLoadStart(url);
|
||||
break;
|
||||
case "onLoadStop":
|
||||
String url = call.arguments["url"];
|
||||
if (_widget != null && _widget.onLoadStop != null)
|
||||
_widget.onLoadStop(this, url);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onLoadStop(url);
|
||||
else if (_inAppBrowser != null) _inAppBrowser.onLoadStop(url);
|
||||
break;
|
||||
case "onLoadError":
|
||||
String url = call.arguments["url"];
|
||||
|
@ -448,8 +498,10 @@ class InAppWebViewController {
|
|||
break;
|
||||
case "onConsoleMessage":
|
||||
String message = call.arguments["message"];
|
||||
ConsoleMessageLevel messageLevel = ConsoleMessageLevel.fromValue(call.arguments["messageLevel"]);
|
||||
ConsoleMessage consoleMessage = ConsoleMessage(message: message, messageLevel: messageLevel);
|
||||
ConsoleMessageLevel messageLevel =
|
||||
ConsoleMessageLevel.fromValue(call.arguments["messageLevel"]);
|
||||
ConsoleMessage consoleMessage =
|
||||
ConsoleMessage(message: message, messageLevel: messageLevel);
|
||||
if (_widget != null && _widget.onConsoleMessage != null)
|
||||
_widget.onConsoleMessage(this, consoleMessage);
|
||||
else if (_inAppBrowser != null)
|
||||
|
@ -460,31 +512,31 @@ class InAppWebViewController {
|
|||
int y = call.arguments["y"];
|
||||
if (_widget != null && _widget.onScrollChanged != null)
|
||||
_widget.onScrollChanged(this, x, y);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onScrollChanged(x, y);
|
||||
else if (_inAppBrowser != null) _inAppBrowser.onScrollChanged(x, y);
|
||||
break;
|
||||
case "onDownloadStart":
|
||||
String url = call.arguments["url"];
|
||||
if (_widget != null && _widget.onDownloadStart != null)
|
||||
_widget.onDownloadStart(this, url);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onDownloadStart(url);
|
||||
else if (_inAppBrowser != null) _inAppBrowser.onDownloadStart(url);
|
||||
break;
|
||||
case "onLoadResourceCustomScheme":
|
||||
String scheme = call.arguments["scheme"];
|
||||
String url = call.arguments["url"];
|
||||
if (_widget != null && _widget.onLoadResourceCustomScheme != null) {
|
||||
try {
|
||||
var response = await _widget.onLoadResourceCustomScheme(this, scheme, url);
|
||||
return (response != null) ? response.toJson(): null;
|
||||
var response =
|
||||
await _widget.onLoadResourceCustomScheme(this, scheme, url);
|
||||
return (response != null) ? response.toJson() : null;
|
||||
} catch (error) {
|
||||
print(error);
|
||||
return null;
|
||||
}
|
||||
} else if (_inAppBrowser != null) {
|
||||
try {
|
||||
var response = await _inAppBrowser.onLoadResourceCustomScheme(scheme, url);
|
||||
return (response != null) ? response.toJson(): null;
|
||||
var response =
|
||||
await _inAppBrowser.onLoadResourceCustomScheme(scheme, url);
|
||||
return (response != null) ? response.toJson() : null;
|
||||
} catch (error) {
|
||||
print(error);
|
||||
return null;
|
||||
|
@ -495,15 +547,19 @@ class InAppWebViewController {
|
|||
String url = call.arguments["url"];
|
||||
if (_widget != null && _widget.onTargetBlank != null)
|
||||
_widget.onTargetBlank(this, url);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onTargetBlank(url);
|
||||
else if (_inAppBrowser != null) _inAppBrowser.onTargetBlank(url);
|
||||
break;
|
||||
case "onGeolocationPermissionsShowPrompt":
|
||||
String origin = call.arguments["origin"];
|
||||
if (_widget != null && _widget.onGeolocationPermissionsShowPrompt != null)
|
||||
return (await _widget.onGeolocationPermissionsShowPrompt(this, origin))?.toMap();
|
||||
if (_widget != null &&
|
||||
_widget.onGeolocationPermissionsShowPrompt != null)
|
||||
return (await _widget.onGeolocationPermissionsShowPrompt(
|
||||
this, origin))
|
||||
?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onGeolocationPermissionsShowPrompt(origin))?.toMap();
|
||||
return (await _inAppBrowser
|
||||
.onGeolocationPermissionsShowPrompt(origin))
|
||||
?.toMap();
|
||||
break;
|
||||
case "onJsAlert":
|
||||
String message = call.arguments["message"];
|
||||
|
@ -523,17 +579,22 @@ class InAppWebViewController {
|
|||
String message = call.arguments["message"];
|
||||
String defaultValue = call.arguments["defaultValue"];
|
||||
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)
|
||||
return (await _inAppBrowser.onJsPrompt(message, defaultValue))?.toMap();
|
||||
return (await _inAppBrowser.onJsPrompt(message, defaultValue))
|
||||
?.toMap();
|
||||
break;
|
||||
case "onSafeBrowsingHit":
|
||||
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)
|
||||
return (await _widget.onSafeBrowsingHit(this, url, threatType))?.toMap();
|
||||
return (await _widget.onSafeBrowsingHit(this, url, threatType))
|
||||
?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onSafeBrowsingHit(url, threatType))?.toMap();
|
||||
return (await _inAppBrowser.onSafeBrowsingHit(url, threatType))
|
||||
?.toMap();
|
||||
break;
|
||||
case "onReceivedHttpAuthRequest":
|
||||
String host = call.arguments["host"];
|
||||
|
@ -541,12 +602,17 @@ class InAppWebViewController {
|
|||
String realm = call.arguments["realm"];
|
||||
int port = call.arguments["port"];
|
||||
int previousFailureCount = call.arguments["previousFailureCount"];
|
||||
var protectionSpace = ProtectionSpace(host: host, protocol: protocol, realm: realm, port: port);
|
||||
var challenge = HttpAuthChallenge(previousFailureCount: previousFailureCount, protectionSpace: protectionSpace);
|
||||
var protectionSpace = ProtectionSpace(
|
||||
host: host, protocol: protocol, realm: realm, port: port);
|
||||
var challenge = HttpAuthChallenge(
|
||||
previousFailureCount: previousFailureCount,
|
||||
protectionSpace: protectionSpace);
|
||||
if (_widget != null && _widget.onReceivedHttpAuthRequest != null)
|
||||
return (await _widget.onReceivedHttpAuthRequest(this, challenge))?.toMap();
|
||||
return (await _widget.onReceivedHttpAuthRequest(this, challenge))
|
||||
?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onReceivedHttpAuthRequest(challenge))?.toMap();
|
||||
return (await _inAppBrowser.onReceivedHttpAuthRequest(challenge))
|
||||
?.toMap();
|
||||
break;
|
||||
case "onReceivedServerTrustAuthRequest":
|
||||
String host = call.arguments["host"];
|
||||
|
@ -556,33 +622,47 @@ class InAppWebViewController {
|
|||
int error = call.arguments["error"];
|
||||
String message = call.arguments["message"];
|
||||
Uint8List serverCertificate = call.arguments["serverCertificate"];
|
||||
var protectionSpace = ProtectionSpace(host: host, protocol: protocol, realm: realm, port: port);
|
||||
var challenge = ServerTrustChallenge(protectionSpace: protectionSpace, error: error, message: message, serverCertificate: serverCertificate);
|
||||
var protectionSpace = ProtectionSpace(
|
||||
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)
|
||||
return (await _widget.onReceivedServerTrustAuthRequest(this, challenge))?.toMap();
|
||||
return (await _widget.onReceivedServerTrustAuthRequest(
|
||||
this, challenge))
|
||||
?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onReceivedServerTrustAuthRequest(challenge))?.toMap();
|
||||
return (await _inAppBrowser
|
||||
.onReceivedServerTrustAuthRequest(challenge))
|
||||
?.toMap();
|
||||
break;
|
||||
case "onReceivedClientCertRequest":
|
||||
String host = call.arguments["host"];
|
||||
String protocol = call.arguments["protocol"];
|
||||
String realm = call.arguments["realm"];
|
||||
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);
|
||||
if (_widget != null && _widget.onReceivedClientCertRequest != null)
|
||||
return (await _widget.onReceivedClientCertRequest(this, challenge))?.toMap();
|
||||
return (await _widget.onReceivedClientCertRequest(this, challenge))
|
||||
?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onReceivedClientCertRequest(challenge))?.toMap();
|
||||
return (await _inAppBrowser.onReceivedClientCertRequest(challenge))
|
||||
?.toMap();
|
||||
break;
|
||||
case "onFindResultReceived":
|
||||
int activeMatchOrdinal = call.arguments["activeMatchOrdinal"];
|
||||
int numberOfMatches = call.arguments["numberOfMatches"];
|
||||
bool isDoneCounting = call.arguments["isDoneCounting"];
|
||||
if (_widget != null && _widget.onFindResultReceived != null)
|
||||
_widget.onFindResultReceived(this, activeMatchOrdinal, numberOfMatches, isDoneCounting);
|
||||
_widget.onFindResultReceived(
|
||||
this, activeMatchOrdinal, numberOfMatches, isDoneCounting);
|
||||
else if (_inAppBrowser != null)
|
||||
_inAppBrowser.onFindResultReceived(activeMatchOrdinal, numberOfMatches, isDoneCounting);
|
||||
_inAppBrowser.onFindResultReceived(
|
||||
activeMatchOrdinal, numberOfMatches, isDoneCounting);
|
||||
break;
|
||||
case "onNavigationStateChange":
|
||||
String url = call.arguments["url"];
|
||||
|
@ -595,24 +675,34 @@ class InAppWebViewController {
|
|||
String origin = call.arguments["origin"];
|
||||
List<String> resources = call.arguments["resources"].cast<String>();
|
||||
if (_widget != null && _widget.onPermissionRequest != null)
|
||||
return (await _widget.onPermissionRequest(this, origin, resources))?.toMap();
|
||||
return (await _widget.onPermissionRequest(this, origin, resources))
|
||||
?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onPermissionRequest(origin, resources))?.toMap();
|
||||
return (await _inAppBrowser.onPermissionRequest(origin, resources))
|
||||
?.toMap();
|
||||
break;
|
||||
case "onCallJsHandler":
|
||||
String handlerName = call.arguments["handlerName"];
|
||||
// decode args to json
|
||||
List<dynamic> args = jsonDecode(call.arguments["args"]);
|
||||
|
||||
switch(handlerName) {
|
||||
switch (handlerName) {
|
||||
case "onLoadResource":
|
||||
Map<dynamic, dynamic> argMap = args[0];
|
||||
String initiatorType = argMap["initiatorType"];
|
||||
String url = argMap["name"];
|
||||
double startTime = argMap["startTime"] is int ? argMap["startTime"].toDouble() : argMap["startTime"];
|
||||
double duration = argMap["duration"] is int ? argMap["duration"].toDouble() : argMap["duration"];
|
||||
double startTime = argMap["startTime"] is int
|
||||
? argMap["startTime"].toDouble()
|
||||
: argMap["startTime"];
|
||||
double duration = argMap["duration"] is int
|
||||
? argMap["duration"].toDouble()
|
||||
: argMap["duration"];
|
||||
|
||||
var response = new LoadedResource(initiatorType: initiatorType, url: url, startTime: startTime, duration: duration);
|
||||
var response = new LoadedResource(
|
||||
initiatorType: initiatorType,
|
||||
url: url,
|
||||
startTime: startTime,
|
||||
duration: duration);
|
||||
|
||||
if (_widget != null && _widget.onLoadResource != null)
|
||||
_widget.onLoadResource(this, response);
|
||||
|
@ -631,12 +721,23 @@ class InAppWebViewController {
|
|||
AjaxRequestHeaders headers = AjaxRequestHeaders(argMap["headers"]);
|
||||
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)
|
||||
return jsonEncode(await _widget.shouldInterceptAjaxRequest(this, request));
|
||||
return jsonEncode(
|
||||
await _widget.shouldInterceptAjaxRequest(this, request));
|
||||
else if (_inAppBrowser != null)
|
||||
return jsonEncode(await _inAppBrowser.shouldInterceptAjaxRequest(request));
|
||||
return jsonEncode(
|
||||
await _inAppBrowser.shouldInterceptAjaxRequest(request));
|
||||
return null;
|
||||
case "onAjaxReadyStateChange":
|
||||
Map<dynamic, dynamic> argMap = args[0];
|
||||
|
@ -658,14 +759,31 @@ class InAppWebViewController {
|
|||
String statusText = argMap["statusText"];
|
||||
Map<dynamic, dynamic> responseHeaders = argMap["responseHeaders"];
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
if (_widget != null && _widget.onAjaxReadyStateChange != null)
|
||||
return jsonEncode(await _widget.onAjaxReadyStateChange(this, request));
|
||||
return jsonEncode(
|
||||
await _widget.onAjaxReadyStateChange(this, request));
|
||||
else if (_inAppBrowser != null)
|
||||
return jsonEncode(await _inAppBrowser.onAjaxReadyStateChange(request));
|
||||
return jsonEncode(
|
||||
await _inAppBrowser.onAjaxReadyStateChange(request));
|
||||
return null;
|
||||
case "onAjaxProgress":
|
||||
Map<dynamic, dynamic> argMap = args[0];
|
||||
|
@ -688,11 +806,31 @@ class InAppWebViewController {
|
|||
Map<dynamic, dynamic> responseHeaders = argMap["responseHeaders"];
|
||||
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"],
|
||||
loaded: eventMap["loaded"],
|
||||
total: eventMap["total"],
|
||||
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);
|
||||
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)
|
||||
return jsonEncode(await _widget.onAjaxProgress(this, request));
|
||||
|
@ -706,7 +844,9 @@ class InAppWebViewController {
|
|||
Map<dynamic, dynamic> headers = argMap["headers"];
|
||||
Uint8List body = Uint8List.fromList(argMap["body"].cast<int>());
|
||||
String mode = argMap["mode"];
|
||||
FetchRequestCredential credentials = FetchRequest.createFetchRequestCredentialFromMap(argMap["credentials"]);
|
||||
FetchRequestCredential credentials =
|
||||
FetchRequest.createFetchRequestCredentialFromMap(
|
||||
argMap["credentials"]);
|
||||
String cache = argMap["cache"];
|
||||
String redirect = argMap["redirect"];
|
||||
String referrer = argMap["referrer"];
|
||||
|
@ -714,13 +854,26 @@ class InAppWebViewController {
|
|||
String integrity = argMap["integrity"];
|
||||
bool keepalive = argMap["keepalive"];
|
||||
|
||||
var request = new FetchRequest(url: url, method: method, headers: headers, body: body, mode: mode, credentials: credentials,
|
||||
cache: cache, redirect: redirect, referrer: referrer, referrerPolicy: referrerPolicy, integrity: integrity, keepalive: keepalive);
|
||||
var request = new FetchRequest(
|
||||
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)
|
||||
return jsonEncode(await _widget.shouldInterceptFetchRequest(this, request));
|
||||
return jsonEncode(
|
||||
await _widget.shouldInterceptFetchRequest(this, request));
|
||||
else if (_inAppBrowser != null)
|
||||
return jsonEncode(await _inAppBrowser.shouldInterceptFetchRequest(request));
|
||||
return jsonEncode(
|
||||
await _inAppBrowser.shouldInterceptFetchRequest(request));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -777,10 +930,11 @@ class InAppWebViewController {
|
|||
Future<String> getHtml() async {
|
||||
var html = "";
|
||||
InAppWebViewWidgetOptions options = await getOptions();
|
||||
if (options != null && options.inAppWebViewOptions.javaScriptEnabled == true) {
|
||||
html = await evaluateJavascript(source: "window.document.getElementsByTagName('html')[0].outerHTML;");
|
||||
if (html != null && html.isNotEmpty)
|
||||
return html;
|
||||
if (options != null &&
|
||||
options.inAppWebViewOptions.javaScriptEnabled == true) {
|
||||
html = await evaluateJavascript(
|
||||
source: "window.document.getElementsByTagName('html')[0].outerHTML;");
|
||||
if (html != null && html.isNotEmpty) return html;
|
||||
}
|
||||
|
||||
var webviewUrl = await getUrl();
|
||||
|
@ -789,13 +943,13 @@ class InAppWebViewController {
|
|||
var assetPath = assetPathSplitted[assetPathSplitted.length - 1];
|
||||
var bytes = await rootBundle.load(assetPath);
|
||||
html = utf8.decode(bytes.buffer.asUint8List());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
HttpClient client = new HttpClient();
|
||||
var url = Uri.parse(webviewUrl);
|
||||
try {
|
||||
var htmlRequest = await client.getUrl(url);
|
||||
html = await (await htmlRequest.close()).transform(Utf8Decoder()).join();
|
||||
html =
|
||||
await (await htmlRequest.close()).transform(Utf8Decoder()).join();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
@ -809,12 +963,14 @@ class InAppWebViewController {
|
|||
|
||||
HttpClient client = new HttpClient();
|
||||
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;
|
||||
|
||||
var html = await getHtml();
|
||||
if (html.isEmpty) {
|
||||
return favicons;
|
||||
return favicons;
|
||||
}
|
||||
|
||||
var assetPathBase;
|
||||
|
@ -835,14 +991,18 @@ class InAppWebViewController {
|
|||
if (manifestUrl.startsWith("/")) {
|
||||
manifestUrl = manifestUrl.substring(1);
|
||||
}
|
||||
manifestUrl = ((assetPathBase == null) ? url.scheme + "://" + url.host + "/" : assetPathBase) + manifestUrl;
|
||||
manifestUrl = ((assetPathBase == null)
|
||||
? url.scheme + "://" + url.host + "/"
|
||||
: assetPathBase) +
|
||||
manifestUrl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!attributes["rel"].contains("icon")) {
|
||||
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
|
||||
|
@ -850,7 +1010,7 @@ class InAppWebViewController {
|
|||
var faviconUrl = url.scheme + "://" + url.host + "/favicon.ico";
|
||||
await client.headUrl(Uri.parse(faviconUrl));
|
||||
favicons.add(Favicon(url: faviconUrl, rel: "shortcut icon"));
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
print("/favicon.ico file not found: " + e.toString());
|
||||
}
|
||||
|
||||
|
@ -864,16 +1024,19 @@ class InAppWebViewController {
|
|||
try {
|
||||
manifestRequest = await client.getUrl(Uri.parse(manifestUrl));
|
||||
manifestResponse = await manifestRequest.close();
|
||||
manifestFound = manifestResponse.statusCode == 200 && manifestResponse.headers.contentType?.mimeType == "application/json";
|
||||
} catch(e) {
|
||||
manifestFound = manifestResponse.statusCode == 200 &&
|
||||
manifestResponse.headers.contentType?.mimeType == "application/json";
|
||||
} catch (e) {
|
||||
print("Manifest file not found: " + e.toString());
|
||||
}
|
||||
|
||||
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")) {
|
||||
for(Map<String, dynamic> icon in manifest["icons"]) {
|
||||
favicons.addAll(_createFavicons(url, assetPathBase, icon["src"], icon["rel"], icon["sizes"], true));
|
||||
for (Map<String, dynamic> icon in manifest["icons"]) {
|
||||
favicons.addAll(_createFavicons(url, assetPathBase, icon["src"],
|
||||
icon["rel"], icon["sizes"], true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -885,7 +1048,8 @@ class InAppWebViewController {
|
|||
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<String> urlSplitted = urlIcon.split("/");
|
||||
|
@ -893,17 +1057,26 @@ class InAppWebViewController {
|
|||
if (urlIcon.startsWith("/")) {
|
||||
urlIcon = urlIcon.substring(1);
|
||||
}
|
||||
urlIcon = ((assetPathBase == null) ? url.scheme + "://" + url.host + "/" : assetPathBase) + urlIcon;
|
||||
urlIcon = ((assetPathBase == null)
|
||||
? url.scheme + "://" + url.host + "/"
|
||||
: assetPathBase) +
|
||||
urlIcon;
|
||||
}
|
||||
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") {
|
||||
List<String> sizesSplitted = sizes.split(" ");
|
||||
for (String size in sizesSplitted) {
|
||||
int width = int.parse(size.split("x")[0]);
|
||||
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 {
|
||||
favicons.add(Favicon(url: urlIcon, rel: rel, width: null, height: null));
|
||||
|
@ -913,7 +1086,8 @@ class InAppWebViewController {
|
|||
}
|
||||
|
||||
///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);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
|
||||
|
@ -926,7 +1100,8 @@ class InAppWebViewController {
|
|||
}
|
||||
|
||||
///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(postData != null);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -942,7 +1117,11 @@ class InAppWebViewController {
|
|||
///Loads the given [data] into this WebView, using [baseUrl] as the base URL for the content.
|
||||
///The [mimeType] parameter specifies the format of the data.
|
||||
///The [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);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
|
||||
|
@ -985,7 +1164,9 @@ class InAppWebViewController {
|
|||
///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);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
|
||||
|
@ -1107,8 +1288,7 @@ class InAppWebViewController {
|
|||
}
|
||||
args.putIfAbsent('source', () => source);
|
||||
var data = await _channel.invokeMethod('evaluateJavascript', args);
|
||||
if (data != null && Platform.isAndroid)
|
||||
data = json.decode(data);
|
||||
if (data != null && Platform.isAndroid) data = json.decode(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1122,9 +1302,10 @@ class InAppWebViewController {
|
|||
args.putIfAbsent('urlFile', () => urlFile);
|
||||
await _channel.invokeMethod('injectJavascriptFileFromUrl', args);
|
||||
}
|
||||
|
||||
|
||||
///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);
|
||||
await evaluateJavascript(source: source);
|
||||
}
|
||||
|
@ -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));
|
||||
this.javaScriptHandlersMap[handlerName] = (callback);
|
||||
}
|
||||
|
@ -1209,7 +1392,8 @@ class InAppWebViewController {
|
|||
///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 `null` if [handlerName] was not found.
|
||||
JavaScriptHandlerCallback removeJavaScriptHandler({@required String handlerName}) {
|
||||
JavaScriptHandlerCallback removeJavaScriptHandler(
|
||||
{@required String handlerName}) {
|
||||
return this.javaScriptHandlersMap.remove(handlerName);
|
||||
}
|
||||
|
||||
|
@ -1252,15 +1436,20 @@ class InAppWebViewController {
|
|||
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
|
||||
}
|
||||
|
||||
InAppWebViewWidgetOptions inAppWebViewWidgetOptions = InAppWebViewWidgetOptions();
|
||||
Map<dynamic, dynamic> options = await _channel.invokeMethod('getOptions', args);
|
||||
InAppWebViewWidgetOptions inAppWebViewWidgetOptions =
|
||||
InAppWebViewWidgetOptions();
|
||||
Map<dynamic, dynamic> options =
|
||||
await _channel.invokeMethod('getOptions', args);
|
||||
if (options != null) {
|
||||
options = options.cast<String, dynamic>();
|
||||
inAppWebViewWidgetOptions.inAppWebViewOptions = InAppWebViewOptions.fromMap(options);
|
||||
inAppWebViewWidgetOptions.inAppWebViewOptions =
|
||||
InAppWebViewOptions.fromMap(options);
|
||||
if (Platform.isAndroid)
|
||||
inAppWebViewWidgetOptions.androidInAppWebViewOptions = AndroidInAppWebViewOptions.fromMap(options);
|
||||
inAppWebViewWidgetOptions.androidInAppWebViewOptions =
|
||||
AndroidInAppWebViewOptions.fromMap(options);
|
||||
else if (Platform.isIOS)
|
||||
inAppWebViewWidgetOptions.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options);
|
||||
inAppWebViewWidgetOptions.iosInAppWebViewOptions =
|
||||
IosInAppWebViewOptions.fromMap(options);
|
||||
}
|
||||
|
||||
return inAppWebViewWidgetOptions;
|
||||
|
@ -1276,7 +1465,8 @@ class InAppWebViewController {
|
|||
_inAppBrowser.throwIsNotOpened();
|
||||
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>();
|
||||
|
||||
List<dynamic> historyListMap = result["history"];
|
||||
|
@ -1285,9 +1475,14 @@ class InAppWebViewController {
|
|||
int currentIndex = result["currentIndex"];
|
||||
|
||||
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];
|
||||
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);
|
||||
}
|
||||
|
@ -1434,12 +1629,14 @@ class InAppWebViewController {
|
|||
|
||||
///Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerCss()].
|
||||
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()].
|
||||
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.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,7 @@ import 'content_blocker.dart';
|
|||
import 'types.dart';
|
||||
|
||||
class AndroidOptions {}
|
||||
|
||||
class IosOptions {}
|
||||
|
||||
class WebViewOptions {
|
||||
|
@ -37,85 +38,130 @@ class ChromeSafariBrowserOptions {
|
|||
}
|
||||
|
||||
///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`.
|
||||
bool useShouldOverrideUrlLoading;
|
||||
|
||||
///Set to `true` to be able to listen at the [onLoadResource] event. The default value is `false`.
|
||||
bool useOnLoadResource;
|
||||
|
||||
///Set to `true` to be able to listen at the [onDownloadStart] event. The default value is `false`.
|
||||
bool useOnDownloadStart;
|
||||
|
||||
///Set to `true` to be able to listen at the [onTargetBlank] event. The default value is `false`.
|
||||
bool useOnTargetBlank;
|
||||
|
||||
///Set to `true` to have all the browser's cache cleared before the new window is opened. The default value is `false`.
|
||||
bool clearCache;
|
||||
|
||||
///Sets the user-agent for the WebView.
|
||||
///
|
||||
///**NOTE**: available on iOS 9.0+.
|
||||
String userAgent;
|
||||
|
||||
///Append to the existing user-agent. Setting userAgent will override this.
|
||||
///
|
||||
///**NOTE**: available on Android 17+ and on iOS 9.0+.
|
||||
String applicationNameForUserAgent;
|
||||
|
||||
///Set to `true` to enable JavaScript. The default value is `true`.
|
||||
bool javaScriptEnabled;
|
||||
|
||||
///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`.
|
||||
///
|
||||
///**NOTE**: on iOS the debugging mode is always enabled.
|
||||
bool debuggingEnabled;
|
||||
|
||||
///Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`.
|
||||
bool javaScriptCanOpenWindowsAutomatically;
|
||||
|
||||
///Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`.
|
||||
///
|
||||
///**NOTE**: available on iOS 10.0+.
|
||||
bool mediaPlaybackRequiresUserGesture;
|
||||
|
||||
///Sets the minimum font size. The default value is `8` for Android, `0` for iOS.
|
||||
int minimumFontSize;
|
||||
|
||||
///Define whether the vertical scrollbar should be drawn or not. The default value is `true`.
|
||||
bool verticalScrollBarEnabled;
|
||||
|
||||
///Define whether the horizontal scrollbar should be drawn or not. The default value is `true`.
|
||||
bool horizontalScrollBarEnabled;
|
||||
|
||||
///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+.
|
||||
List<String> resourceCustomSchemes;
|
||||
|
||||
///List of [ContentBlocker] that are a set of rules used to block content in the browser window.
|
||||
///
|
||||
///**NOTE**: available on iOS 11.0+.
|
||||
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].
|
||||
///
|
||||
///**NOTE**: available on iOS 13.0+.
|
||||
InAppWebViewUserPreferredContentMode preferredContentMode;
|
||||
|
||||
///Set to `true` to be able to listen at the [shouldInterceptAjaxRequest] event. The default value is `false`.
|
||||
bool useShouldInterceptAjaxRequest;
|
||||
|
||||
///Set to `true` to be able to listen at the [shouldInterceptFetchRequest] event. The default value is `false`.
|
||||
bool useShouldInterceptFetchRequest;
|
||||
|
||||
///Set to `true` to open a browser window with incognito mode. The default value is `false`.
|
||||
///
|
||||
///**NOTE**: available on iOS 9.0+.
|
||||
bool incognito;
|
||||
|
||||
///Sets whether WebView should use browser caching. The default value is `true`.
|
||||
///
|
||||
///**NOTE**: available on iOS 9.0+.
|
||||
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`.
|
||||
bool transparentBackground;
|
||||
|
||||
///Set to `true` to disable vertical scroll. The default value is `false`.
|
||||
bool disableVerticalScroll;
|
||||
|
||||
///Set to `true` to disable horizontal scroll. The default value is `false`.
|
||||
bool disableHorizontalScroll;
|
||||
|
||||
InAppWebViewOptions({this.useShouldOverrideUrlLoading = false, this.useOnLoadResource = false, this.useOnDownloadStart = false, this.useOnTargetBlank = 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)
|
||||
this.minimumFontSize = Platform.isAndroid ? 8 : 0;
|
||||
assert(!this.resourceCustomSchemes.contains("http") && !this.resourceCustomSchemes.contains("https"));
|
||||
}
|
||||
InAppWebViewOptions(
|
||||
{this.useShouldOverrideUrlLoading = false,
|
||||
this.useOnLoadResource = false,
|
||||
this.useOnDownloadStart = false,
|
||||
this.useOnTargetBlank = 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)
|
||||
this.minimumFontSize = Platform.isAndroid ? 8 : 0;
|
||||
assert(!this.resourceCustomSchemes.contains("http") &&
|
||||
!this.resourceCustomSchemes.contains("https"));
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -134,7 +180,8 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
|
|||
"applicationNameForUserAgent": applicationNameForUserAgent,
|
||||
"javaScriptEnabled": javaScriptEnabled,
|
||||
"debuggingEnabled": debuggingEnabled,
|
||||
"javaScriptCanOpenWindowsAutomatically": javaScriptCanOpenWindowsAutomatically,
|
||||
"javaScriptCanOpenWindowsAutomatically":
|
||||
javaScriptCanOpenWindowsAutomatically,
|
||||
"mediaPlaybackRequiresUserGesture": mediaPlaybackRequiresUserGesture,
|
||||
"verticalScrollBarEnabled": verticalScrollBarEnabled,
|
||||
"horizontalScrollBarEnabled": horizontalScrollBarEnabled,
|
||||
|
@ -151,15 +198,14 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
|
|||
};
|
||||
}
|
||||
|
||||
@override
|
||||
static InAppWebViewOptions fromMap(Map<String, dynamic> map) {
|
||||
List<ContentBlocker> contentBlockers = [];
|
||||
List<dynamic> contentBlockersMapList = map["contentBlockers"];
|
||||
if (contentBlockersMapList != null) {
|
||||
contentBlockersMapList.forEach((contentBlocker) {
|
||||
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
|
|||
options.applicationNameForUserAgent = map["applicationNameForUserAgent"];
|
||||
options.javaScriptEnabled = map["javaScriptEnabled"];
|
||||
options.debuggingEnabled = map["debuggingEnabled"];
|
||||
options.javaScriptCanOpenWindowsAutomatically = map["javaScriptCanOpenWindowsAutomatically"];
|
||||
options.mediaPlaybackRequiresUserGesture = map["mediaPlaybackRequiresUserGesture"];
|
||||
options.javaScriptCanOpenWindowsAutomatically =
|
||||
map["javaScriptCanOpenWindowsAutomatically"];
|
||||
options.mediaPlaybackRequiresUserGesture =
|
||||
map["mediaPlaybackRequiresUserGesture"];
|
||||
options.verticalScrollBarEnabled = map["verticalScrollBarEnabled"];
|
||||
options.horizontalScrollBarEnabled = map["horizontalScrollBarEnabled"];
|
||||
options.resourceCustomSchemes = List<String>.from(map["resourceCustomSchemes"] ?? []);
|
||||
options.resourceCustomSchemes =
|
||||
List<String>.from(map["resourceCustomSchemes"] ?? []);
|
||||
options.contentBlockers = contentBlockers;
|
||||
options.preferredContentMode = InAppWebViewUserPreferredContentMode.fromValue(map["preferredContentMode"]);
|
||||
options.useShouldInterceptAjaxRequest = map["useShouldInterceptAjaxRequest"];
|
||||
options.useShouldInterceptFetchRequest = map["useShouldInterceptFetchRequest"];
|
||||
options.preferredContentMode =
|
||||
InAppWebViewUserPreferredContentMode.fromValue(
|
||||
map["preferredContentMode"]);
|
||||
options.useShouldInterceptAjaxRequest =
|
||||
map["useShouldInterceptAjaxRequest"];
|
||||
options.useShouldInterceptFetchRequest =
|
||||
map["useShouldInterceptFetchRequest"];
|
||||
options.incognito = map["incognito"];
|
||||
options.cacheEnabled = map["cacheEnabled"];
|
||||
options.transparentBackground = map["transparentBackground"];
|
||||
|
@ -192,92 +245,124 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
|
|||
}
|
||||
|
||||
///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`.
|
||||
int textZoom;
|
||||
|
||||
///Set to `true` to have the session cookie cache cleared before the new window is opened.
|
||||
bool clearSessionCache;
|
||||
|
||||
///Set to `true` if the WebView should use its built-in zoom mechanisms. The default value is `false`.
|
||||
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`.
|
||||
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`.
|
||||
bool supportZoom;
|
||||
|
||||
///Set to `true` if you want the database storage API is enabled. The default value is `false`.
|
||||
bool databaseEnabled;
|
||||
|
||||
///Set to `true` if you want the DOM storage API is enabled. The default value is `false`.
|
||||
bool domStorageEnabled;
|
||||
|
||||
///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 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`.
|
||||
bool useWideViewPort;
|
||||
|
||||
///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.
|
||||
///
|
||||
///**NOTE**: available on Android 26+.
|
||||
bool safeBrowsingEnabled;
|
||||
|
||||
///Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
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`.
|
||||
bool allowContentAccess;
|
||||
|
||||
///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`.
|
||||
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.
|
||||
///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`.
|
||||
bool allowFileAccessFromFileURLs;
|
||||
|
||||
///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.
|
||||
///This includes access to content from other file scheme URLs. The default value is `false`.
|
||||
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.
|
||||
///This option is used one time: repeated calls are ignored.
|
||||
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`.
|
||||
bool blockNetworkImage;
|
||||
|
||||
///Sets whether the WebView should not load resources from the network. The default value is `false`.
|
||||
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.
|
||||
///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;
|
||||
|
||||
///Sets the cursive font family name. The default value is `"cursive"`.
|
||||
String cursiveFontFamily;
|
||||
|
||||
///Sets the default fixed font size. The default value is `16`.
|
||||
int defaultFixedFontSize;
|
||||
|
||||
///Sets the default font size. The default value is `16`.
|
||||
int defaultFontSize;
|
||||
|
||||
///Sets the default text encoding name to use when decoding html pages. The default value is `"UTF-8"`.
|
||||
String defaultTextEncodingName;
|
||||
|
||||
///Disables the action mode menu items according to menuItems flag.
|
||||
///
|
||||
///**NOTE**: available on Android 24+.
|
||||
AndroidInAppWebViewModeMenuItem disabledActionModeMenuItems;
|
||||
|
||||
///Sets the fantasy font family name. The default value is `"fantasy"`.
|
||||
String fantasyFontFamily;
|
||||
|
||||
///Sets the fixed font family name. The default value is `"monospace"`.
|
||||
String fixedFontFamily;
|
||||
|
||||
///Set the force dark mode for this WebView. The default value is [AndroidInAppWebViewForceDark.FORCE_DARK_OFF].
|
||||
///
|
||||
///**NOTE**: available on Android 29+.
|
||||
AndroidInAppWebViewForceDark forceDark;
|
||||
|
||||
///Sets whether Geolocation API is enabled. The default value is `true`.
|
||||
bool geolocationEnabled;
|
||||
|
||||
///Sets the underlying layout algorithm. This will cause a re-layout of the WebView.
|
||||
AndroidInAppWebViewLayoutAlgorithm layoutAlgorithm;
|
||||
|
||||
///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.
|
||||
///The default value is `false`.
|
||||
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.
|
||||
///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`.
|
||||
bool loadsImagesAutomatically;
|
||||
|
||||
///Sets the minimum logical font size. The default is `8`.
|
||||
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].
|
||||
///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.
|
||||
|
@ -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.
|
||||
///The default is `0`.
|
||||
int initialScale;
|
||||
|
||||
///Tells the WebView whether it needs to set a node. The default value is `true`.
|
||||
bool needInitialFocus;
|
||||
|
||||
///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.
|
||||
///Offscreen WebViews in this mode use more memory. The default value is `false`.
|
||||
///
|
||||
///**NOTE**: available on Android 23+.
|
||||
bool offscreenPreRaster;
|
||||
|
||||
///Sets the sans-serif font family name. The default value is `"sans-serif"`.
|
||||
String sansSerifFontFamily;
|
||||
|
||||
///Sets the serif font family name. The default value is `"sans-serif"`.
|
||||
String serifFontFamily;
|
||||
|
||||
///Sets the standard font family name. The default value is `"sans-serif"`.
|
||||
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.
|
||||
///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;
|
||||
|
||||
///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.
|
||||
///The default value is `true`.
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
bool thirdPartyCookiesEnabled;
|
||||
|
||||
///Boolean value to enable Hardware Acceleration in the WebView.
|
||||
///The default value is `true`.
|
||||
bool hardwareAcceleration;
|
||||
|
||||
AndroidInAppWebViewOptions({this.textZoom = 100, this.clearSessionCache = false, this.builtInZoomControls = false, this.displayZoomControls = false, this.supportZoom = true, this.databaseEnabled = false,
|
||||
this.domStorageEnabled = false, 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
|
||||
});
|
||||
AndroidInAppWebViewOptions(
|
||||
{this.textZoom = 100,
|
||||
this.clearSessionCache = false,
|
||||
this.builtInZoomControls = false,
|
||||
this.displayZoomControls = false,
|
||||
this.supportZoom = true,
|
||||
this.databaseEnabled = false,
|
||||
this.domStorageEnabled = false,
|
||||
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
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -369,7 +493,6 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr
|
|||
};
|
||||
}
|
||||
|
||||
@override
|
||||
static AndroidInAppWebViewOptions fromMap(Map<String, dynamic> map) {
|
||||
AndroidInAppWebViewOptions options = new AndroidInAppWebViewOptions();
|
||||
options.textZoom = map["textZoom"];
|
||||
|
@ -381,25 +504,32 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr
|
|||
options.domStorageEnabled = map["domStorageEnabled"];
|
||||
options.useWideViewPort = map["useWideViewPort"];
|
||||
options.safeBrowsingEnabled = map["safeBrowsingEnabled"];
|
||||
options.mixedContentMode = AndroidInAppWebViewMixedContentMode.fromValue(map["mixedContentMode"]);
|
||||
options.mixedContentMode =
|
||||
AndroidInAppWebViewMixedContentMode.fromValue(map["mixedContentMode"]);
|
||||
options.allowContentAccess = map["allowContentAccess"];
|
||||
options.allowFileAccess = map["allowFileAccess"];
|
||||
options.allowFileAccessFromFileURLs = map["allowFileAccessFromFileURLs"];
|
||||
options.allowUniversalAccessFromFileURLs = map["allowUniversalAccessFromFileURLs"];
|
||||
options.allowUniversalAccessFromFileURLs =
|
||||
map["allowUniversalAccessFromFileURLs"];
|
||||
options.appCachePath = map["appCachePath"];
|
||||
options.blockNetworkImage = map["blockNetworkImage"];
|
||||
options.blockNetworkLoads = map["blockNetworkLoads"];
|
||||
options.cacheMode = AndroidInAppWebViewCacheMode.fromValue(map["cacheMode"]);
|
||||
options.cacheMode =
|
||||
AndroidInAppWebViewCacheMode.fromValue(map["cacheMode"]);
|
||||
options.cursiveFontFamily = map["cursiveFontFamily"];
|
||||
options.defaultFixedFontSize = map["defaultFixedFontSize"];
|
||||
options.defaultFontSize = map["defaultFontSize"];
|
||||
options.defaultTextEncodingName = map["defaultTextEncodingName"];
|
||||
options.disabledActionModeMenuItems = AndroidInAppWebViewModeMenuItem.fromValue(map["disabledActionModeMenuItems"]);
|
||||
options.disabledActionModeMenuItems =
|
||||
AndroidInAppWebViewModeMenuItem.fromValue(
|
||||
map["disabledActionModeMenuItems"]);
|
||||
options.fantasyFontFamily = map["fantasyFontFamily"];
|
||||
options.fixedFontFamily = map["fixedFontFamily"];
|
||||
options.forceDark = AndroidInAppWebViewForceDark.fromValue(map["forceDark"]);
|
||||
options.forceDark =
|
||||
AndroidInAppWebViewForceDark.fromValue(map["forceDark"]);
|
||||
options.geolocationEnabled = map["geolocationEnabled"];
|
||||
options.layoutAlgorithm = AndroidInAppWebViewLayoutAlgorithm.fromValue(map["layoutAlgorithm"]);
|
||||
options.layoutAlgorithm =
|
||||
AndroidInAppWebViewLayoutAlgorithm.fromValue(map["layoutAlgorithm"]);
|
||||
options.loadWithOverviewMode = map["loadWithOverviewMode"];
|
||||
options.loadsImagesAutomatically = map["loadsImagesAutomatically"];
|
||||
options.minimumLogicalFontSize = map["minimumLogicalFontSize"];
|
||||
|
@ -417,57 +547,79 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr
|
|||
}
|
||||
|
||||
///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`.
|
||||
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`.
|
||||
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`.
|
||||
bool suppressesIncrementalRendering;
|
||||
|
||||
///Set to `true` to allow AirPlay. The default value is `true`.
|
||||
bool allowsAirPlayForMediaPlayback;
|
||||
|
||||
///Set to `true` to allow the horizontal swipe gestures trigger back-forward list navigations. The default value is `true`.
|
||||
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`.
|
||||
///
|
||||
///**NOTE**: available on iOS 9.0+.
|
||||
bool allowsLinkPreview;
|
||||
|
||||
///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`.
|
||||
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.
|
||||
///For this to work, add the `webkit-playsinline` attribute to any `<video>` elements. The default value is `false`.
|
||||
bool allowsInlineMediaPlayback;
|
||||
|
||||
///Set to `true` to allow HTML5 videos play picture-in-picture. The default value is `true`.
|
||||
///
|
||||
///**NOTE**: available on iOS 9.0+.
|
||||
bool allowsPictureInPictureMediaPlayback;
|
||||
|
||||
///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.
|
||||
///The default value is `true`.
|
||||
///
|
||||
///**NOTE**: available on iOS 13.0+.
|
||||
bool isFraudulentWebsiteWarningEnabled;
|
||||
|
||||
///The level of granularity with which the user can interactively select content in the web view.
|
||||
///The default value is [IosInAppWebViewSelectionGranularity.DYNAMIC]
|
||||
IosInAppWebViewSelectionGranularity selectionGranularity;
|
||||
|
||||
///Specifying a dataDetectoryTypes value adds interactivity to web content that matches the value.
|
||||
///For example, Safari adds a link to “apple.com” in the text “Visit apple.com” if the dataDetectorTypes property is set to [IosInAppWebViewDataDetectorTypes.LINK].
|
||||
///The default value is [IosInAppWebViewDataDetectorTypes.NONE].
|
||||
///
|
||||
///**NOTE**: available on iOS 10.0+.
|
||||
List<IosInAppWebViewDataDetectorTypes> dataDetectorTypes;
|
||||
|
||||
///Set `true` if shared cookies from `HTTPCookieStorage.shared` should used for every load request in the WebView.
|
||||
///The default value is `false`.
|
||||
///
|
||||
///**NOTE**: available on iOS 11.0+.
|
||||
bool sharedCookiesEnabled;
|
||||
|
||||
IosInAppWebViewOptions({this.disallowOverScroll = false, this.enableViewportScale = 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
|
||||
});
|
||||
IosInAppWebViewOptions(
|
||||
{this.disallowOverScroll = false,
|
||||
this.enableViewportScale = 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
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -481,11 +633,13 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio
|
|||
"enableViewportScale": enableViewportScale,
|
||||
"suppressesIncrementalRendering": suppressesIncrementalRendering,
|
||||
"allowsAirPlayForMediaPlayback": allowsAirPlayForMediaPlayback,
|
||||
"allowsBackForwardNavigationGestures": allowsBackForwardNavigationGestures,
|
||||
"allowsBackForwardNavigationGestures":
|
||||
allowsBackForwardNavigationGestures,
|
||||
"allowsLinkPreview": allowsLinkPreview,
|
||||
"ignoresViewportScaleLimits": ignoresViewportScaleLimits,
|
||||
"allowsInlineMediaPlayback": allowsInlineMediaPlayback,
|
||||
"allowsPictureInPictureMediaPlayback": allowsPictureInPictureMediaPlayback,
|
||||
"allowsPictureInPictureMediaPlayback":
|
||||
allowsPictureInPictureMediaPlayback,
|
||||
"isFraudulentWebsiteWarningEnabled": isFraudulentWebsiteWarningEnabled,
|
||||
"selectionGranularity": selectionGranularity.toValue(),
|
||||
"dataDetectorTypes": dataDetectorTypesList,
|
||||
|
@ -493,26 +647,34 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio
|
|||
};
|
||||
}
|
||||
|
||||
@override
|
||||
static IosInAppWebViewOptions fromMap(Map<String, dynamic> map) {
|
||||
List<IosInAppWebViewDataDetectorTypes> dataDetectorTypes = [];
|
||||
List<String> dataDetectorTypesList = List<String>.from(map["dataDetectorTypes"] ?? []);
|
||||
List<String> dataDetectorTypesList =
|
||||
List<String>.from(map["dataDetectorTypes"] ?? []);
|
||||
dataDetectorTypesList.forEach((dataDetectorType) {
|
||||
dataDetectorTypes.add(IosInAppWebViewDataDetectorTypes.fromValue(dataDetectorType));
|
||||
dataDetectorTypes
|
||||
.add(IosInAppWebViewDataDetectorTypes.fromValue(dataDetectorType));
|
||||
});
|
||||
|
||||
IosInAppWebViewOptions options = new IosInAppWebViewOptions();
|
||||
options.disallowOverScroll = map["disallowOverScroll"];
|
||||
options.enableViewportScale = map["enableViewportScale"];
|
||||
options.suppressesIncrementalRendering = map["suppressesIncrementalRendering"];
|
||||
options.allowsAirPlayForMediaPlayback = map["allowsAirPlayForMediaPlayback"];
|
||||
options.allowsBackForwardNavigationGestures = map["allowsBackForwardNavigationGestures"];
|
||||
options.suppressesIncrementalRendering =
|
||||
map["suppressesIncrementalRendering"];
|
||||
options.allowsAirPlayForMediaPlayback =
|
||||
map["allowsAirPlayForMediaPlayback"];
|
||||
options.allowsBackForwardNavigationGestures =
|
||||
map["allowsBackForwardNavigationGestures"];
|
||||
options.allowsLinkPreview = map["allowsLinkPreview"];
|
||||
options.ignoresViewportScaleLimits = map["ignoresViewportScaleLimits"];
|
||||
options.allowsInlineMediaPlayback = map["allowsInlineMediaPlayback"];
|
||||
options.allowsPictureInPictureMediaPlayback = map["allowsPictureInPictureMediaPlayback"];
|
||||
options.isFraudulentWebsiteWarningEnabled = map["isFraudulentWebsiteWarningEnabled"];
|
||||
options.selectionGranularity = IosInAppWebViewSelectionGranularity.fromValue(map["selectionGranularity"]);
|
||||
options.allowsPictureInPictureMediaPlayback =
|
||||
map["allowsPictureInPictureMediaPlayback"];
|
||||
options.isFraudulentWebsiteWarningEnabled =
|
||||
map["isFraudulentWebsiteWarningEnabled"];
|
||||
options.selectionGranularity =
|
||||
IosInAppWebViewSelectionGranularity.fromValue(
|
||||
map["selectionGranularity"]);
|
||||
options.dataDetectorTypes = dataDetectorTypes;
|
||||
options.sharedCookiesEnabled = map["sharedCookiesEnabled"];
|
||||
return options;
|
||||
|
@ -520,18 +682,26 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio
|
|||
}
|
||||
|
||||
///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.
|
||||
///The default value is `false`.
|
||||
bool hidden;
|
||||
|
||||
///Set to `false` to hide the toolbar at the top of the WebView. The default value is `true`.
|
||||
bool toolbarTop;
|
||||
|
||||
///Set the custom background color of the toolbar at the top.
|
||||
String toolbarTopBackgroundColor;
|
||||
|
||||
///Set to `true` to hide the url bar on the toolbar at the top. The default value is `false`.
|
||||
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
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -543,7 +713,6 @@ class InAppBrowserOptions implements BrowserOptions, AndroidOptions, IosOptions
|
|||
};
|
||||
}
|
||||
|
||||
@override
|
||||
static InAppBrowserOptions fromMap(Map<String, dynamic> map) {
|
||||
InAppBrowserOptions options = new InAppBrowserOptions();
|
||||
options.hidden = map["hidden"];
|
||||
|
@ -558,14 +727,21 @@ class InAppBrowserOptions implements BrowserOptions, AndroidOptions, IosOptions
|
|||
class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
|
||||
///Set to `true` if you want the title should be displayed. The default value is `false`.
|
||||
bool hideTitleBar;
|
||||
|
||||
///Set the action bar's title.
|
||||
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`.
|
||||
bool closeOnCannotGoBack;
|
||||
|
||||
///Set to `false` to hide the progress bar at the bottom of the toolbar at the top. The default value is `true`.
|
||||
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
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -577,7 +753,6 @@ class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
|
|||
};
|
||||
}
|
||||
|
||||
@override
|
||||
static AndroidInAppBrowserOptions fromMap(Map<String, dynamic> map) {
|
||||
AndroidInAppBrowserOptions options = new AndroidInAppBrowserOptions();
|
||||
options.hideTitleBar = map["hideTitleBar"];
|
||||
|
@ -592,24 +767,37 @@ class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
|
|||
class IosInAppBrowserOptions implements BrowserOptions, IosOptions {
|
||||
///Set to `false` to hide the toolbar at the bottom of the WebView. The default value is `true`.
|
||||
bool toolbarBottom;
|
||||
|
||||
///Set the custom background color of the toolbar at the bottom.
|
||||
String toolbarBottomBackgroundColor;
|
||||
|
||||
///Set to `true` to set the toolbar at the bottom translucent. The default value is `true`.
|
||||
bool toolbarBottomTranslucent;
|
||||
|
||||
///Set the custom text for the close button.
|
||||
String closeButtonCaption;
|
||||
|
||||
///Set the custom color for the close button.
|
||||
String closeButtonColor;
|
||||
|
||||
///Set the custom modal presentation style when presenting the WebView. The default value is [IosWebViewOptionsPresentationStyle.FULL_SCREEN].
|
||||
IosWebViewOptionsPresentationStyle presentationStyle;
|
||||
|
||||
///Set to the custom transition style when presenting the WebView. The default value is [IosWebViewOptionsTransitionStyle.COVER_VERTICAL].
|
||||
IosWebViewOptionsTransitionStyle transitionStyle;
|
||||
|
||||
///Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`.
|
||||
bool spinner;
|
||||
|
||||
IosInAppBrowserOptions({this.toolbarBottom = true, this.toolbarBottomBackgroundColor = "", this.toolbarBottomTranslucent = true, this.closeButtonCaption = "",
|
||||
this.closeButtonColor = "", this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN,
|
||||
this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL, this.spinner = true});
|
||||
IosInAppBrowserOptions(
|
||||
{this.toolbarBottom = true,
|
||||
this.toolbarBottomBackgroundColor = "",
|
||||
this.toolbarBottomTranslucent = true,
|
||||
this.closeButtonCaption = "",
|
||||
this.closeButtonColor = "",
|
||||
this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN,
|
||||
this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL,
|
||||
this.spinner = true});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -625,7 +813,6 @@ class IosInAppBrowserOptions implements BrowserOptions, IosOptions {
|
|||
};
|
||||
}
|
||||
|
||||
@override
|
||||
static IosInAppBrowserOptions fromMap(Map<String, dynamic> map) {
|
||||
IosInAppBrowserOptions options = new IosInAppBrowserOptions();
|
||||
options.toolbarBottom = map["toolbarBottom"];
|
||||
|
@ -633,27 +820,39 @@ class IosInAppBrowserOptions implements BrowserOptions, IosOptions {
|
|||
options.toolbarBottomTranslucent = map["toolbarBottomTranslucent"];
|
||||
options.closeButtonCaption = map["closeButtonCaption"];
|
||||
options.closeButtonColor = map["closeButtonColor"];
|
||||
options.presentationStyle = IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
|
||||
options.transitionStyle = IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
|
||||
options.presentationStyle =
|
||||
IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
|
||||
options.transitionStyle =
|
||||
IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
|
||||
options.spinner = map["spinner"];
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
///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`.
|
||||
bool addShareButton;
|
||||
|
||||
///Set to `false` if the title shouldn't be shown in the custom tab. The default value is `true`.
|
||||
bool showTitle;
|
||||
|
||||
///Set the custom background color of the toolbar.
|
||||
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`.
|
||||
bool enableUrlBarHiding;
|
||||
|
||||
///Set to `true` to enable Instant Apps. The default value is `false`.
|
||||
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
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -666,9 +865,9 @@ class AndroidChromeCustomTabsOptions implements ChromeSafariBrowserOptions, Andr
|
|||
};
|
||||
}
|
||||
|
||||
@override
|
||||
static AndroidChromeCustomTabsOptions fromMap(Map<String, dynamic> map) {
|
||||
AndroidChromeCustomTabsOptions options = new AndroidChromeCustomTabsOptions();
|
||||
AndroidChromeCustomTabsOptions options =
|
||||
new AndroidChromeCustomTabsOptions();
|
||||
options.addShareButton = map["addShareButton"];
|
||||
options.showTitle = map["showTitle"];
|
||||
options.toolbarBackgroundColor = map["toolbarBackgroundColor"];
|
||||
|
@ -682,28 +881,39 @@ class AndroidChromeCustomTabsOptions implements ChromeSafariBrowserOptions, Andr
|
|||
class IosSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
|
||||
///Set to `true` if Reader mode should be entered automatically when it is available for the webpage. The default value is `false`.
|
||||
bool entersReaderIfAvailable;
|
||||
|
||||
///Set to `true` to enable bar collapsing. The default value is `false`.
|
||||
bool barCollapsingEnabled;
|
||||
|
||||
///Set the custom style for the dismiss button. The default value is [IosSafariOptionsDismissButtonStyle.DONE].
|
||||
///
|
||||
///**NOTE**: available on iOS 11.0+.
|
||||
IosSafariOptionsDismissButtonStyle dismissButtonStyle;
|
||||
|
||||
///Set the custom background color of the navigation bar and the toolbar.
|
||||
///
|
||||
///**NOTE**: available on iOS 10.0+.
|
||||
String preferredBarTintColor;
|
||||
|
||||
///Set the custom color of the control buttons on the navigation bar and the toolbar.
|
||||
///
|
||||
///**NOTE**: available on iOS 10.0+.
|
||||
String preferredControlTintColor;
|
||||
|
||||
///Set the custom modal presentation style when presenting the WebView. The default value is [IosWebViewOptionsPresentationStyle.FULL_SCREEN].
|
||||
IosWebViewOptionsPresentationStyle presentationStyle;
|
||||
|
||||
///Set to the custom transition style when presenting the WebView. The default value is [IosWebViewOptionsTransitionStyle.COVER_VERTICAL].
|
||||
IosWebViewOptionsTransitionStyle transitionStyle;
|
||||
|
||||
IosSafariOptions({this.entersReaderIfAvailable = false, this.barCollapsingEnabled = false, this.dismissButtonStyle = IosSafariOptionsDismissButtonStyle.DONE,
|
||||
this.preferredBarTintColor = "", this.preferredControlTintColor = "", this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN,
|
||||
this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL});
|
||||
IosSafariOptions(
|
||||
{this.entersReaderIfAvailable = false,
|
||||
this.barCollapsingEnabled = false,
|
||||
this.dismissButtonStyle = IosSafariOptionsDismissButtonStyle.DONE,
|
||||
this.preferredBarTintColor = "",
|
||||
this.preferredControlTintColor = "",
|
||||
this.presentationStyle = IosWebViewOptionsPresentationStyle.FULL_SCREEN,
|
||||
this.transitionStyle = IosWebViewOptionsTransitionStyle.COVER_VERTICAL});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -718,16 +928,18 @@ class IosSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
|
|||
};
|
||||
}
|
||||
|
||||
@override
|
||||
static IosSafariOptions fromMap(Map<String, dynamic> map) {
|
||||
IosSafariOptions options = new IosSafariOptions();
|
||||
options.entersReaderIfAvailable = map["entersReaderIfAvailable"];
|
||||
options.barCollapsingEnabled = map["barCollapsingEnabled"];
|
||||
options.dismissButtonStyle = IosSafariOptionsDismissButtonStyle.fromValue(map["dismissButtonStyle"]);
|
||||
options.dismissButtonStyle =
|
||||
IosSafariOptionsDismissButtonStyle.fromValue(map["dismissButtonStyle"]);
|
||||
options.preferredBarTintColor = map["preferredBarTintColor"];
|
||||
options.preferredControlTintColor = map["preferredControlTintColor"];
|
||||
options.presentationStyle = IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
|
||||
options.transitionStyle = IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
|
||||
options.presentationStyle =
|
||||
IosWebViewOptionsPresentationStyle.fromValue(map["presentationStyle"]);
|
||||
options.transitionStyle =
|
||||
IosWebViewOptionsTransitionStyle.fromValue(map["transitionStyle"]);
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: flutter_inappwebview
|
||||
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>
|
||||
homepage: https://github.com/pichillilorenzo/flutter_inappwebview
|
||||
|
||||
|
|
Loading…
Reference in New Issue