diff --git a/.idea/workspace.xml b/.idea/workspace.xml index e195666a..b71b49ee 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -16,6 +16,13 @@ + + + + + + + @@ -38,8 +45,8 @@ - - + + @@ -50,7 +57,7 @@ - + @@ -62,8 +69,8 @@ - - + + @@ -74,7 +81,7 @@ - + @@ -86,17 +93,26 @@ - - + + + + + + + + + + + - - + + @@ -104,11 +120,11 @@ - + - - + + @@ -150,11 +166,11 @@ onAjaxReadyStateChange onAjaxEvent shouldInterceptAjaxRequest - shouldInterceptFetchRequest onAjaxProgress onAjaxReady NAVIGATION onNavigationStateChange + shouldInterceptFetchRequest activity.getPreferences(0) @@ -225,12 +241,12 @@ @@ -245,55 +261,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -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!")); diff --git a/example/lib/inline_example.screen.dart b/example/lib/inline_example.screen.dart index 9bc0061b..d748da14 100755 --- a/example/lib/inline_example.screen.dart +++ b/example/lib/inline_example.screen.dart @@ -289,7 +289,7 @@ class _InlineExampleScreenState extends State { 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 { 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 { diff --git a/ios/Classes/InAppWebView.swift b/ios/Classes/InAppWebView.swift index 3b41d413..4388e010 100755 --- a/ios/Classes/InAppWebView.swift +++ b/ios/Classes/InAppWebView.swift @@ -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,52 +268,7 @@ let interceptAjaxRequestsJS = """ }; function handleEvent(e) { var self = this; - var headers = this.getAllResponseHeaders(); - var responseHeaders = {}; - if (headers != null) { - var arr = headers.trim().split(/[\\r\\n]+/); - arr.forEach(function (line) { - var parts = line.split(': '); - var header = parts.shift(); - var value = parts.join(': '); - responseHeaders[header] = value; - }); - } - var ajaxRequest = { - method: this._flutter_inappbrowser_method, - url: this._flutter_inappbrowser_url, - isAsync: this._flutter_inappbrowser_isAsync, - user: this._flutter_inappbrowser_user, - password: this._flutter_inappbrowser_password, - withCredentials: this.withCredentials, - headers: this._flutter_inappbrowser_request_headers, - readyState: this.readyState, - status: this.status, - responseURL: this.responseURL, - responseType: this.responseType, - responseText: this.responseText, - statusText: this.statusText, - responseHeaders, responseHeaders, - event: { - type: e.type, - loaded: e.loaded, - lengthComputable: e.lengthComputable - } - }; - window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('onAjaxProgress', ajaxRequest).then(function(result) { - if (result != null) { - switch (result) { - case 0: - self.abort(); - return; - }; - } - }); - }; - ajax.prototype.send = function(data) { - var self = this; - var onreadystatechange = this.onreadystatechange; - this.onreadystatechange = function() { + if (window.\(variableForShouldInterceptAjaxRequestJS) == null || window.\(variableForShouldInterceptAjaxRequestJS) == true) { var headers = this.getAllResponseHeaders(); var responseHeaders = {}; if (headers != null) { @@ -330,9 +294,14 @@ let interceptAjaxRequestsJS = """ responseType: this.responseType, responseText: this.responseText, statusText: this.statusText, - responseHeaders: responseHeaders + responseHeaders, responseHeaders, + event: { + type: e.type, + loaded: e.loaded, + lengthComputable: e.lengthComputable + } }; - window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('onAjaxReadyStateChange', ajaxRequest).then(function(result) { + window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('onAjaxProgress', ajaxRequest).then(function(result) { if (result != null) { switch (result) { case 0: @@ -340,119 +309,264 @@ let interceptAjaxRequestsJS = """ return; }; } - if (onreadystatechange != null) { - onreadystatechange(); - } }); - }; - this.addEventListener('loadstart', handleEvent); - this.addEventListener('load', handleEvent); - this.addEventListener('loadend', handleEvent); - this.addEventListener('progress', handleEvent); - this.addEventListener('error', handleEvent); - this.addEventListener('abort', handleEvent); - var ajaxRequest = { - data: data, - method: this._flutter_inappbrowser_method, - url: this._flutter_inappbrowser_url, - isAsync: this._flutter_inappbrowser_isAsync, - user: this._flutter_inappbrowser_user, - password: this._flutter_inappbrowser_password, - withCredentials: this.withCredentials, - headers: this._flutter_inappbrowser_request_headers - }; - window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('shouldInterceptAjaxRequest', ajaxRequest).then(function(result) { - if (result != null) { - switch (result.action) { - case 0: - self.abort(); - return; + } + }; + 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) { + var arr = headers.trim().split(/[\\r\\n]+/); + arr.forEach(function (line) { + var parts = line.split(': '); + var header = parts.shift(); + var value = parts.join(': '); + responseHeaders[header] = value; + }); + } + var ajaxRequest = { + method: this._flutter_inappbrowser_method, + url: this._flutter_inappbrowser_url, + isAsync: this._flutter_inappbrowser_isAsync, + user: this._flutter_inappbrowser_user, + password: this._flutter_inappbrowser_password, + withCredentials: this.withCredentials, + headers: this._flutter_inappbrowser_request_headers, + readyState: this.readyState, + status: this.status, + responseURL: this.responseURL, + responseType: this.responseType, + responseText: this.responseText, + statusText: this.statusText, + responseHeaders: responseHeaders + }; + window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('onAjaxReadyStateChange', ajaxRequest).then(function(result) { + if (result != null) { + switch (result) { + case 0: + self.abort(); + return; + }; + } + if (onreadystatechange != null) { + onreadystatechange(); + } + }); + } else if (onreadystatechange != null) { + onreadystatechange(); + } }; - data = result.data; - self.withCredentials = result.withCredentials; - for (var header in result.headers) { - var value = result.headers[header]; - self.setRequestHeader(header, value); - }; - if ((self._flutter_inappbrowser_method != result.method && result.method != null) || (self._flutter_inappbrowser_url != result.url && result.url != null)) { - self.abort(); - self.open(result.method, result.url, result.isAsync, result.user, result.password); - return; - } } - send.call(self, data); - }); + this.addEventListener('loadstart', handleEvent); + this.addEventListener('load', handleEvent); + this.addEventListener('loadend', handleEvent); + this.addEventListener('progress', handleEvent); + this.addEventListener('error', handleEvent); + this.addEventListener('abort', handleEvent); + var ajaxRequest = { + data: data, + method: this._flutter_inappbrowser_method, + url: this._flutter_inappbrowser_url, + isAsync: this._flutter_inappbrowser_isAsync, + user: this._flutter_inappbrowser_user, + password: this._flutter_inappbrowser_password, + withCredentials: this.withCredentials, + headers: this._flutter_inappbrowser_request_headers + }; + window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('shouldInterceptAjaxRequest', ajaxRequest).then(function(result) { + if (result != null) { + switch (result.action) { + case 0: + self.abort(); + return; + }; + data = result.data; + self.withCredentials = result.withCredentials; + for (var header in result.headers) { + var value = result.headers[header]; + self.setRequestHeader(header, value); + }; + if ((self._flutter_inappbrowser_method != result.method && result.method != null) || (self._flutter_inappbrowser_url != result.url && result.url != null)) { + self.abort(); + self.open(result.method, result.url, result.isAsync, result.user, result.password); + return; + } + } + 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) { - var fetchRequest = { - url: null, - method: null, - headers: null, - body: null, - mode: null, - credentials: null, - cache: null, - redirect: null, - referrer: null, - referrerPolicy: null, - integrity: null, - keepalive: null - }; - if (resource instanceof Request) { - fetchRequest.url = resource.url; - fetchRequest.method = resource.method; - fetchRequest.headers = resource.headers; - fetchRequest.body = resource.body; - fetchRequest.mode = resource.mode; - fetchRequest.credentials = resource.credentials; - fetchRequest.cache = resource.cache; - fetchRequest.redirect = resource.redirect; - fetchRequest.referrer = resource.referrer; - fetchRequest.referrerPolicy = resource.referrerPolicy; - fetchRequest.integrity = resource.integrity; - fetchRequest.keepalive = resource.keepalive; - } else { - fetchRequest.url = resource; - if (init != null) { - fetchRequest.method = init.method; - fetchRequest.headers = init.headers; - fetchRequest.body = init.body; - fetchRequest.mode = init.mode; - fetchRequest.credentials = init.credentials; - fetchRequest.cache = init.cache; - fetchRequest.redirect = init.redirect; - fetchRequest.referrer = init.referrer; - fetchRequest.referrerPolicy = init.referrerPolicy; - fetchRequest.integrity = init.integrity; - fetchRequest.keepalive = init.keepalive; - } + function convertHeadersToJson(headers) { + var headersObj = {}; + for (var header of headers.keys()) { + var value = headers.get(header); + headersObj[header] = value; } - return window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('shouldInterceptFetchRequest', fetchRequest).then(function(result) { - if (result != null) { - switch (result.action) { - case 0: - var controller = new AbortController(); - if (init != null) { - init.signal = controller.signal; - } else { - init = { - signal: controller.signal - }; - } - controller.abort(); - break; + 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, + headers: null, + body: null, + mode: null, + credentials: null, + cache: null, + redirect: null, + referrer: null, + referrerPolicy: null, + integrity: null, + keepalive: null + }; + if (resource instanceof Request) { + fetchRequest.url = resource.url; + fetchRequest.method = resource.method; + fetchRequest.headers = resource.headers; + fetchRequest.body = resource.body; + fetchRequest.mode = resource.mode; + fetchRequest.credentials = resource.credentials; + fetchRequest.cache = resource.cache; + fetchRequest.redirect = resource.redirect; + fetchRequest.referrer = resource.referrer; + fetchRequest.referrerPolicy = resource.referrerPolicy; + fetchRequest.integrity = resource.integrity; + fetchRequest.keepalive = resource.keepalive; + } else { + fetchRequest.url = resource; + if (init != null) { + fetchRequest.method = init.method; + fetchRequest.headers = init.headers; + fetchRequest.body = init.body; + fetchRequest.mode = init.mode; + fetchRequest.credentials = init.credentials; + fetchRequest.cache = init.cache; + fetchRequest.redirect = init.redirect; + fetchRequest.referrer = init.referrer; + fetchRequest.referrerPolicy = init.referrerPolicy; + fetchRequest.integrity = init.integrity; + 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) { + case 0: + var controller = new AbortController(); + if (init != null) { + init.signal = controller.signal; + } else { + init = { + signal: controller.signal + }; + } + 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 { diff --git a/lib/src/in_app_webview.dart b/lib/src/in_app_webview.dart index db5625ec..54e117b3 100755 --- a/lib/src/in_app_webview.dart +++ b/lib/src/in_app_webview.dart @@ -647,9 +647,9 @@ class InAppWebViewController { String url = argMap["url"]; String method = argMap["method"]; Map headers = argMap["headers"]; - dynamic body = argMap["body"]; + Uint8List body = Uint8List.fromList(argMap["body"].cast()); 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"]; diff --git a/lib/src/types.dart b/lib/src/types.dart index 06c2f266..98814aff 100644 --- a/lib/src/types.dart +++ b/lib/src/types.dart @@ -820,14 +820,83 @@ class FetchRequestAction { static const PROCEED = const FetchRequestAction._internal(1); } +/// +class FetchRequestCredential { + String type; + + FetchRequestCredential({this.type}); + + Map toMap() { + return { + "type": type + }; + } +} + +/// +class FetchRequestCredentialDefault extends FetchRequestCredential { + String value; + + FetchRequestCredentialDefault({type, this.value}): super(type: type); + + Map 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 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 toMap() { + return { + "type": type, + "id": id, + "name": name, + "password": password, + "iconURL": iconURL + }; + } +} + /// class FetchRequest { String url; String method; - Map headers; - dynamic body; + Map 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 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; + } } \ No newline at end of file