updated shouldInterceptFetchRequest

This commit is contained in:
Lorenzo Pichilli 2019-11-06 22:55:54 +01:00
parent e4d8b79866
commit b4544c7d98
8 changed files with 810 additions and 441 deletions

View File

@ -16,6 +16,13 @@
<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$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/assets/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/example/assets/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/lib/inline_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/inline_example.screen.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/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" />
</list>
<ignored path="$PROJECT_DIR$/.dart_tool/" />
<ignored path="$PROJECT_DIR$/.idea/" />
@ -38,8 +45,8 @@
<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="2670">
<caret line="194" column="34" selection-start-line="189" selection-start-column="2" selection-end-line="194" selection-end-column="34" />
<state relative-caret-position="260">
<caret line="659" column="36" selection-start-line="659" selection-start-column="36" selection-end-line="659" selection-end-column="36" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
@ -50,7 +57,7 @@
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="7530">
<state relative-caret-position="896">
<caret line="511" column="30" selection-start-line="511" selection-start-column="7" selection-end-line="511" selection-end-column="30" />
<folding>
<element signature="e#0#20#0" expanded="true" />
@ -62,8 +69,8 @@
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="10530">
<caret line="709" column="3" selection-start-line="709" selection-start-column="3" selection-end-line="709" selection-end-column="3" />
<state relative-caret-position="376">
<caret line="944" column="4" selection-start-line="944" selection-start-column="4" selection-end-line="944" selection-end-column="4" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
@ -74,7 +81,7 @@
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1365">
<state relative-caret-position="545">
<caret line="94" column="37" selection-start-line="94" selection-start-column="7" selection-end-line="94" selection-end-column="37" />
<folding>
<element signature="e#0#17#0" expanded="true" />
@ -86,17 +93,26 @@
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="525">
<caret line="35" column="52" selection-start-line="35" selection-start-column="52" selection-end-line="36" selection-end-column="15" />
<state relative-caret-position="566">
<caret line="67" column="37" selection-start-line="67" selection-start-column="37" selection-end-line="67" selection-end-column="37" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="170">
<caret line="127" column="25" selection-start-line="127" selection-start-column="10" selection-end-line="127" selection-end-column="25" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/example/lib/inline_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="4545">
<caret line="313" column="35" selection-start-line="313" selection-start-column="12" selection-end-line="313" selection-end-column="35" />
<state relative-caret-position="283">
<caret line="302" column="47" lean-forward="true" selection-start-line="302" selection-start-column="47" selection-end-line="302" selection-end-column="47" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
@ -104,11 +120,11 @@
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<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="435">
<caret line="29" column="61" selection-start-line="29" selection-start-column="39" selection-end-line="29" selection-end-column="61" />
<state relative-caret-position="525">
<caret line="35" column="37" selection-start-line="35" selection-start-column="37" selection-end-line="35" selection-end-column="37" />
</state>
</provider>
</entry>
@ -150,11 +166,11 @@
<find>onAjaxReadyStateChange</find>
<find>onAjaxEvent</find>
<find>shouldInterceptAjaxRequest</find>
<find>shouldInterceptFetchRequest</find>
<find>onAjaxProgress</find>
<find>onAjaxReady</find>
<find>NAVIGATION</find>
<find>onNavigationStateChange</find>
<find>shouldInterceptFetchRequest</find>
</findStrings>
<replaceStrings>
<replace>activity.getPreferences(0)</replace>
@ -225,12 +241,12 @@
<option value="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" />
<option value="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js" />
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
<option value="$PROJECT_DIR$/lib/src/types.dart" />
<option value="$PROJECT_DIR$/example/lib/inline_example.screen.dart" />
<option value="$PROJECT_DIR$/example/assets/index.html" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
<option value="$PROJECT_DIR$/CHANGELOG.md" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
<option value="$PROJECT_DIR$/lib/src/types.dart" />
<option value="$PROJECT_DIR$/example/assets/index.html" />
<option value="$PROJECT_DIR$/example/lib/inline_example.screen.dart" />
</list>
</option>
</component>
@ -245,55 +261,6 @@
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="ios" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
<item name="t_rex_runner" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="nodejs_server_test_auth_basic_and_ssl" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="nodejs_server_test_auth_basic_and_ssl" type="462c0819:PsiDirectoryNode" />
<item name="assets" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="PackagesPane" />
<pane id="AndroidView">
<subPane>
<expand>
@ -334,6 +301,44 @@
<select />
</subPane>
</pane>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
<item name="t_rex_runner" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="nodejs_server_test_auth_basic_and_ssl" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="PackagesPane" />
</panes>
</component>
<component name="PropertiesComponent">
@ -485,6 +490,7 @@
</component>
<component name="ToolWindowManager">
<frame x="0" y="23" width="1920" height="1057" extended-state="0" />
<editor active="true" />
<layout>
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.6529745" visible="true" weight="0.15867944" />
<window_info id="Structure" order="1" sideWeight="0.34702548" side_tool="true" weight="0.15867944" />
@ -497,7 +503,7 @@
<window_info id="Resources Explorer" order="8" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" weight="0.32642487" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49574015" weight="0.34404144" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49574015" weight="0.29326424" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.34196892" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
@ -505,10 +511,10 @@
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.50692225" side_tool="true" weight="0.38445595" />
<window_info anchor="bottom" id="Version Control" order="9" weight="0.32953367" />
<window_info active="true" anchor="bottom" id="Terminal" order="10" sideWeight="0.49533224" visible="true" weight="0.37823835" />
<window_info anchor="bottom" id="Logcat" order="11" weight="0.32953367" />
<window_info anchor="bottom" id="Messages" order="12" weight="0.3253886" />
<window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" />
<window_info active="true" anchor="bottom" id="Terminal" order="10" sideWeight="0.49533224" visible="true" weight="0.50259066" />
<window_info anchor="bottom" id="Messages" order="11" weight="0.3253886" />
<window_info anchor="bottom" id="Dependency Viewer" order="12" weight="0.32800853" />
<window_info anchor="bottom" id="Logcat" order="13" weight="0.32953367" />
<window_info anchor="bottom" id="Dart Analysis" order="14" sideWeight="0.4968051" weight="0.3253886" />
<window_info anchor="bottom" id="Flutter Performance" order="15" sideWeight="0.5042598" side_tool="true" weight="0.5160622" />
<window_info anchor="bottom" id="Build" order="16" />
@ -736,17 +742,10 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js">
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="15">
<caret line="61" selection-start-line="61" selection-end-line="61" />
</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="2670">
<caret line="194" column="34" selection-start-line="189" selection-start-column="2" selection-end-line="194" selection-end-column="34" />
<state relative-caret-position="545">
<caret line="94" column="37" selection-start-line="94" selection-start-column="7" selection-end-line="94" selection-end-column="37" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
@ -755,7 +754,7 @@
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="7530">
<state relative-caret-position="896">
<caret line="511" column="30" selection-start-line="511" selection-start-column="7" selection-end-line="511" selection-end-column="30" />
<folding>
<element signature="e#0#20#0" expanded="true" />
@ -763,47 +762,54 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="10530">
<caret line="709" column="3" selection-start-line="709" selection-start-column="3" selection-end-line="709" selection-end-column="3" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1365">
<caret line="94" column="37" selection-start-line="94" selection-start-column="7" selection-end-line="94" selection-end-column="37" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="525">
<caret line="35" column="52" selection-start-line="35" selection-start-column="52" selection-end-line="36" selection-end-column="15" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/inline_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="4545">
<caret line="313" column="35" selection-start-line="313" selection-start-column="12" selection-end-line="313" selection-end-column="35" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="435">
<caret line="29" column="61" selection-start-line="29" selection-start-column="39" selection-end-line="29" selection-end-column="61" />
<state relative-caret-position="525">
<caret line="35" column="37" selection-start-line="35" selection-start-column="37" selection-end-line="35" selection-end-column="37" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="376">
<caret line="944" column="4" selection-start-line="944" selection-start-column="4" selection-end-line="944" selection-end-column="4" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="260">
<caret line="659" column="36" selection-start-line="659" selection-start-column="36" selection-end-line="659" selection-end-column="36" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="566">
<caret line="67" column="37" selection-start-line="67" selection-start-column="37" selection-end-line="67" selection-end-column="37" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="170">
<caret line="127" column="25" selection-start-line="127" selection-start-column="10" selection-end-line="127" selection-end-column="25" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/inline_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="283">
<caret line="302" column="47" lean-forward="true" selection-start-line="302" selection-start-column="47" selection-end-line="302" selection-end-column="47" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>

View File

@ -85,16 +85,24 @@ final public class InAppWebView extends InputAwareWebView {
" }" +
"})(window.console);";
static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppBrowserPlatformReady'));";
static final String variableForOnLoadResourceJS = "window._flutter_inappbrowser_useOnLoadResource";
static final String enableVariableForOnLoadResourceJS = variableForOnLoadResourceJS + " = $PLACEHOLDER_VALUE;";
static final String resourceObserverJS = "(function() {" +
" var observer = new PerformanceObserver(function(list) {" +
" list.getEntries().forEach(function(entry) {" +
" if (window." + variableForOnLoadResourceJS + " == null || window." + variableForOnLoadResourceJS + " == true) {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('onLoadResource', entry);" +
" }" +
" });" +
" });" +
" observer.observe({entryTypes: ['resource']});" +
"})();";
static final String platformReadyJS = "window.dispatchEvent(new Event('flutterInAppBrowserPlatformReady'));";
static final String variableForShouldInterceptAjaxRequestJS = "window._flutter_inappbrowser_useShouldInterceptAjaxRequest";
static final String enableVariableForShouldInterceptAjaxRequestJS = variableForShouldInterceptAjaxRequestJS + " = $PLACEHOLDER_VALUE;";
static final String interceptAjaxRequestsJS = "(function(ajax) {" +
" var send = ajax.prototype.send;" +
@ -106,6 +114,7 @@ final public class InAppWebView extends InputAwareWebView {
" ajax.prototype._flutter_inappbrowser_user = null;" +
" ajax.prototype._flutter_inappbrowser_password = null;" +
" ajax.prototype._flutter_inappbrowser_password = null;" +
" ajax.prototype._flutter_inappbrowser_already_onreadystatechange_wrapped = false;" +
" ajax.prototype._flutter_inappbrowser_request_headers = {};" +
" ajax.prototype.open = function(method, url, isAsync, user, password) {" +
" isAsync = (isAsync != null) ? isAsync : true;" +
@ -122,6 +131,7 @@ final public class InAppWebView extends InputAwareWebView {
" };" +
" function handleEvent(e) {" +
" var self = this;" +
" if (window." + variableForShouldInterceptAjaxRequestJS + " == null || window." + variableForShouldInterceptAjaxRequestJS + " == true) {" +
" var headers = this.getAllResponseHeaders();" +
" var responseHeaders = {};" +
" if (headers != null) {" +
@ -163,11 +173,16 @@ final public class InAppWebView extends InputAwareWebView {
" };" +
" }" +
" });" +
" }" +
" };" +
" ajax.prototype.send = function(data) {" +
" var self = this;" +
" if (window." + variableForShouldInterceptAjaxRequestJS + " == null || window." + variableForShouldInterceptAjaxRequestJS + " == true) {" +
" if (!this._flutter_inappbrowser_already_onreadystatechange_wrapped) {" +
" this._flutter_inappbrowser_already_onreadystatechange_wrapped = true;" +
" var onreadystatechange = this.onreadystatechange;" +
" this.onreadystatechange = function() {" +
" if (window." + variableForShouldInterceptAjaxRequestJS + " == null || window." + variableForShouldInterceptAjaxRequestJS + " == true) {" +
" var headers = this.getAllResponseHeaders();" +
" var responseHeaders = {};" +
" if (headers != null) {" +
@ -207,7 +222,11 @@ final public class InAppWebView extends InputAwareWebView {
" onreadystatechange();" +
" }" +
" });" +
" } else if (onreadystatechange != null) {" +
" onreadystatechange();" +
" }" +
" };" +
" }" +
" this.addEventListener('loadstart', handleEvent);" +
" this.addEventListener('load', handleEvent);" +
" this.addEventListener('loadend', handleEvent);" +
@ -245,14 +264,83 @@ final public class InAppWebView extends InputAwareWebView {
" }" +
" send.call(self, data);" +
" });" +
" } else {" +
" send.call(this, data);" +
" }" +
" };" +
"})(window.XMLHttpRequest);";
static final String variableForShouldInterceptFetchRequestsJS = "window._flutter_inappbrowser_useShouldInterceptFetchRequest";
static final String enableVariableForShouldInterceptFetchRequestsJS = variableForShouldInterceptFetchRequestsJS + " = $PLACEHOLDER_VALUE;";
static final String interceptFetchRequestsJS = "(function(fetch) {" +
" if (fetch == null) {" +
" return;" +
" }" +
" window.fetch = function(resource, init) {" +
" function convertHeadersToJson(headers) {" +
" var headersObj = {};" +
" for (var header of headers.keys()) {" +
" var value = headers.get(header);" +
" headersObj[header] = value;" +
" }" +
" return headersObj;" +
" }" +
" function convertJsonToHeaders(headersJson) {" +
" return new Headers(headersJson);" +
" }" +
" function convertBodyToArray(body) {" +
" return new Response(body).arrayBuffer().then(function(arrayBuffer) {" +
" var arr = Array.from(new Uint8Array(arrayBuffer));" +
" return arr;" +
" })" +
" }" +
" function convertArrayIntBodyToUint8Array(arrayIntBody) {" +
" return new Uint8Array(arrayIntBody);" +
" }" +
" function convertCredentialsToJson(credentials) {" +
" var credentialsObj = {};" +
" if (window.FederatedCredential != null && credentials instanceof FederatedCredential) {" +
" credentialsObj.type = credentials.type;" +
" credentialsObj.id = credentials.id;" +
" credentialsObj.name = credentials.name;" +
" credentialsObj.protocol = credentials.protocol;" +
" credentialsObj.provider = credentials.provider;" +
" credentialsObj.iconURL = credentials.iconURL;" +
" } else if (window.PasswordCredential != null && credentials instanceof PasswordCredential) {" +
" credentialsObj.type = credentials.type;" +
" credentialsObj.id = credentials.id;" +
" credentialsObj.name = credentials.name;" +
" credentialsObj.password = credentials.password;" +
" credentialsObj.iconURL = credentials.iconURL;" +
" } else {" +
" credentialsObj.type = 'default';" +
" credentialsObj.value = credentials;" +
" }" +
" }" +
" function convertJsonToCredential(credentialsJson) {" +
" var credentials;" +
" if (window.FederatedCredential != null && credentialsJson.type === 'federated') {" +
" credentials = new FederatedCredential({" +
" id: credentialsJson.id," +
" name: credentialsJson.name," +
" protocol: credentialsJson.protocol," +
" provider: credentialsJson.provider," +
" iconURL: credentialsJson.iconURL" +
" });" +
" } else if (window.PasswordCredential != null && credentialsJson.type === 'password') {" +
" credentials = new PasswordCredential({" +
" id: credentialsJson.id," +
" name: credentialsJson.name," +
" password: credentialsJson.password," +
" iconURL: credentialsJson.iconURL" +
" });" +
" } else {" +
" credentials = credentialsJson;" +
" }" +
" return credentials;" +
" }" +
" window.fetch = async function(resource, init) {" +
" if (window." + variableForShouldInterceptFetchRequestsJS + " == null || window." + variableForShouldInterceptFetchRequestsJS + " == true) {" +
" var fetchRequest = {" +
" url: null," +
" method: null," +
@ -296,6 +384,12 @@ final public class InAppWebView extends InputAwareWebView {
" fetchRequest.keepalive = init.keepalive;" +
" }" +
" }" +
" if (fetchRequest.headers instanceof Headers) {" +
" fetchRequest.headers = convertHeadersToJson(fetchRequest.headers);" +
" }" +
" fetchRequest.credentials = convertCredentialsToJson(fetchRequest.credentials);" +
" return convertBodyToArray(fetchRequest.body).then(function(body) {" +
" fetchRequest.body = body;" +
" return window." + JavaScriptBridgeInterface.name + ".callHandler('shouldInterceptFetchRequest', fetchRequest).then(function(result) {" +
" if (result != null) {" +
" switch (result.action) {" +
@ -311,9 +405,29 @@ final public class InAppWebView extends InputAwareWebView {
" controller.abort();" +
" break;" +
" }" +
" var resultResource = (result.resource != null) ? result.resource : resource;" +
" var resultInit = init;" +
" if (result.init != null) {" +
" resultInit.method = result.method;" +
" resultInit.headers = convertJsonToHeaders(result.headers);" +
" resultInit.body = convertArrayIntBodyToUint8Array(result.body);" +
" resultInit.mode = result.mode;" +
" resultInit.credentials = convertJsonToCredential(result.credentials);" +
" resultInit.cache = result.cache;" +
" resultInit.redirect = result.redirect;" +
" resultInit.referrer = result.referrer;" +
" resultInit.referrerPolicy = result.referrerPolicy;" +
" resultInit.integrity = result.integrity;" +
" resultInit.keepalive = result.keepalive;" +
" }" +
" return fetch(resultResource, resultInit);" +
" }" +
" return fetch(resource, init);" +
" });" +
" });" +
" } else {" +
" return fetch(resource, init);" +
" }" +
" };" +
"})(window.fetch);";
@ -612,6 +726,36 @@ final public class InAppWebView extends InputAwareWebView {
if (newOptionsMap.get("debuggingEnabled") != null && options.debuggingEnabled != newOptions.debuggingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
setWebContentsDebuggingEnabled(newOptions.debuggingEnabled);
if (newOptionsMap.get("useShouldInterceptAjaxRequest") != null && options.useShouldInterceptAjaxRequest != newOptions.useShouldInterceptAjaxRequest) {
String placeholderValue = newOptions.useShouldInterceptAjaxRequest ? "true" : "false";
String sourceJs = InAppWebView.enableVariableForShouldInterceptAjaxRequestJS.replace("$PLACEHOLDER_VALUE", placeholderValue);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
evaluateJavascript(sourceJs, (ValueCallback<String>) null);
} else {
loadUrl("javascript:" + sourceJs);
}
}
if (newOptionsMap.get("useShouldInterceptFetchRequest") != null && options.useShouldInterceptFetchRequest != newOptions.useShouldInterceptFetchRequest) {
String placeholderValue = newOptions.useShouldInterceptFetchRequest ? "true" : "false";
String sourceJs = InAppWebView.enableVariableForShouldInterceptFetchRequestsJS.replace("$PLACEHOLDER_VALUE", placeholderValue);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
evaluateJavascript(sourceJs, (ValueCallback<String>) null);
} else {
loadUrl("javascript:" + sourceJs);
}
}
if (newOptionsMap.get("useOnLoadResource") != null && options.useOnLoadResource != newOptions.useOnLoadResource) {
String placeholderValue = newOptions.useOnLoadResource ? "true" : "false";
String sourceJs = InAppWebView.enableVariableForOnLoadResourceJS.replace("$PLACEHOLDER_VALUE", placeholderValue);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
evaluateJavascript(sourceJs, (ValueCallback<String>) null);
} else {
loadUrl("javascript:" + sourceJs);
}
}
if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically)
settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically);

View File

@ -14,6 +14,7 @@ import android.webkit.CookieSyncManager;
import android.webkit.HttpAuthHandler;
import android.webkit.SafeBrowsingResponse;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
@ -182,7 +183,7 @@ public class InAppWebViewClient extends WebViewClient {
view.requestFocus();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript(InAppWebView.platformReadyJS, (MethodChannel.Result) null);
webView.evaluateJavascript(InAppWebView.platformReadyJS, (ValueCallback<String>) null);
} else {
webView.loadUrl("javascript:" + InAppWebView.platformReadyJS.replaceAll("[\r\n]+", ""));
}

View File

@ -31,6 +31,8 @@
<option value="1">option 1</option>
<option value="2">option 2</option>
</select>
<input type="file">
<input type="file" accept="image/*" capture>
<button onclick="testHistoryPush1()">History Push 1</button>
<button onclick="testHistoryPush2()">History Push 2</button>
<button onclick="testLocationHref()">Location Href</button>
@ -110,6 +112,20 @@
console.error("ERROR: " + error);
});
fetch("http://192.168.1.20:8082/test-ajax-post", {
method: 'POST',
body: JSON.stringify({
name: 'Lorenzo Fetch API'
}),
headers: {
'Content-Type': 'application/json'
}
}).then(function(response) {
console.log(response);
}).catch(function(error) {
console.error("ERROR: " + error);
});
/*
alert("Alert Popup");
console.log(confirm("Press a button!"));

View File

@ -289,7 +289,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
print("Current highlighted: $activeMatchOrdinal, Number of matches found: $numberOfMatches, find operation completed: $isDoneCounting");
},
shouldInterceptAjaxRequest: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
print("AJAX REQUEST: ${ajaxRequest.method} - ${ajaxRequest.url}, DATA: ${ajaxRequest.data}");
//print("AJAX REQUEST: ${ajaxRequest.method} - ${ajaxRequest.url}, DATA: ${ajaxRequest.data}");
// ajaxRequest.method = "GET";
// ajaxRequest.url = "http://192.168.1.20:8082/test-download-file";
// ajaxRequest.headers = {
@ -299,16 +299,17 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
return null;
},
onAjaxReadyStateChange: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
print("AJAX READY STATE CHANGE: ${ajaxRequest.method} - ${ajaxRequest.url}, ${ajaxRequest.status}, ${ajaxRequest.readyState}, ${ajaxRequest.responseType}, ${ajaxRequest.responseText}, ${ajaxRequest.responseHeaders}");
return AjaxRequestAction.ABORT;
//print("AJAX READY STATE CHANGE: ${ajaxRequest.method} - ${ajaxRequest.url}, ${ajaxRequest.status}, ${ajaxRequest.readyState}, ${ajaxRequest.responseType}, ${ajaxRequest.responseText}, ${ajaxRequest.responseHeaders}");
return AjaxRequestAction.PROCEED;
},
onAjaxProgress: (InAppWebViewController controller, AjaxRequest ajaxRequest) async {
print("AJAX EVENT: ${ajaxRequest.method} - ${ajaxRequest.url}, ${ajaxRequest.event.type}, LOADED: ${ajaxRequest.event.loaded}, ${ajaxRequest.responseHeaders}");
return AjaxRequestAction.ABORT;
//print("AJAX EVENT: ${ajaxRequest.method} - ${ajaxRequest.url}, ${ajaxRequest.event.type}, LOADED: ${ajaxRequest.event.loaded}, ${ajaxRequest.responseHeaders}");
return AjaxRequestAction.PROCEED;
},
shouldInterceptFetchRequest: (InAppWebViewController controller, FetchRequest fetchRequest) async {
print("FETCH REQUEST: ${fetchRequest.method} - ${fetchRequest.url}");
print("FETCH REQUEST: ${fetchRequest.method} - ${fetchRequest.url}, headers: ${fetchRequest.headers}");
fetchRequest.action = FetchRequestAction.ABORT;
print(fetchRequest.body);
return fetchRequest;
},
onNavigationStateChange: (InAppWebViewController controller, String url) async {

View File

@ -58,17 +58,6 @@ let consoleLogJS = """
})(window.console);
"""
let resourceObserverJS = """
(function() {
var observer = new PerformanceObserver(function(list) {
list.getEntries().forEach(function(entry) {
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler("onLoadResource", entry);
});
});
observer.observe({entryTypes: ['resource']});
})();
"""
let javaScriptBridgeJS = """
window.\(JAVASCRIPT_BRIDGE_NAME) = {};
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler = function() {
@ -232,6 +221,25 @@ function wkwebview_FindNext(forward) {
}
"""
let variableForOnLoadResourceJS = "window._flutter_inappbrowser_useOnLoadResource"
let enableVariableForOnLoadResourceJS = "\(variableForOnLoadResourceJS) = $PLACEHOLDER_VALUE;"
let resourceObserverJS = """
(function() {
var observer = new PerformanceObserver(function(list) {
list.getEntries().forEach(function(entry) {
if (window.\(variableForOnLoadResourceJS) == null || window.\(variableForOnLoadResourceJS) == true) {
window.\(JAVASCRIPT_BRIDGE_NAME).callHandler("onLoadResource", entry);
}
});
});
observer.observe({entryTypes: ['resource']});
})();
"""
let variableForShouldInterceptAjaxRequestJS = "window._flutter_inappbrowser_useShouldInterceptAjaxRequest"
let enableVariableForShouldInterceptAjaxRequestJS = "\(variableForShouldInterceptAjaxRequestJS) = $PLACEHOLDER_VALUE;"
let interceptAjaxRequestsJS = """
(function(ajax) {
var send = ajax.prototype.send;
@ -243,6 +251,7 @@ let interceptAjaxRequestsJS = """
ajax.prototype._flutter_inappbrowser_user = null;
ajax.prototype._flutter_inappbrowser_password = null;
ajax.prototype._flutter_inappbrowser_password = null;
ajax.prototype._flutter_inappbrowser_already_onreadystatechange_wrapped = false;
ajax.prototype._flutter_inappbrowser_request_headers = {};
ajax.prototype.open = function(method, url, isAsync, user, password) {
isAsync = (isAsync != null) ? isAsync : true;
@ -259,6 +268,7 @@ let interceptAjaxRequestsJS = """
};
function handleEvent(e) {
var self = this;
if (window.\(variableForShouldInterceptAjaxRequestJS) == null || window.\(variableForShouldInterceptAjaxRequestJS) == true) {
var headers = this.getAllResponseHeaders();
var responseHeaders = {};
if (headers != null) {
@ -300,11 +310,16 @@ let interceptAjaxRequestsJS = """
};
}
});
}
};
ajax.prototype.send = function(data) {
var self = this;
if (window.\(variableForShouldInterceptAjaxRequestJS) == null || window.\(variableForShouldInterceptAjaxRequestJS) == true) {
if (!this._flutter_inappbrowser_already_onreadystatechange_wrapped) {
this._flutter_inappbrowser_already_onreadystatechange_wrapped = true;
var onreadystatechange = this.onreadystatechange;
this.onreadystatechange = function() {
if (window.\(variableForShouldInterceptAjaxRequestJS) == null || window.\(variableForShouldInterceptAjaxRequestJS) == true) {
var headers = this.getAllResponseHeaders();
var responseHeaders = {};
if (headers != null) {
@ -344,7 +359,11 @@ let interceptAjaxRequestsJS = """
onreadystatechange();
}
});
} else if (onreadystatechange != null) {
onreadystatechange();
}
};
}
this.addEventListener('loadstart', handleEvent);
this.addEventListener('load', handleEvent);
this.addEventListener('loadend', handleEvent);
@ -382,16 +401,85 @@ let interceptAjaxRequestsJS = """
}
send.call(self, data);
});
} else {
send.call(this, data);
}
};
})(window.XMLHttpRequest);
"""
let variableForShouldInterceptFetchRequestsJS = "window._flutter_inappbrowser_useShouldInterceptFetchRequest"
let enableVariableForShouldInterceptFetchRequestsJS = "\(variableForShouldInterceptFetchRequestsJS) = $PLACEHOLDER_VALUE;"
let interceptFetchRequestsJS = """
(function(fetch) {
if (fetch == null) {
return;
}
window.fetch = function(resource, init) {
function convertHeadersToJson(headers) {
var headersObj = {};
for (var header of headers.keys()) {
var value = headers.get(header);
headersObj[header] = value;
}
return headersObj;
}
function convertJsonToHeaders(headersJson) {
return new Headers(headersJson);
}
function convertBodyToArray(body) {
return new Response(body).arrayBuffer().then(function(arrayBuffer) {
var arr = Array.from(new Uint8Array(arrayBuffer));
return arr;
})
}
function convertArrayIntBodyToUint8Array(arrayIntBody) {
return new Uint8Array(arrayIntBody);
}
function convertCredentialsToJson(credentials) {
var credentialsObj = {};
if (window.FederatedCredential != null && credentials instanceof FederatedCredential) {
credentialsObj.type = credentials.type;
credentialsObj.id = credentials.id;
credentialsObj.name = credentials.name;
credentialsObj.protocol = credentials.protocol;
credentialsObj.provider = credentials.provider;
credentialsObj.iconURL = credentials.iconURL;
} else if (window.PasswordCredential != null && credentials instanceof PasswordCredential) {
credentialsObj.type = credentials.type;
credentialsObj.id = credentials.id;
credentialsObj.name = credentials.name;
credentialsObj.password = credentials.password;
credentialsObj.iconURL = credentials.iconURL;
} else {
credentialsObj.type = 'default';
credentialsObj.value = credentials;
}
}
function convertJsonToCredential(credentialsJson) {
var credentials;
if (window.FederatedCredential != null && credentialsJson.type === 'federated') {
credentials = new FederatedCredential({
id: credentialsJson.id,
name: credentialsJson.name,
protocol: credentialsJson.protocol,
provider: credentialsJson.provider,
iconURL: credentialsJson.iconURL
});
} else if (window.PasswordCredential != null && credentialsJson.type === 'password') {
credentials = new PasswordCredential({
id: credentialsJson.id,
name: credentialsJson.name,
password: credentialsJson.password,
iconURL: credentialsJson.iconURL
});
} else {
credentials = credentialsJson;
}
return credentials;
}
window.fetch = async function(resource, init) {
if (window.\(variableForShouldInterceptFetchRequestsJS) == null || window.\(variableForShouldInterceptFetchRequestsJS) == true) {
var fetchRequest = {
url: null,
method: null,
@ -435,6 +523,12 @@ let interceptFetchRequestsJS = """
fetchRequest.keepalive = init.keepalive;
}
}
if (fetchRequest.headers instanceof Headers) {
fetchRequest.headers = convertHeadersToJson(fetchRequest.headers);
}
fetchRequest.credentials = convertCredentialsToJson(fetchRequest.credentials);
return convertBodyToArray(fetchRequest.body).then(function(body) {
fetchRequest.body = body;
return window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('shouldInterceptFetchRequest', fetchRequest).then(function(result) {
if (result != null) {
switch (result.action) {
@ -450,9 +544,29 @@ let interceptFetchRequestsJS = """
controller.abort();
break;
}
var resultResource = (result.resource != null) ? result.resource : resource;
var resultInit = init;
if (result.init != null) {
resultInit.method = result.method;
resultInit.headers = convertJsonToHeaders(result.headers);
resultInit.body = convertArrayIntBodyToUint8Array(result.body);
resultInit.mode = result.mode;
resultInit.credentials = convertJsonToCredential(result.credentials);
resultInit.cache = result.cache;
resultInit.redirect = result.redirect;
resultInit.referrer = result.referrer;
resultInit.referrerPolicy = result.referrerPolicy;
resultInit.integrity = result.integrity;
resultInit.keepalive = result.keepalive;
}
return fetch(resultResource, resultInit);
}
return fetch(resource, init);
});
});
} else {
return fetch(resource, init);
}
};
})(window.fetch);
"""
@ -819,15 +933,18 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
}
if newOptionsMap["useOnLoadResource"] != nil && options?.useOnLoadResource != newOptions.useOnLoadResource && newOptions.useOnLoadResource {
evaluateJavaScript(resourceObserverJS, completionHandler: nil)
let placeholderValue = newOptions.useOnLoadResource ? "true" : "false"
evaluateJavaScript(enableVariableForOnLoadResourceJS.replacingOccurrences(of: "$PLACEHOLDER_VALUE", with: placeholderValue), completionHandler: nil)
}
if newOptionsMap["useShouldInterceptAjaxRequest"] != nil && options?.useShouldInterceptAjaxRequest != newOptions.useShouldInterceptAjaxRequest && newOptions.useShouldInterceptAjaxRequest {
evaluateJavaScript(interceptAjaxRequestsJS, completionHandler: nil)
let placeholderValue = newOptions.useShouldInterceptAjaxRequest ? "true" : "false"
evaluateJavaScript(enableVariableForShouldInterceptAjaxRequestJS.replacingOccurrences(of: "$PLACEHOLDER_VALUE", with: placeholderValue), completionHandler: nil)
}
if newOptionsMap["useShouldInterceptFetchRequest"] != nil && options?.useShouldInterceptFetchRequest != newOptions.useShouldInterceptFetchRequest && newOptions.useShouldInterceptFetchRequest {
evaluateJavaScript(interceptFetchRequestsJS, completionHandler: nil)
let placeholderValue = newOptions.useShouldInterceptFetchRequest ? "true" : "false"
evaluateJavaScript(enableVariableForShouldInterceptFetchRequestsJS.replacingOccurrences(of: "$PLACEHOLDER_VALUE", with: placeholderValue), completionHandler: nil)
}
if newOptionsMap["mediaPlaybackRequiresUserGesture"] != nil && options?.mediaPlaybackRequiresUserGesture != newOptions.mediaPlaybackRequiresUserGesture {

View File

@ -647,9 +647,9 @@ class InAppWebViewController {
String url = argMap["url"];
String method = argMap["method"];
Map<dynamic, dynamic> headers = argMap["headers"];
dynamic body = argMap["body"];
Uint8List body = Uint8List.fromList(argMap["body"].cast<int>());
String mode = argMap["mode"];
String credentials = argMap["credentials"];
FetchRequestCredential credentials = FetchRequest.createFetchRequestCredentialFromMap(argMap["credentials"]);
String cache = argMap["cache"];
String redirect = argMap["redirect"];
String referrer = argMap["referrer"];

View File

@ -820,14 +820,83 @@ class FetchRequestAction {
static const PROCEED = const FetchRequestAction._internal(1);
}
///
class FetchRequestCredential {
String type;
FetchRequestCredential({this.type});
Map<String, dynamic> toMap() {
return {
"type": type
};
}
}
///
class FetchRequestCredentialDefault extends FetchRequestCredential {
String value;
FetchRequestCredentialDefault({type, this.value}): super(type: type);
Map<String, dynamic> toMap() {
return {
"type": type,
"value": value,
};
}
}
///
class FetchRequestFederatedCredential extends FetchRequestCredential {
dynamic id;
String name;
String protocol;
String provider;
String iconURL;
FetchRequestFederatedCredential({type, this.id, this.name, this.protocol, this.provider, this.iconURL}): super(type: type);
Map<String, dynamic> toMap() {
return {
"type": type,
"id": id,
"name": name,
"protocol": protocol,
"provider": provider,
"iconURL": iconURL
};
}
}
///
class FetchRequestPasswordCredential extends FetchRequestCredential {
dynamic id;
String name;
String password;
String iconURL;
FetchRequestPasswordCredential({type, this.id, this.name, this.password, this.iconURL}): super(type: type);
Map<String, dynamic> toMap() {
return {
"type": type,
"id": id,
"name": name,
"password": password,
"iconURL": iconURL
};
}
}
///
class FetchRequest {
String url;
String method;
Map<dynamic, dynamic> headers;
dynamic body;
Map<String, dynamic> headers;
Uint8List body;
String mode;
String credentials;
FetchRequestCredential credentials;
String cache;
String redirect;
String referrer;
@ -847,7 +916,7 @@ class FetchRequest {
"headers": headers,
"body": body,
"mode": mode,
"credentials": credentials,
"credentials": credentials?.toMap(),
"cache": cache,
"redirect": redirect,
"referrer": referrer,
@ -861,4 +930,19 @@ class FetchRequest {
Map<String, dynamic> toJson() {
return this.toMap();
}
static FetchRequestCredential createFetchRequestCredentialFromMap(credentialsMap) {
if (credentialsMap != null) {
if (credentialsMap["type"] == "default") {
return FetchRequestCredentialDefault(type: credentialsMap["type"], value: credentialsMap["value"]);
} else if (credentialsMap["type"] == "federated") {
return FetchRequestFederatedCredential(type: credentialsMap["type"], id: credentialsMap["id"], name: credentialsMap["name"],
protocol: credentialsMap["protocol"], provider: credentialsMap["provider"], iconURL: credentialsMap["iconURL"]);
} else if (credentialsMap["type"] == "password") {
return FetchRequestPasswordCredential(type: credentialsMap["type"], id: credentialsMap["id"], name: credentialsMap["name"],
password: credentialsMap["password"], iconURL: credentialsMap["iconURL"]);
}
}
return null;
}
}