added getScrollX and getScrollY webview methods, added HttpOnly and SameSite set cookie options, added animated option to scrollTo and scrollBy webview methods, Added error and message to the ServerTrustChallenge class for iOS, added contentInsetAdjustmentBehavior webview iOS-specific option, added getCertificate android-specific webview method, added copy and copyWithValue methods for webview class options
This commit is contained in:
parent
1b2de86375
commit
b9d1482887
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,8 +1,15 @@
|
|||
## 3.4.0
|
||||
|
||||
- Added `requestFocusNodeHref`, `requestImageRef`, `getMetaTags`, `getMetaThemeColor` webview methods
|
||||
- Added `requestFocusNodeHref`, `requestImageRef`, `getMetaTags`, `getMetaThemeColor`, `getScrollX`, `getScrollY` webview methods
|
||||
- Added `WebStorage`, `LocalStorage` and `SessionStorage` class to manage `window.localStorage` and `window.sessionStorage` JavaScript [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API)
|
||||
- Added `supportZoom` webview option also on iOS
|
||||
- Added `HttpOnly`, `SameSite` set cookie options
|
||||
- Updated `Cookie` class
|
||||
- Added `animated` option to `scrollTo` and `scrollBy` webview methods
|
||||
- Added error and message to the `ServerTrustChallenge` class for iOS (class used by the `onReceivedServerTrustAuthRequest` event)
|
||||
- Added `contentInsetAdjustmentBehavior` webview iOS-specific option
|
||||
- Added `getCertificate` android-specific webview method
|
||||
- Added `copy` and `copyWithValue` methods for webview class options
|
||||
- Fixed `zoomBy`, `setOptions` webview methods on Android
|
||||
- Fixed `databaseEnabled` android webview option default value to `true`
|
||||
|
||||
|
@ -12,6 +19,8 @@
|
|||
- `getHtml` webview method now could return `null` if it was unable to get it.
|
||||
- Moved `supportZoom` webview option to cross-platform
|
||||
- `builtInZoomControls` android webview options changed default value to `true`
|
||||
- Updated `ServerTrustChallenge` class used by the `onReceivedServerTrustAuthRequest` event
|
||||
- The method `getOptions`could return null now
|
||||
|
||||
## 3.3.0+3
|
||||
|
||||
|
|
11
README.md
11
README.md
|
@ -59,6 +59,10 @@ Because of [Flutter AndroidX compatibility](https://flutter.dev/docs/development
|
|||
|
||||
Also, note that to use the `InAppWebView` widget on Android, it requires **Android API 20+** (see [AndroidView](https://api.flutter.dev/flutter/widgets/AndroidView-class.html)).
|
||||
|
||||
**Support HTTP request**: Starting with Android 9 (API level 28), cleartext support is disabled by default:
|
||||
- Check the official [Network security configuration - "Opt out of cleartext traffic"](https://developer.android.com/training/articles/security-config#CleartextTrafficPermitted) section.
|
||||
- Also, check this StackOverflow issue answer: [Cleartext HTTP traffic not permitted](https://stackoverflow.com/a/50834600/4637638).
|
||||
|
||||
### IMPORTANT Note for iOS
|
||||
|
||||
If you are starting a new fresh app, you need to create the Flutter App with `flutter create --androidx -i swift`
|
||||
|
@ -392,8 +396,8 @@ Screenshots:
|
|||
* `clearMatches`: Clears the highlighting surrounding text matches created by `findAllAsync()`.
|
||||
* `getTRexRunnerHtml`: Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with `getTRexRunnerCss()`.
|
||||
* `getTRexRunnerCss`: Gets the css of the Chromium's t-rex runner game. Used in combination with `getTRexRunnerHtml()`.
|
||||
* `scrollTo({@required int x, @required int y})`: Scrolls the WebView to the position.
|
||||
* `scrollBy({@required int x, @required int y})`: Moves the scrolled position of the WebView.
|
||||
* `scrollTo({@required int x, @required int y, bool animated = false})`: Scrolls the WebView to the position.
|
||||
* `scrollBy({@required int x, @required int y, bool animated = false})`: Moves the scrolled position of the WebView.
|
||||
* `pauseTimers`: On Android, it pauses all layout, parsing, and JavaScript timers for all WebViews. This is a global requests, not restricted to just this WebView. This can be useful if the application has been paused. On iOS, it is restricted to just this WebView.
|
||||
* `resumeTimers`: On Android, it resumes all layout, parsing, and JavaScript timers for all WebViews. This will resume dispatching all timers. On iOS, it resumes all layout, parsing, and JavaScript timers to just this WebView.
|
||||
* `printCurrentPage`: Prints the current page.
|
||||
|
@ -406,6 +410,8 @@ Screenshots:
|
|||
* `requestImageRef`: Requests the URL of the image last touched by the user.
|
||||
* `getMetaTags`: Returns the list of `<meta>` tags of the current WebView.
|
||||
* `getMetaThemeColor`: Returns an instance of `Color` representing the `content` value of the `<meta name="theme-color" content="">` tag of the current WebView, if available, otherwise `null`.
|
||||
* `getScrollX`: Returns the scrolled left position of the current WebView.
|
||||
* `getScrollY`: Returns the scrolled top position of the current WebView.
|
||||
* `static getDefaultUserAgent`: Gets the default user agent.
|
||||
|
||||
##### `InAppWebViewController` Android-specific methods
|
||||
|
@ -587,6 +593,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
|
|||
* `isPagingEnabled`: A Boolean value that determines whether paging is enabled for the scroll view. The default value is `false`.
|
||||
* `maximumZoomScale`: A floating-point value that specifies the maximum scale factor that can be applied to the scroll view's content. The default value is `1.0`.
|
||||
* `minimumZoomScale`: A floating-point value that specifies the minimum scale factor that can be applied to the scroll view's content. The default value is `1.0`.
|
||||
* `contentInsetAdjustmentBehavior`: Configures how safe area insets are added to the adjusted content inset. The default value is `IOSUIScrollViewContentInsetAdjustmentBehavior.NEVER`.
|
||||
|
||||
#### `InAppWebView` Events
|
||||
|
||||
|
|
|
@ -280,7 +280,8 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
{
|
||||
Integer x = (Integer) call.argument("x");
|
||||
Integer y = (Integer) call.argument("y");
|
||||
scrollTo(x, y);
|
||||
Boolean animated = (Boolean) call.argument("animated");
|
||||
scrollTo(x, y, animated);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
@ -288,7 +289,8 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
{
|
||||
Integer x = (Integer) call.argument("x");
|
||||
Integer y = (Integer) call.argument("y");
|
||||
scrollBy(x, y);
|
||||
Boolean animated = (Boolean) call.argument("animated");
|
||||
scrollBy(x, y, animated);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
@ -376,6 +378,21 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
}
|
||||
result.success(true);
|
||||
break;
|
||||
case "requestFocusNodeHref":
|
||||
result.success(requestFocusNodeHref());
|
||||
break;
|
||||
case "requestImageRef":
|
||||
result.success(requestImageRef());
|
||||
break;
|
||||
case "getScrollX":
|
||||
result.success(getScrollX());
|
||||
break;
|
||||
case "getScrollY":
|
||||
result.success(getScrollY());
|
||||
break;
|
||||
case "getCertificate":
|
||||
result.success(getCertificate());
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
}
|
||||
|
@ -804,14 +821,14 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
result.success(false);
|
||||
}
|
||||
|
||||
public void scrollTo(Integer x, Integer y) {
|
||||
public void scrollTo(Integer x, Integer y, Boolean animated) {
|
||||
if (webView != null)
|
||||
webView.scrollTo(x, y);
|
||||
webView.scrollTo(x, y, animated);
|
||||
}
|
||||
|
||||
public void scrollBy(Integer x, Integer y) {
|
||||
public void scrollBy(Integer x, Integer y, Boolean animated) {
|
||||
if (webView != null)
|
||||
webView.scrollBy(x, y);
|
||||
webView.scrollBy(x, y, animated);
|
||||
}
|
||||
|
||||
public void onPauseWebView() {
|
||||
|
@ -930,6 +947,36 @@ public class InAppBrowserActivity extends AppCompatActivity implements MethodCha
|
|||
webView.contextMenu = contextMenu;
|
||||
}
|
||||
|
||||
public Map<String, Object> requestFocusNodeHref() {
|
||||
if (webView != null)
|
||||
return webView.requestFocusNodeHref();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, Object> requestImageRef() {
|
||||
if (webView != null)
|
||||
return webView.requestImageRef();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getScrollX() {
|
||||
if (webView != null)
|
||||
return webView.getScrollX();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getScrollY() {
|
||||
if (webView != null)
|
||||
return webView.getScrollY();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, Object> getCertificate() {
|
||||
if (webView != null)
|
||||
return webView.getSslCertificate();
|
||||
return null;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
channel.setMethodCallHandler(null);
|
||||
activityResultListeners.clear();
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.hardware.display.DisplayManager;
|
|||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.webkit.ValueCallback;
|
||||
|
@ -308,7 +307,8 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
if (webView != null) {
|
||||
Integer x = (Integer) call.argument("x");
|
||||
Integer y = (Integer) call.argument("y");
|
||||
webView.scrollTo(x, y);
|
||||
Boolean animated = (Boolean) call.argument("animated");
|
||||
webView.scrollTo(x, y, animated);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
@ -316,7 +316,8 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
if (webView != null) {
|
||||
Integer x = (Integer) call.argument("x");
|
||||
Integer y = (Integer) call.argument("y");
|
||||
webView.scrollBy(x, y);
|
||||
Boolean animated = (Boolean) call.argument("animated");
|
||||
webView.scrollBy(x, y, animated);
|
||||
}
|
||||
result.success(true);
|
||||
break;
|
||||
|
@ -461,14 +462,35 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
if (webView != null) {
|
||||
result.success(webView.requestFocusNodeHref());
|
||||
} else {
|
||||
result.success(false);
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "requestImageRef":
|
||||
if (webView != null) {
|
||||
result.success(webView.requestImageRef());
|
||||
} else {
|
||||
result.success(false);
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "getScrollX":
|
||||
if (webView != null) {
|
||||
result.success(webView.getScrollX());
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "getScrollY":
|
||||
if (webView != null) {
|
||||
result.success(webView.getScrollY());
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
case "getCertificate":
|
||||
if (webView != null) {
|
||||
result.success(webView.getSslCertificate());
|
||||
} else {
|
||||
result.success(null);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package com.pichillilorenzo.flutter_inappwebview.InAppWebView;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.net.http.SslCertificate;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
@ -36,6 +39,7 @@ import android.widget.HorizontalScrollView;
|
|||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.webkit.WebViewCompat;
|
||||
import androidx.webkit.WebViewFeature;
|
||||
|
@ -52,6 +56,11 @@ import com.pichillilorenzo.flutter_inappwebview.Util;
|
|||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateNotYetValidException;
|
||||
import java.security.cert.CertificateParsingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -1484,6 +1493,28 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
channel.invokeMethod("onScrollChanged", obj);
|
||||
}
|
||||
|
||||
public void scrollTo(Integer x, Integer y, Boolean animated) {
|
||||
if (animated) {
|
||||
PropertyValuesHolder pvhX = PropertyValuesHolder.ofInt("scrollX", x);
|
||||
PropertyValuesHolder pvhY = PropertyValuesHolder.ofInt("scrollY", y);
|
||||
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(this, pvhX, pvhY);
|
||||
anim.setDuration(300).start();
|
||||
} else {
|
||||
scrollTo(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void scrollBy(Integer x, Integer y, Boolean animated) {
|
||||
if (animated) {
|
||||
PropertyValuesHolder pvhX = PropertyValuesHolder.ofInt("scrollX", getScrollX() + x);
|
||||
PropertyValuesHolder pvhY = PropertyValuesHolder.ofInt("scrollY", getScrollY() + y);
|
||||
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(this, pvhX, pvhY);
|
||||
anim.setDuration(300).start();
|
||||
} else {
|
||||
scrollBy(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
class DownloadStartListener implements DownloadListener {
|
||||
@Override
|
||||
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
|
||||
|
@ -1833,6 +1864,110 @@ final public class InAppWebView extends InputAwareWebView {
|
|||
return obj;
|
||||
}
|
||||
|
||||
public Map<String, Object> getSslCertificate() {
|
||||
SslCertificate sslCertificate = getCertificate();
|
||||
|
||||
SslCertificate.DName issuedByName = sslCertificate.getIssuedBy();
|
||||
Map<String, Object> issuedBy = new HashMap<>();
|
||||
issuedBy.put("CName", issuedByName.getCName());
|
||||
issuedBy.put("DName", issuedByName.getDName());
|
||||
issuedBy.put("OName", issuedByName.getOName());
|
||||
issuedBy.put("UName", issuedByName.getUName());
|
||||
|
||||
SslCertificate.DName issuedToName = sslCertificate.getIssuedTo();
|
||||
Map<String, Object> issuedTo = new HashMap<>();
|
||||
issuedTo.put("CName", issuedToName.getCName());
|
||||
issuedTo.put("DName", issuedToName.getDName());
|
||||
issuedTo.put("OName", issuedToName.getOName());
|
||||
issuedTo.put("UName", issuedToName.getUName());
|
||||
|
||||
Map<String, Object> x509CertificateMap = new HashMap<>();
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||
X509Certificate x509Certificate = sslCertificate.getX509Certificate();
|
||||
if (x509Certificate != null) {
|
||||
x509CertificateMap.put("basicConstraints", x509Certificate.getBasicConstraints());
|
||||
try {
|
||||
x509CertificateMap.put("extendedKeyUsage", x509Certificate.getExtendedKeyUsage());
|
||||
} catch (CertificateParsingException e) {
|
||||
x509CertificateMap.put("extendedKeyUsage", null);
|
||||
}
|
||||
|
||||
Map<String, Object> issuerDN = new HashMap<>();
|
||||
issuerDN.put("name", x509Certificate.getIssuerDN().getName());
|
||||
x509CertificateMap.put("issuerDN", issuerDN);
|
||||
|
||||
x509CertificateMap.put("issuerUniqueID", x509Certificate.getIssuerUniqueID());
|
||||
|
||||
Map<String, Object> issuerX500Principal = new HashMap<>();
|
||||
issuerX500Principal.put("name", x509Certificate.getIssuerX500Principal().getName());
|
||||
issuerX500Principal.put("encoded", x509Certificate.getIssuerX500Principal().getEncoded());
|
||||
x509CertificateMap.put("issuerX500Principal", issuerX500Principal);
|
||||
|
||||
x509CertificateMap.put("keyUsage", x509Certificate.getKeyUsage());
|
||||
x509CertificateMap.put("notAfter", x509Certificate.getNotAfter().getTime());
|
||||
x509CertificateMap.put("notBefore", x509Certificate.getNotBefore().getTime());
|
||||
x509CertificateMap.put("serialNumber", x509Certificate.getSerialNumber().longValue());
|
||||
x509CertificateMap.put("sigAlgName", x509Certificate.getSigAlgName());
|
||||
x509CertificateMap.put("sigAlgOID", x509Certificate.getSigAlgOID());
|
||||
x509CertificateMap.put("sigAlgParams", x509Certificate.getSigAlgParams());
|
||||
x509CertificateMap.put("signature", x509Certificate.getSignature());
|
||||
|
||||
Map<String, Object> subjectDN = new HashMap<>();
|
||||
subjectDN.put("name", x509Certificate.getSubjectDN().getName());
|
||||
x509CertificateMap.put("subjectDN", subjectDN);
|
||||
|
||||
x509CertificateMap.put("subjectUniqueID", x509Certificate.getSubjectUniqueID());
|
||||
|
||||
Map<String, Object> subjectX500Principal = new HashMap<>();
|
||||
subjectX500Principal.put("name", x509Certificate.getSubjectX500Principal().getName());
|
||||
subjectX500Principal.put("encoded", x509Certificate.getSubjectX500Principal().getEncoded());
|
||||
x509CertificateMap.put("subjectX500Principal", subjectX500Principal);
|
||||
|
||||
try {
|
||||
x509CertificateMap.put("TBSCertificate", x509Certificate.getTBSCertificate());
|
||||
} catch (CertificateEncodingException e) {
|
||||
x509CertificateMap.put("TBSCertificate", null);
|
||||
}
|
||||
|
||||
x509CertificateMap.put("version", x509Certificate.getVersion());
|
||||
x509CertificateMap.put("criticalExtensionOIDs", x509Certificate.getCriticalExtensionOIDs());
|
||||
x509CertificateMap.put("nonCriticalExtensionOIDs", x509Certificate.getNonCriticalExtensionOIDs());
|
||||
try {
|
||||
x509CertificateMap.put("encoded", x509Certificate.getEncoded());
|
||||
} catch (CertificateEncodingException e) {
|
||||
x509CertificateMap.put("encoded", null);
|
||||
}
|
||||
|
||||
Map<String, Object> publicKey = new HashMap<>();
|
||||
publicKey.put("algorithm", x509Certificate.getPublicKey().getAlgorithm());
|
||||
publicKey.put("encoded", x509Certificate.getPublicKey().getEncoded());
|
||||
publicKey.put("format", x509Certificate.getPublicKey().getFormat());
|
||||
x509CertificateMap.put("publicKey", publicKey);
|
||||
|
||||
x509CertificateMap.put("type", x509Certificate.getType());
|
||||
x509CertificateMap.put("hasUnsupportedCriticalExtension", x509Certificate.hasUnsupportedCriticalExtension());
|
||||
|
||||
try {
|
||||
x509Certificate.checkValidity();
|
||||
x509CertificateMap.put("valid", true);
|
||||
} catch (CertificateExpiredException e) {
|
||||
x509CertificateMap.put("valid", false);
|
||||
} catch (CertificateNotYetValidException e) {
|
||||
x509CertificateMap.put("valid", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
obj.put("issuedBy", issuedBy);
|
||||
obj.put("issuedTo", issuedTo);
|
||||
obj.put("validNotAfterDate", sslCertificate.getValidNotAfterDate().getTime());
|
||||
obj.put("validNotBeforeDate", sslCertificate.getValidNotBeforeDate().getTime());
|
||||
obj.put("x509Certificate", x509CertificateMap);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
|
|
|
@ -29,9 +29,11 @@ import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.Credential;
|
|||
import com.pichillilorenzo.flutter_inappwebview.CredentialDatabase.CredentialDatabase;
|
||||
import com.pichillilorenzo.flutter_inappwebview.InAppBrowser.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Shared;
|
||||
import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
@ -426,7 +428,8 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
obj.put("protocol", protocol);
|
||||
obj.put("realm", realm);
|
||||
obj.put("port", port);
|
||||
obj.put("error", error.getPrimaryError());
|
||||
obj.put("androidError", error.getPrimaryError());
|
||||
obj.put("iosError", null);
|
||||
obj.put("serverCertificate", null);
|
||||
try {
|
||||
X509Certificate certificate;
|
||||
|
|
|
@ -6,6 +6,8 @@ import android.webkit.CookieManager;
|
|||
import android.webkit.CookieSyncManager;
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
@ -47,7 +49,19 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
|
|||
Long expiresDate = (expiresDateString != null ? new Long(expiresDateString) : null);
|
||||
Integer maxAge = (Integer) call.argument("maxAge");
|
||||
Boolean isSecure = (Boolean) call.argument("isSecure");
|
||||
MyCookieManager.setCookie(url, name, value, domain, path, expiresDate, maxAge, isSecure, result);
|
||||
Boolean isHttpOnly = (Boolean) call.argument("isHttpOnly");
|
||||
String sameSite = (String) call.argument("sameSite");
|
||||
MyCookieManager.setCookie(url,
|
||||
name,
|
||||
value,
|
||||
domain,
|
||||
path,
|
||||
expiresDate,
|
||||
maxAge,
|
||||
isSecure,
|
||||
isHttpOnly,
|
||||
sameSite,
|
||||
result);
|
||||
}
|
||||
break;
|
||||
case "getCookies":
|
||||
|
@ -86,6 +100,8 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
|
|||
Long expiresDate,
|
||||
Integer maxAge,
|
||||
Boolean isSecure,
|
||||
Boolean isHttpOnly,
|
||||
String sameSite,
|
||||
final MethodChannel.Result result) {
|
||||
|
||||
String cookieValue = name + "=" + value + "; Domain=" + domain + "; Path=" + path;
|
||||
|
@ -99,6 +115,12 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
|
|||
if (isSecure != null && isSecure)
|
||||
cookieValue += "; Secure";
|
||||
|
||||
if (isHttpOnly != null && isHttpOnly)
|
||||
cookieValue += "; HttpOnly";
|
||||
|
||||
if (sameSite != null)
|
||||
cookieValue += "; SameSite=" + sameSite;
|
||||
|
||||
cookieValue += ";";
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
|
@ -135,6 +157,14 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
|
|||
Map<String, Object> cookieMap = new HashMap<>();
|
||||
cookieMap.put("name", name);
|
||||
cookieMap.put("value", value);
|
||||
cookieMap.put("expiresDate", null);
|
||||
cookieMap.put("isSessionOnly", null);
|
||||
cookieMap.put("domain", null);
|
||||
cookieMap.put("sameSite", null);
|
||||
cookieMap.put("isSecure", null);
|
||||
cookieMap.put("isHttpOnly", null);
|
||||
cookieMap.put("path", null);
|
||||
|
||||
cookieListMap.add(cookieMap);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.9/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.9/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-06-12 02:54:04.283438","version":"1.17.1"}
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.9/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"android":[{"name":"e2e","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/e2e-0.2.4+4/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.4.4/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.9/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.0+hotfix.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+3/","dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"e2e","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"permission_handler","dependencies":[]}],"date_created":"2020-06-13 01:39:11.912485","version":"1.17.1"}
|
|
@ -16,6 +16,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
ContextMenu contextMenu;
|
||||
String url = "";
|
||||
double progress = 0;
|
||||
CookieManager _cookieManager = CookieManager.instance();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -78,8 +79,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
||||
child: InAppWebView(
|
||||
contextMenu: contextMenu,
|
||||
// initialUrl: "https://github.com/flutter",
|
||||
initialFile: "assets/index.html",
|
||||
initialUrl: "https://github.com/flutter",
|
||||
// initialFile: "assets/index.html",
|
||||
initialHeaders: {},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
|
@ -101,37 +102,12 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
print("shouldOverrideUrlLoading");
|
||||
return ShouldOverrideUrlLoadingAction.ALLOW;
|
||||
},
|
||||
onCreateWindow: (controller, onCreateWindowRequest) {
|
||||
print("onCreateWindow");
|
||||
},
|
||||
onLoadStop: (InAppWebViewController controller, String url) async {
|
||||
print("onLoadStop $url");
|
||||
setState(() {
|
||||
this.url = url;
|
||||
});
|
||||
/*var origins = await WebStorageManager.instance().android.getOrigins();
|
||||
for (var origin in origins) {
|
||||
print(origin);
|
||||
print(await WebStorageManager.instance().android.getQuotaForOrigin(origin: origin.origin));
|
||||
print(await WebStorageManager.instance().android.getUsageForOrigin(origin: origin.origin));
|
||||
}
|
||||
await WebStorageManager.instance().android.deleteAllData();
|
||||
print("\n\nDELETED\n\n");
|
||||
origins = await WebStorageManager.instance().android.getOrigins();
|
||||
for (var origin in origins) {
|
||||
print(origin);
|
||||
await WebStorageManager.instance().android.deleteOrigin(origin: origin.origin);
|
||||
}*/
|
||||
/*var records = await WebStorageManager.instance().ios.fetchDataRecords(dataTypes: IOSWKWebsiteDataType.ALL);
|
||||
for(var record in records) {
|
||||
print(record);
|
||||
}
|
||||
await WebStorageManager.instance().ios.removeDataModifiedSince(dataTypes: IOSWKWebsiteDataType.ALL, date: DateTime(0));
|
||||
print("\n\nDELETED\n\n");
|
||||
records = await WebStorageManager.instance().ios.fetchDataRecords(dataTypes: IOSWKWebsiteDataType.ALL);
|
||||
for(var record in records) {
|
||||
print(record);
|
||||
}*/
|
||||
|
||||
},
|
||||
onProgressChanged: (InAppWebViewController controller, int progress) {
|
||||
setState(() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
|
@ -347,7 +347,8 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
|
|||
if webView != nil {
|
||||
let x = arguments!["x"] as! Int
|
||||
let y = arguments!["y"] as! Int
|
||||
webView!.scrollTo(x: x, y: y)
|
||||
let animated = arguments!["animated"] as! Bool
|
||||
webView!.scrollTo(x: x, y: y, animated: animated)
|
||||
}
|
||||
result(true)
|
||||
break
|
||||
|
@ -355,7 +356,8 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
|
|||
if webView != nil {
|
||||
let x = arguments!["x"] as! Int
|
||||
let y = arguments!["y"] as! Int
|
||||
webView!.scrollBy(x: x, y: y)
|
||||
let animated = arguments!["animated"] as! Bool
|
||||
webView!.scrollBy(x: x, y: y, animated: animated)
|
||||
}
|
||||
result(true)
|
||||
break
|
||||
|
@ -475,6 +477,20 @@ public class FlutterWebViewController: FlutterMethodCallDelegate, FlutterPlatfor
|
|||
result(false)
|
||||
}
|
||||
break
|
||||
case "getScrollX":
|
||||
if webView != nil {
|
||||
result(Int(webView!.scrollView.contentOffset.x))
|
||||
} else {
|
||||
result(false)
|
||||
}
|
||||
break
|
||||
case "getScrollY":
|
||||
if webView != nil {
|
||||
result(Int(webView!.scrollView.contentOffset.y))
|
||||
} else {
|
||||
result(false)
|
||||
}
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
break
|
||||
|
|
|
@ -243,13 +243,15 @@ public class InAppBrowserWebViewController: UIViewController, FlutterPlugin, UIS
|
|||
case "scrollTo":
|
||||
let x = arguments!["x"] as! Int
|
||||
let y = arguments!["y"] as! Int
|
||||
webView.scrollTo(x: x, y: y)
|
||||
let animated = arguments!["animated"] as! Bool
|
||||
webView.scrollTo(x: x, y: y, animated: animated)
|
||||
result(true)
|
||||
break
|
||||
case "scrollBy":
|
||||
let x = arguments!["x"] as! Int
|
||||
let y = arguments!["y"] as! Int
|
||||
webView.scrollTo(x: x, y: y)
|
||||
let animated = arguments!["animated"] as! Bool
|
||||
webView.scrollTo(x: x, y: y, animated: animated)
|
||||
result(true)
|
||||
break
|
||||
case "pauseTimers":
|
||||
|
|
|
@ -1105,6 +1105,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
|
||||
if #available(iOS 11.0, *) {
|
||||
accessibilityIgnoresInvertColors = (options?.accessibilityIgnoresInvertColors)!
|
||||
scrollView.contentInsetAdjustmentBehavior =
|
||||
UIScrollView.ContentInsetAdjustmentBehavior.init(rawValue: (options?.contentInsetAdjustmentBehavior)!)!
|
||||
}
|
||||
|
||||
configuration.suppressesIncrementalRendering = (options?.suppressesIncrementalRendering)!
|
||||
|
@ -1488,6 +1490,10 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
if newOptionsMap["accessibilityIgnoresInvertColors"] != nil && options?.accessibilityIgnoresInvertColors != newOptions.accessibilityIgnoresInvertColors {
|
||||
accessibilityIgnoresInvertColors = newOptions.accessibilityIgnoresInvertColors
|
||||
}
|
||||
if newOptionsMap["contentInsetAdjustmentBehavior"] != nil && options?.contentInsetAdjustmentBehavior != newOptions.contentInsetAdjustmentBehavior {
|
||||
scrollView.contentInsetAdjustmentBehavior =
|
||||
UIScrollView.ContentInsetAdjustmentBehavior.init(rawValue: newOptions.contentInsetAdjustmentBehavior)!
|
||||
}
|
||||
}
|
||||
|
||||
if newOptionsMap["enableViewportScale"] != nil && options?.enableViewportScale != newOptions.enableViewportScale {
|
||||
|
@ -2542,6 +2548,10 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
public func onReceivedServerTrustAuthRequest(challenge: URLAuthenticationChallenge, result: FlutterResult?) {
|
||||
var serverCertificateData: NSData?
|
||||
let serverTrust = challenge.protectionSpace.serverTrust!
|
||||
|
||||
var secResult = SecTrustResultType.invalid
|
||||
SecTrustEvaluate(serverTrust, &secResult);
|
||||
|
||||
if let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) {
|
||||
let serverCertificateCFData = SecCertificateCopyData(serverCertificate)
|
||||
let data = CFDataGetBytePtr(serverCertificateCFData)
|
||||
|
@ -2549,6 +2559,32 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
serverCertificateData = NSData(bytes: data, length: size)
|
||||
}
|
||||
|
||||
let error = secResult != SecTrustResultType.proceed ? secResult.rawValue : nil
|
||||
|
||||
var message = ""
|
||||
switch secResult {
|
||||
case .deny:
|
||||
message = "Indicates a user-configured deny; do not proceed."
|
||||
break
|
||||
case .fatalTrustFailure:
|
||||
message = "Indicates a trust failure which cannot be overridden by the user."
|
||||
break
|
||||
case .invalid:
|
||||
message = "Indicates an invalid setting or result."
|
||||
break
|
||||
case .otherError:
|
||||
message = "Indicates a failure other than that of trust evaluation."
|
||||
break
|
||||
case .recoverableTrustFailure:
|
||||
message = "Indicates a trust policy failure which can be overridden by the user."
|
||||
break
|
||||
case .unspecified:
|
||||
message = "Indicates the evaluation succeeded and the certificate is implicitly trusted, but user intent was not explicitly specified."
|
||||
break
|
||||
default:
|
||||
message = ""
|
||||
}
|
||||
|
||||
let arguments: [String: Any?] = [
|
||||
"host": challenge.protectionSpace.host,
|
||||
"protocol": challenge.protectionSpace.protocol,
|
||||
|
@ -2556,8 +2592,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
"port": challenge.protectionSpace.port,
|
||||
"previousFailureCount": challenge.previousFailureCount,
|
||||
"serverCertificate": serverCertificateData,
|
||||
"error": -1,
|
||||
"message": "",
|
||||
"androidError": nil,
|
||||
"iosError": error,
|
||||
"message": message,
|
||||
]
|
||||
channel?.invokeMethod("onReceivedServerTrustAuthRequest", arguments: arguments, result: result)
|
||||
}
|
||||
|
@ -2746,14 +2783,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
evaluateJavaScript("wkwebview_ClearMatches();", completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
public func scrollTo(x: Int, y: Int) {
|
||||
scrollView.setContentOffset(CGPoint(x: x, y: y), animated: false)
|
||||
public func scrollTo(x: Int, y: Int, animated: Bool) {
|
||||
scrollView.setContentOffset(CGPoint(x: x, y: y), animated: animated)
|
||||
}
|
||||
|
||||
public func scrollBy(x: Int, y: Int) {
|
||||
public func scrollBy(x: Int, y: Int, animated: Bool) {
|
||||
let newX = CGFloat(x) + scrollView.contentOffset.x
|
||||
let newY = CGFloat(y) + scrollView.contentOffset.y
|
||||
scrollView.setContentOffset(CGPoint(x: newX, y: newY), animated: false)
|
||||
scrollView.setContentOffset(CGPoint(x: newX, y: newY), animated: animated)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ public class InAppWebViewOptions: Options<InAppWebView> {
|
|||
var isPagingEnabled = false
|
||||
var maximumZoomScale = 1.0
|
||||
var minimumZoomScale = 1.0
|
||||
var contentInsetAdjustmentBehavior = 2 // UIScrollView.ContentInsetAdjustmentBehavior.never
|
||||
|
||||
override init(){
|
||||
super.init()
|
||||
|
@ -96,6 +97,7 @@ public class InAppWebViewOptions: Options<InAppWebView> {
|
|||
realOptions["selectionGranularity"] = configuration.selectionGranularity.rawValue
|
||||
if #available(iOS 11.0, *) {
|
||||
realOptions["accessibilityIgnoresInvertColors"] = webView.accessibilityIgnoresInvertColors
|
||||
realOptions["contentInsetAdjustmentBehavior"] = webView.scrollView.contentInsetAdjustmentBehavior.rawValue
|
||||
}
|
||||
realOptions["decelerationRate"] = InAppWebView.getDecelerationRateString(type: webView.scrollView.decelerationRate)
|
||||
realOptions["alwaysBounceVertical"] = webView.scrollView.alwaysBounceVertical
|
||||
|
|
|
@ -45,8 +45,20 @@ class MyCookieManager: NSObject, FlutterPlugin {
|
|||
|
||||
let maxAge = arguments!["maxAge"] as? Int64
|
||||
let isSecure = arguments!["isSecure"] as? Bool
|
||||
let isHttpOnly = arguments!["isHttpOnly"] as? Bool
|
||||
let sameSite = arguments!["sameSite"] as? String
|
||||
|
||||
MyCookieManager.setCookie(url: url, name: name, value: value, domain: domain, path: path, expiresDate: expiresDate, maxAge: maxAge, isSecure: isSecure, result: result)
|
||||
MyCookieManager.setCookie(url: url,
|
||||
name: name,
|
||||
value: value,
|
||||
domain: domain,
|
||||
path: path,
|
||||
expiresDate: expiresDate,
|
||||
maxAge: maxAge,
|
||||
isSecure: isSecure,
|
||||
isHttpOnly: isHttpOnly,
|
||||
sameSite: sameSite,
|
||||
result: result)
|
||||
break
|
||||
case "getCookies":
|
||||
let url = arguments!["url"] as! String
|
||||
|
@ -82,6 +94,8 @@ class MyCookieManager: NSObject, FlutterPlugin {
|
|||
expiresDate: Int64?,
|
||||
maxAge: Int64?,
|
||||
isSecure: Bool?,
|
||||
isHttpOnly: Bool?,
|
||||
sameSite: String?,
|
||||
result: @escaping FlutterResult) {
|
||||
var properties: [HTTPCookiePropertyKey: Any] = [:]
|
||||
properties[.originURL] = url
|
||||
|
@ -90,6 +104,7 @@ class MyCookieManager: NSObject, FlutterPlugin {
|
|||
properties[.domain] = domain
|
||||
properties[.path] = path
|
||||
if expiresDate != nil {
|
||||
// convert from milliseconds
|
||||
properties[.expires] = Date(timeIntervalSince1970: TimeInterval(Double(expiresDate!)/1000))
|
||||
}
|
||||
if maxAge != nil {
|
||||
|
@ -98,21 +113,61 @@ class MyCookieManager: NSObject, FlutterPlugin {
|
|||
if isSecure != nil && isSecure! {
|
||||
properties[.secure] = "TRUE"
|
||||
}
|
||||
if isHttpOnly != nil && isHttpOnly! {
|
||||
properties[.init("HttpOnly")] = "YES"
|
||||
}
|
||||
if sameSite != nil {
|
||||
if #available(iOS 13.0, *) {
|
||||
var sameSiteValue = HTTPCookieStringPolicy(rawValue: "None")
|
||||
switch sameSite {
|
||||
case "Lax":
|
||||
sameSiteValue = HTTPCookieStringPolicy.sameSiteLax
|
||||
case "Strict":
|
||||
sameSiteValue = HTTPCookieStringPolicy.sameSiteStrict
|
||||
default:
|
||||
break
|
||||
}
|
||||
properties[.sameSitePolicy] = sameSiteValue
|
||||
} else {
|
||||
properties[.init("SameSite")] = sameSite
|
||||
}
|
||||
}
|
||||
|
||||
let cookie = HTTPCookie(properties: properties)!
|
||||
|
||||
MyCookieManager.httpCookieStore!.setCookie(cookie, completionHandler: {() in
|
||||
result(true)
|
||||
})
|
||||
}
|
||||
|
||||
public static func getCookies(url: String, result: @escaping FlutterResult) {
|
||||
var cookieList: [[String: Any]] = []
|
||||
var cookieList: [[String: Any?]] = []
|
||||
MyCookieManager.httpCookieStore!.getAllCookies { (cookies) in
|
||||
for cookie in cookies {
|
||||
if cookie.domain.contains(URL(string: url)!.host!) {
|
||||
var sameSite: String? = nil
|
||||
if #available(iOS 13.0, *) {
|
||||
if let sameSiteValue = cookie.sameSitePolicy?.rawValue {
|
||||
sameSite = sameSiteValue.prefix(1).capitalized + sameSiteValue.dropFirst()
|
||||
}
|
||||
}
|
||||
|
||||
var expiresDateTimestamp: Int64 = -1
|
||||
if let expiresDate = cookie.expiresDate?.timeIntervalSince1970 {
|
||||
// convert to milliseconds
|
||||
expiresDateTimestamp = Int64(expiresDate * 1000)
|
||||
}
|
||||
|
||||
cookieList.append([
|
||||
"name": cookie.name,
|
||||
"value": cookie.value
|
||||
"value": cookie.value,
|
||||
"expiresDate": expiresDateTimestamp != -1 ? expiresDateTimestamp : nil,
|
||||
"isSessionOnly": cookie.isSessionOnly,
|
||||
"domain": cookie.domain,
|
||||
"sameSite": sameSite,
|
||||
"isSecure": cookie.isSecure,
|
||||
"isHttpOnly": cookie.isHTTPOnly,
|
||||
"path": cookie.path,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,8 +40,10 @@ class CookieManager {
|
|||
String path = "/",
|
||||
int expiresDate,
|
||||
int maxAge,
|
||||
bool isSecure}) async {
|
||||
if (domain == null || domain.isEmpty) domain = _getDomainName(url);
|
||||
bool isSecure,
|
||||
bool isHttpOnly,
|
||||
HTTPCookieSameSitePolicy sameSite}) async {
|
||||
if (domain == null) domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(name != null && name.isNotEmpty);
|
||||
|
@ -58,6 +60,8 @@ class CookieManager {
|
|||
args.putIfAbsent('expiresDate', () => expiresDate?.toString());
|
||||
args.putIfAbsent('maxAge', () => maxAge);
|
||||
args.putIfAbsent('isSecure', () => isSecure);
|
||||
args.putIfAbsent('isHttpOnly', () => isHttpOnly);
|
||||
args.putIfAbsent('sameSite', () => sameSite?.toValue());
|
||||
|
||||
await _channel.invokeMethod('setCookie', args);
|
||||
}
|
||||
|
@ -71,10 +75,19 @@ class CookieManager {
|
|||
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"]));
|
||||
name: cookieListMap[i]["name"],
|
||||
value: cookieListMap[i]["value"],
|
||||
expiresDate: cookieListMap[i]["expiresDate"],
|
||||
isSessionOnly: cookieListMap[i]["isSessionOnly"],
|
||||
domain: cookieListMap[i]["domain"],
|
||||
sameSite: HTTPCookieSameSitePolicy.fromValue(cookieListMap[i]["sameSite"]),
|
||||
isSecure: cookieListMap[i]["isSecure"],
|
||||
isHttpOnly: cookieListMap[i]["isHttpOnly"],
|
||||
path: cookieListMap[i]["path"]));
|
||||
}
|
||||
return cookies;
|
||||
}
|
||||
|
@ -92,7 +105,16 @@ class CookieManager {
|
|||
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"]);
|
||||
return Cookie(
|
||||
name: cookies[i]["name"],
|
||||
value: cookies[i]["value"],
|
||||
expiresDate: cookies[i]["expiresDate"],
|
||||
isSessionOnly: cookies[i]["isSessionOnly"],
|
||||
domain: cookies[i]["domain"],
|
||||
sameSite: HTTPCookieSameSitePolicy.fromValue(cookies[i]["sameSite"]),
|
||||
isSecure: cookies[i]["isSecure"],
|
||||
isHttpOnly: cookies[i]["isHttpOnly"],
|
||||
path: cookies[i]["path"]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -203,36 +203,19 @@ class InAppBrowser {
|
|||
await _channel.invokeMethod('setOptions', args);
|
||||
}
|
||||
|
||||
///Gets the current [InAppBrowser] options as a `Map`. Returns `null` if the options are not setted yet.
|
||||
///Gets the current [InAppBrowser] options. Returns `null` if it wasn't able to get them.
|
||||
Future<InAppBrowserClassOptions> getOptions() async {
|
||||
this.throwIsNotOpened();
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
||||
InAppBrowserClassOptions inAppBrowserClassOptions =
|
||||
InAppBrowserClassOptions();
|
||||
Map<dynamic, dynamic> options =
|
||||
await _channel.invokeMethod('getOptions', args);
|
||||
if (options != null) {
|
||||
options = options.cast<String, dynamic>();
|
||||
inAppBrowserClassOptions.crossPlatform =
|
||||
InAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions =
|
||||
InAppWebViewGroupOptions();
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions.crossPlatform =
|
||||
InAppWebViewOptions.fromMap(options);
|
||||
if (Platform.isAndroid) {
|
||||
inAppBrowserClassOptions.android =
|
||||
AndroidInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions.android =
|
||||
AndroidInAppWebViewOptions.fromMap(options);
|
||||
} else if (Platform.isIOS) {
|
||||
inAppBrowserClassOptions.ios = IOSInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions.ios =
|
||||
IOSInAppWebViewOptions.fromMap(options);
|
||||
}
|
||||
return InAppBrowserClassOptions.fromMap(options);
|
||||
}
|
||||
|
||||
return inAppBrowserClassOptions;
|
||||
return null;
|
||||
}
|
||||
|
||||
///Returns `true` if the [InAppBrowser] instance is opened, otherwise `false`.
|
||||
|
|
|
@ -366,14 +366,20 @@ class InAppWebViewController {
|
|||
String protocol = call.arguments["protocol"];
|
||||
String realm = call.arguments["realm"];
|
||||
int port = call.arguments["port"];
|
||||
int error = call.arguments["error"];
|
||||
int androidError = call.arguments["androidError"];
|
||||
int iosError = call.arguments["iosError"];
|
||||
String message = call.arguments["message"];
|
||||
Uint8List serverCertificate = call.arguments["serverCertificate"];
|
||||
|
||||
AndroidSslError androidSslError = androidError != null ? AndroidSslError.fromValue(androidError) : null;
|
||||
IOSSslError iosSslError = iosError != null ? IOSSslError.fromValue(iosError) : null;
|
||||
|
||||
var protectionSpace = ProtectionSpace(
|
||||
host: host, protocol: protocol, realm: realm, port: port);
|
||||
var challenge = ServerTrustChallenge(
|
||||
protectionSpace: protectionSpace,
|
||||
error: error,
|
||||
androidError: androidSslError,
|
||||
iosError: iosSslError,
|
||||
message: message,
|
||||
serverCertificate: serverCertificate);
|
||||
if (_webview != null &&
|
||||
|
@ -811,8 +817,10 @@ class InAppWebViewController {
|
|||
if (webviewUrl.startsWith("file:///")) {
|
||||
var assetPathSplitted = webviewUrl.split("/flutter_assets/");
|
||||
var assetPath = assetPathSplitted[assetPathSplitted.length - 1];
|
||||
try {
|
||||
var bytes = await rootBundle.load(assetPath);
|
||||
html = utf8.decode(bytes.buffer.asUint8List());
|
||||
} catch (e) {}
|
||||
} else {
|
||||
HttpClient client = new HttpClient();
|
||||
var url = Uri.parse(webviewUrl);
|
||||
|
@ -839,7 +847,7 @@ class InAppWebViewController {
|
|||
String manifestUrl;
|
||||
|
||||
var html = await getHtml();
|
||||
if (html != null && html.isEmpty) {
|
||||
if (html == null || (html != null && html.isEmpty)) {
|
||||
return favicons;
|
||||
}
|
||||
|
||||
|
@ -880,8 +888,9 @@ 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, stacktrace) {
|
||||
print("/favicon.ico file not found: " + e.toString());
|
||||
print(stacktrace);
|
||||
}
|
||||
|
||||
// try to get the manifest file
|
||||
|
@ -896,8 +905,9 @@ class InAppWebViewController {
|
|||
manifestResponse = await manifestRequest.close();
|
||||
manifestFound = manifestResponse.statusCode == 200 &&
|
||||
manifestResponse.headers.contentType?.mimeType == "application/json";
|
||||
} catch (e) {
|
||||
} catch (e, stacktrace) {
|
||||
print("Manifest file not found: " + e.toString());
|
||||
print(stacktrace);
|
||||
}
|
||||
|
||||
if (manifestFound) {
|
||||
|
@ -1261,26 +1271,18 @@ class InAppWebViewController {
|
|||
await _channel.invokeMethod('setOptions', args);
|
||||
}
|
||||
|
||||
///Gets the current WebView options. Returns the options with `null` value if they are not set yet.
|
||||
///Gets the current WebView options. Returns `null` if it wasn't able to get them.
|
||||
Future<InAppWebViewGroupOptions> getOptions() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
||||
InAppWebViewGroupOptions inAppWebViewGroupOptions =
|
||||
InAppWebViewGroupOptions();
|
||||
Map<dynamic, dynamic> options =
|
||||
await _channel.invokeMethod('getOptions', args);
|
||||
if (options != null) {
|
||||
options = options.cast<String, dynamic>();
|
||||
inAppWebViewGroupOptions.crossPlatform =
|
||||
InAppWebViewOptions.fromMap(options);
|
||||
if (Platform.isAndroid)
|
||||
inAppWebViewGroupOptions.android =
|
||||
AndroidInAppWebViewOptions.fromMap(options);
|
||||
else if (Platform.isIOS)
|
||||
inAppWebViewGroupOptions.ios = IOSInAppWebViewOptions.fromMap(options);
|
||||
return InAppWebViewGroupOptions.fromMap(options);
|
||||
}
|
||||
|
||||
return inAppWebViewGroupOptions;
|
||||
return null;
|
||||
}
|
||||
|
||||
///Gets the WebHistory for this WebView. This contains the back/forward list for use in querying each item in the history stack.
|
||||
|
@ -1378,13 +1380,16 @@ class InAppWebViewController {
|
|||
///
|
||||
///[y] represents the y position to scroll to.
|
||||
///
|
||||
///[animated] `true` to animate the scroll transition, `false` to make the scoll transition immediate.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#scrollTo(int,%20int)
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset
|
||||
Future<void> scrollTo({@required int x, @required int y}) async {
|
||||
Future<void> scrollTo({@required int x, @required int y, bool animated = false}) async {
|
||||
assert(x != null && y != null);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('x', () => x);
|
||||
args.putIfAbsent('y', () => y);
|
||||
args.putIfAbsent('animated', () => animated ?? false);
|
||||
await _channel.invokeMethod('scrollTo', args);
|
||||
}
|
||||
|
||||
|
@ -1394,13 +1399,16 @@ class InAppWebViewController {
|
|||
///
|
||||
///[y] represents the amount of pixels to scroll by vertically.
|
||||
///
|
||||
///[animated] `true` to animate the scroll transition, `false` to make the scoll transition immediate.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#scrollBy(int,%20int)
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset
|
||||
Future<void> scrollBy({@required int x, @required int y}) async {
|
||||
Future<void> scrollBy({@required int x, @required int y, bool animated = false}) async {
|
||||
assert(x != null && y != null);
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('x', () => x);
|
||||
args.putIfAbsent('y', () => y);
|
||||
args.putIfAbsent('animated', () => animated ?? false);
|
||||
await _channel.invokeMethod('scrollBy', args);
|
||||
}
|
||||
|
||||
|
@ -1447,13 +1455,15 @@ class InAppWebViewController {
|
|||
|
||||
///Performs a zoom operation in this WebView.
|
||||
///
|
||||
///[zoomFactor] represents the zoom factor to apply. On Android, the zoom factor will be clamped to the Webview's zoom limits and, also, this value must be in the range 0.01 to 100.0 inclusive.
|
||||
///[zoomFactor] represents the zoom factor to apply. On Android, the zoom factor will be clamped to the Webview's zoom limits and, also, this value must be in the range 0.01 (excluded) to 100.0 (included).
|
||||
///
|
||||
///**NOTE**: available on Android 21+.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#zoomBy(float)
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619412-setzoomscale
|
||||
Future<void> zoomBy(double zoomFactor) async {
|
||||
assert(!Platform.isAndroid || (Platform.isAndroid && zoomFactor > 0.01 && zoomFactor <= 100.0));
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
args.putIfAbsent('zoomFactor', () => zoomFactor);
|
||||
return await _channel.invokeMethod('zoomBy', args);
|
||||
|
@ -1627,6 +1637,24 @@ class InAppWebViewController {
|
|||
return Util.convertColorFromStringRepresentation(colorValue);
|
||||
}
|
||||
|
||||
///Returns the scrolled left position of the current WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#getScrollX()
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619404-contentoffset
|
||||
Future<int> getScrollX() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('getScrollX', args);
|
||||
}
|
||||
|
||||
///Returns the scrolled top position of the current WebView.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/view/View#getScrollY()
|
||||
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619404-contentoffset
|
||||
Future<int> getScrollY() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
return await _channel.invokeMethod('getScrollY', args);
|
||||
}
|
||||
|
||||
///Gets the default user agent.
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebSettings#getDefaultUserAgent(android.content.Context)
|
||||
|
@ -1766,6 +1794,16 @@ class AndroidInAppWebViewController {
|
|||
return await _controller._channel.invokeMethod('clearHistory', args);
|
||||
}
|
||||
|
||||
///Gets the SSL certificate for the main top-level page or null if there is no certificate (the site is not secure).
|
||||
///
|
||||
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#getCertificate()
|
||||
Future<AndroidSslCertificate> getCertificate() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
var sslCertificateMap = (await _controller._channel.invokeMethod('getCertificate', args))?.cast<String, dynamic>();
|
||||
|
||||
return sslCertificateMap != null ? AndroidSslCertificate.fromMap(sslCertificateMap) : null;
|
||||
}
|
||||
|
||||
///Clears the client certificate preferences stored in response to proceeding/cancelling client cert requests.
|
||||
///Note that WebView automatically clears these preferences when the system keychain is updated.
|
||||
///The preferences are shared by all the WebViews that are created by the embedder application.
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'http_auth_credentials_database.dart';
|
|||
import 'chrome_safari_browser.dart';
|
||||
import 'cookie_manager.dart';
|
||||
import 'web_storage_manager.dart';
|
||||
import 'web_storage.dart';
|
||||
|
||||
var uuidGenerator = new Uuid();
|
||||
|
||||
|
@ -912,12 +913,13 @@ class ServerTrustChallenge {
|
|||
///The protection space requiring authentication.
|
||||
ProtectionSpace protectionSpace;
|
||||
|
||||
///The primary error associated to the server SSL certificate.
|
||||
///
|
||||
///**NOTE**: on iOS this value is always -1.
|
||||
int error;
|
||||
///Android-specific primary error associated to the server SSL certificate.
|
||||
AndroidSslError androidError;
|
||||
|
||||
///The message associated to the [error].
|
||||
///iOS-specific primary error associated to the server SSL certificate.
|
||||
IOSSslError iosError;
|
||||
|
||||
///The message associated to the [androidError]/[iosError].
|
||||
///
|
||||
///**NOTE**: on iOS this value is always an empty string.
|
||||
String message;
|
||||
|
@ -927,15 +929,17 @@ class ServerTrustChallenge {
|
|||
|
||||
ServerTrustChallenge(
|
||||
{@required this.protectionSpace,
|
||||
@required this.error,
|
||||
this.androidError,
|
||||
this.iosError,
|
||||
this.message,
|
||||
this.serverCertificate})
|
||||
: assert(protectionSpace != null && error != null);
|
||||
: assert(protectionSpace != null);
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"protectionSpace": protectionSpace?.toMap(),
|
||||
"error": error,
|
||||
"androidError": androidError?.toValue(),
|
||||
"iosError": iosError?.toValue(),
|
||||
"message": message,
|
||||
"serverCertificate": serverCertificate
|
||||
};
|
||||
|
@ -1687,6 +1691,18 @@ class InAppWebViewGroupOptions {
|
|||
return options;
|
||||
}
|
||||
|
||||
static InAppWebViewGroupOptions fromMap(Map<String, dynamic> options) {
|
||||
InAppWebViewGroupOptions inAppWebViewGroupOptions = InAppWebViewGroupOptions();
|
||||
|
||||
inAppWebViewGroupOptions.crossPlatform = InAppWebViewOptions.fromMap(options);
|
||||
if (Platform.isAndroid)
|
||||
inAppWebViewGroupOptions.android = AndroidInAppWebViewOptions.fromMap(options);
|
||||
else if (Platform.isIOS)
|
||||
inAppWebViewGroupOptions.ios = IOSInAppWebViewOptions.fromMap(options);
|
||||
|
||||
return inAppWebViewGroupOptions;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
@ -1695,6 +1711,16 @@ class InAppWebViewGroupOptions {
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
InAppWebViewGroupOptions copy() {
|
||||
return InAppWebViewGroupOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
InAppWebViewGroupOptions copyWithValue(InAppWebViewGroupOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return InAppWebViewGroupOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
||||
///Class that represents the options that can be used for an [InAppBrowser] WebView.
|
||||
|
@ -1741,6 +1767,39 @@ class InAppBrowserClassOptions {
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
static InAppBrowserClassOptions fromMap(Map<String, dynamic> options) {
|
||||
InAppBrowserClassOptions inAppBrowserClassOptions = InAppBrowserClassOptions();
|
||||
|
||||
inAppBrowserClassOptions.crossPlatform =
|
||||
InAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions =
|
||||
InAppWebViewGroupOptions();
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions.crossPlatform =
|
||||
InAppWebViewOptions.fromMap(options);
|
||||
if (Platform.isAndroid) {
|
||||
inAppBrowserClassOptions.android =
|
||||
AndroidInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions.android =
|
||||
AndroidInAppWebViewOptions.fromMap(options);
|
||||
} else if (Platform.isIOS) {
|
||||
inAppBrowserClassOptions.ios = IOSInAppBrowserOptions.fromMap(options);
|
||||
inAppBrowserClassOptions.inAppWebViewGroupOptions.ios =
|
||||
IOSInAppWebViewOptions.fromMap(options);
|
||||
}
|
||||
|
||||
return inAppBrowserClassOptions;
|
||||
}
|
||||
|
||||
InAppBrowserClassOptions copy() {
|
||||
return InAppBrowserClassOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
InAppBrowserClassOptions copyWithValue(InAppBrowserClassOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return InAppBrowserClassOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
||||
///Class that represents the options that can be used for an [ChromeSafariBrowser] window.
|
||||
|
@ -2445,16 +2504,70 @@ class ContentBlockerActionType {
|
|||
|
||||
///Class that represents a cookie returned by the [CookieManager].
|
||||
class Cookie {
|
||||
///The name;
|
||||
///The cookie name.
|
||||
String name;
|
||||
|
||||
///The value;
|
||||
///The cookie value.
|
||||
dynamic value;
|
||||
|
||||
Cookie({@required this.name, @required this.value});
|
||||
///The cookie expiration date in milliseconds.
|
||||
///
|
||||
///**NOTE**: on Android it will be always `null`.
|
||||
int expiresDate;
|
||||
|
||||
///Indicates if the cookie is a session only cookie.
|
||||
///
|
||||
///**NOTE**: on Android it will be always `null`.
|
||||
bool isSessionOnly;
|
||||
|
||||
///The cookie domain.
|
||||
///
|
||||
///**NOTE**: on Android it will be always `null`.
|
||||
String domain;
|
||||
|
||||
///The cookie same site policy.
|
||||
///
|
||||
///**NOTE**: on Android it will be always `null`.
|
||||
HTTPCookieSameSitePolicy sameSite;
|
||||
|
||||
///Indicates if the cookie is secure or not.
|
||||
///
|
||||
///**NOTE**: on Android it will be always `null`.
|
||||
bool isSecure;
|
||||
|
||||
///Indicates if the cookie is a http only cookie.
|
||||
///
|
||||
///**NOTE**: on Android it will be always `null`.
|
||||
bool isHttpOnly;
|
||||
|
||||
///The cookie path.
|
||||
///
|
||||
///**NOTE**: on Android it will be always `null`.
|
||||
String path;
|
||||
|
||||
Cookie(
|
||||
{@required this.name,
|
||||
@required this.value,
|
||||
this.expiresDate,
|
||||
this.isSessionOnly,
|
||||
this.domain,
|
||||
this.sameSite,
|
||||
this.isSecure,
|
||||
this.isHttpOnly,
|
||||
this.path});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {"name": name, "value": value};
|
||||
return {
|
||||
"name": name,
|
||||
"value": value,
|
||||
"expiresDate": expiresDate,
|
||||
"isSessionOnly": isSessionOnly,
|
||||
"domain": domain,
|
||||
"sameSite": sameSite?.toValue(),
|
||||
"isSecure": isSecure,
|
||||
"isHttpOnly": isHttpOnly,
|
||||
"path": path
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
@ -3263,7 +3376,7 @@ class AndroidWebViewPackageInfo {
|
|||
return map != null
|
||||
? AndroidWebViewPackageInfo(
|
||||
versionName: map["versionName"], packageName: map["packageName"])
|
||||
: AndroidWebViewPackageInfo();
|
||||
: null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -3291,17 +3404,10 @@ class RequestFocusNodeHrefResult {
|
|||
///The image's src attribute.
|
||||
String src;
|
||||
|
||||
RequestFocusNodeHrefResult(
|
||||
{this.url,
|
||||
this.title,
|
||||
this.src});
|
||||
RequestFocusNodeHrefResult({this.url, this.title, this.src});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"url": url,
|
||||
"title": title,
|
||||
"src": src
|
||||
};
|
||||
return {"url": url, "title": title, "src": src};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
@ -3341,19 +3447,17 @@ class RequestImageRefResult {
|
|||
class MetaTag {
|
||||
///The meta tag name value.
|
||||
String name;
|
||||
|
||||
///The meta tag content value.
|
||||
String content;
|
||||
|
||||
///The meta tag attributes list.
|
||||
List<MetaTagAttribute> attrs;
|
||||
|
||||
MetaTag({this.name, this.content, this.attrs});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"name": name,
|
||||
"content": content,
|
||||
"attrs": attrs
|
||||
};
|
||||
return {"name": name, "content": content, "attrs": attrs};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
@ -3370,6 +3474,7 @@ class MetaTag {
|
|||
class MetaTagAttribute {
|
||||
///The attribute name.
|
||||
String name;
|
||||
|
||||
///The attribute value.
|
||||
String value;
|
||||
|
||||
|
@ -3392,6 +3497,8 @@ class MetaTagAttribute {
|
|||
}
|
||||
}
|
||||
|
||||
///Class that represents the type of Web Storage: `localStorage` or `sessionStorage`.
|
||||
///Used by the [Storage] class.
|
||||
class WebStorageType {
|
||||
final String _value;
|
||||
|
||||
|
@ -3411,9 +3518,11 @@ class WebStorageType {
|
|||
@override
|
||||
String toString() => _value;
|
||||
|
||||
static const LOCAL_STORAGE =
|
||||
const WebStorageType._internal("localStorage");
|
||||
///`window.localStorage`: same as [SESSION_STORAGE], but persists even when the browser is closed and reopened.
|
||||
static const LOCAL_STORAGE = const WebStorageType._internal("localStorage");
|
||||
|
||||
///`window.sessionStorage`: maintains a separate storage area for each given origin that's available for the duration
|
||||
///of the page session (as long as the browser is open, including page reloads and restores).
|
||||
static const SESSION_STORAGE =
|
||||
const WebStorageType._internal("sessionStorage");
|
||||
|
||||
|
@ -3422,3 +3531,524 @@ class WebStorageType {
|
|||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Class that represents the same site policy of a cookie. Used by the [Cookie] class.
|
||||
class HTTPCookieSameSitePolicy {
|
||||
final String _value;
|
||||
|
||||
const HTTPCookieSameSitePolicy._internal(this._value);
|
||||
|
||||
static HTTPCookieSameSitePolicy fromValue(String value) {
|
||||
return ([
|
||||
"Lax",
|
||||
"Strict",
|
||||
"None",
|
||||
].contains(value))
|
||||
? HTTPCookieSameSitePolicy._internal(value)
|
||||
: null;
|
||||
}
|
||||
|
||||
String toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() => _value;
|
||||
|
||||
///SameSite=Lax;
|
||||
///
|
||||
///Cookies are allowed to be sent with top-level navigations and will be sent along with GET
|
||||
///request initiated by third party website. This is the default value in modern browsers.
|
||||
static const LAX = const HTTPCookieSameSitePolicy._internal("Lax");
|
||||
|
||||
///SameSite=Strict;
|
||||
///
|
||||
///Cookies will only be sent in a first-party context and not be sent along with requests initiated by third party websites.
|
||||
static const STRICT = const HTTPCookieSameSitePolicy._internal("Strict");
|
||||
|
||||
///SameSite=None;
|
||||
///
|
||||
///Cookies will be sent in all contexts, i.e sending cross-origin is allowed.
|
||||
///`None` requires the `Secure` attribute in latest browser versions.
|
||||
static const NONE = const HTTPCookieSameSitePolicy._internal("None");
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Class that represents the Android-specific primary error associated to the server SSL certificate.
|
||||
///Used by the [ServerTrustChallenge] class.
|
||||
class AndroidSslError {
|
||||
final int _value;
|
||||
|
||||
const AndroidSslError._internal(this._value);
|
||||
|
||||
static AndroidSslError fromValue(int value) {
|
||||
if (value != null && value >= 0 && value <= 5)
|
||||
return AndroidSslError._internal(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return "SSL_EXPIRED";
|
||||
case 2:
|
||||
return "SSL_IDMISMATCH";
|
||||
case 3:
|
||||
return "SSL_UNTRUSTED";
|
||||
case 4:
|
||||
return "SSL_DATE_INVALID";
|
||||
case 5:
|
||||
return "SSL_INVALID";
|
||||
case 0:
|
||||
default:
|
||||
return "SSL_NOTYETVALID";
|
||||
}
|
||||
}
|
||||
|
||||
///The certificate is not yet valid
|
||||
static const SSL_NOTYETVALID = const AndroidSslError._internal(0);
|
||||
|
||||
///The certificate has expired
|
||||
static const SSL_EXPIRED = const AndroidSslError._internal(1);
|
||||
|
||||
///Hostname mismatch
|
||||
static const SSL_IDMISMATCH = const AndroidSslError._internal(2);
|
||||
|
||||
///The certificate authority is not trusted
|
||||
static const SSL_UNTRUSTED = const AndroidSslError._internal(3);
|
||||
|
||||
///The date of the certificate is invalid
|
||||
static const SSL_DATE_INVALID = const AndroidSslError._internal(4);
|
||||
|
||||
///A generic error occurred
|
||||
static const SSL_INVALID = const AndroidSslError._internal(5);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Class that represents the iOS-specific primary error associated to the server SSL certificate.
|
||||
///Used by the [ServerTrustChallenge] class.
|
||||
class IOSSslError {
|
||||
final int _value;
|
||||
|
||||
const IOSSslError._internal(this._value);
|
||||
|
||||
static IOSSslError fromValue(int value) {
|
||||
if (value != null && [0, 3, 4, 5, 6, 7].contains(value))
|
||||
return IOSSslError._internal(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 3:
|
||||
return "DENY";
|
||||
case 4:
|
||||
return "UNSPECIFIED";
|
||||
case 5:
|
||||
return "RECOVERABLE_TRUST_FAILURE";
|
||||
case 6:
|
||||
return "FATAL_TRUST_FAILURE";
|
||||
case 7:
|
||||
return "OTHER_ERROR";
|
||||
case 0:
|
||||
default:
|
||||
return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
///Indicates an invalid setting or result.
|
||||
static const INVALID = const IOSSslError._internal(0);
|
||||
|
||||
///Indicates a user-configured deny; do not proceed.
|
||||
static const DENY = const IOSSslError._internal(3);
|
||||
|
||||
///Indicates the evaluation succeeded and the certificate is implicitly trusted, but user intent was not explicitly specified.
|
||||
static const UNSPECIFIED = const IOSSslError._internal(4);
|
||||
|
||||
///Indicates a trust policy failure which can be overridden by the user.
|
||||
static const RECOVERABLE_TRUST_FAILURE = const IOSSslError._internal(5);
|
||||
|
||||
///Indicates a trust failure which cannot be overridden by the user.
|
||||
static const FATAL_TRUST_FAILURE = const IOSSslError._internal(6);
|
||||
|
||||
///Indicates a failure other than that of trust evaluation.
|
||||
static const OTHER_ERROR = const IOSSslError._internal(7);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Class that represents an iOS-specific class used to configure how safe area insets are added to the adjusted content inset.
|
||||
///
|
||||
///**NOTE**: available on iOS 11.0+.
|
||||
class IOSUIScrollViewContentInsetAdjustmentBehavior {
|
||||
final int _value;
|
||||
|
||||
const IOSUIScrollViewContentInsetAdjustmentBehavior._internal(this._value);
|
||||
|
||||
static IOSUIScrollViewContentInsetAdjustmentBehavior fromValue(int value) {
|
||||
if (value != null && value >= 0 && value <= 3)
|
||||
return IOSUIScrollViewContentInsetAdjustmentBehavior._internal(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
int toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (_value) {
|
||||
case 1:
|
||||
return "SCROLLABLE_AXES";
|
||||
case 2:
|
||||
return "NEVER";
|
||||
case 3:
|
||||
return "ALWAYS";
|
||||
case 0:
|
||||
default:
|
||||
return "AUTOMATIC";
|
||||
}
|
||||
}
|
||||
|
||||
///Automatically adjust the scroll view insets.
|
||||
static const AUTOMATIC = const IOSUIScrollViewContentInsetAdjustmentBehavior._internal(0);
|
||||
|
||||
///Adjust the insets only in the scrollable directions.
|
||||
static const SCROLLABLE_AXES = const IOSUIScrollViewContentInsetAdjustmentBehavior._internal(1);
|
||||
|
||||
///Do not adjust the scroll view insets.
|
||||
static const NEVER = const IOSUIScrollViewContentInsetAdjustmentBehavior._internal(2);
|
||||
|
||||
///Always include the safe area insets in the content adjustment.
|
||||
static const ALWAYS = const IOSUIScrollViewContentInsetAdjustmentBehavior._internal(3);
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
class AndroidSslCertificate {
|
||||
AndroidSslCertificateDName issuedBy;
|
||||
AndroidSslCertificateDName issuedTo;
|
||||
int validNotAfterDate;
|
||||
int validNotBeforeDate;
|
||||
AndroidX509Certificate x509Certificate;
|
||||
|
||||
AndroidSslCertificate({
|
||||
this.issuedBy,
|
||||
this.issuedTo,
|
||||
this.validNotAfterDate,
|
||||
this.validNotBeforeDate,
|
||||
this.x509Certificate
|
||||
});
|
||||
|
||||
static AndroidSslCertificate fromMap(Map<String, dynamic> map) {
|
||||
return map != null ? AndroidSslCertificate(
|
||||
issuedBy: AndroidSslCertificateDName.fromMap(map["issuedBy"]?.cast<String, dynamic>()),
|
||||
issuedTo: AndroidSslCertificateDName.fromMap(map["issuedTo"]?.cast<String, dynamic>()),
|
||||
validNotAfterDate: map["validNotAfterDate"],
|
||||
validNotBeforeDate: map["validNotBeforeDate"],
|
||||
x509Certificate: AndroidX509Certificate.fromMap(map["x509Certificate"]?.cast<String, dynamic>()),
|
||||
) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"issuedBy": issuedBy?.toMap(),
|
||||
"issuedTo": issuedTo?.toMap(),
|
||||
"validNotAfterDate": validNotAfterDate,
|
||||
"validNotBeforeDate": validNotBeforeDate,
|
||||
"x509Certificate": x509Certificate?.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidSslCertificateDName {
|
||||
// ignore: non_constant_identifier_names
|
||||
String CName;
|
||||
// ignore: non_constant_identifier_names
|
||||
String DName;
|
||||
// ignore: non_constant_identifier_names
|
||||
String OName;
|
||||
// ignore: non_constant_identifier_names
|
||||
String UName;
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
AndroidSslCertificateDName({this.CName, this.DName, this.OName, this.UName});
|
||||
|
||||
static AndroidSslCertificateDName fromMap(Map<String, dynamic> map) {
|
||||
return map != null ? AndroidSslCertificateDName(
|
||||
CName: map["CName"],
|
||||
DName: map["DName"],
|
||||
OName: map["OName"],
|
||||
UName: map["UName"],
|
||||
) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"CName": CName,
|
||||
"DName": DName,
|
||||
"OName": OName,
|
||||
"UName": UName,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidX509Certificate {
|
||||
int basicConstraints;
|
||||
List<String> extendedKeyUsage;
|
||||
AndroidX509CertificatePrincipal issuerDN;
|
||||
List<bool> issuerUniqueID;
|
||||
AndroidX500Principal issuerX500Principal;
|
||||
List<bool> keyUsage;
|
||||
int notAfter;
|
||||
int notBefore;
|
||||
int serialNumber;
|
||||
String sigAlgName;
|
||||
String sigAlgOID;
|
||||
Uint8List sigAlgParams;
|
||||
Uint8List signature;
|
||||
AndroidX509CertificatePrincipal subjectDN;
|
||||
List<bool> subjectUniqueID;
|
||||
AndroidX500Principal subjectX500Principal;
|
||||
// ignore: non_constant_identifier_names
|
||||
Uint8List TBSCertificate;
|
||||
int version;
|
||||
Set<String> criticalExtensionOIDs;
|
||||
Set<String> nonCriticalExtensionOIDs;
|
||||
Uint8List encoded;
|
||||
AndroidX509CertificatePublicKey publicKey;
|
||||
String type;
|
||||
bool hasUnsupportedCriticalExtension;
|
||||
bool valid;
|
||||
|
||||
AndroidX509Certificate({
|
||||
this.basicConstraints,
|
||||
this.extendedKeyUsage,
|
||||
this.issuerDN,
|
||||
this.issuerUniqueID,
|
||||
this.issuerX500Principal,
|
||||
this.keyUsage,
|
||||
this.notAfter,
|
||||
this.notBefore,
|
||||
this.serialNumber,
|
||||
this.sigAlgName,
|
||||
this.sigAlgOID,
|
||||
this.sigAlgParams,
|
||||
this.signature,
|
||||
this.subjectDN,
|
||||
this.subjectUniqueID,
|
||||
this.subjectX500Principal,
|
||||
// ignore: non_constant_identifier_names
|
||||
this.TBSCertificate,
|
||||
this.version,
|
||||
this.criticalExtensionOIDs,
|
||||
this.nonCriticalExtensionOIDs,
|
||||
this.encoded,
|
||||
this.publicKey,
|
||||
this.type,
|
||||
this.hasUnsupportedCriticalExtension,
|
||||
this.valid
|
||||
});
|
||||
|
||||
static AndroidX509Certificate fromMap(Map<String, dynamic> map) {
|
||||
return map != null ? AndroidX509Certificate(
|
||||
basicConstraints: map["basicConstraints"],
|
||||
extendedKeyUsage: map["extendedKeyUsage"],
|
||||
issuerDN: AndroidX509CertificatePrincipal.fromMap(map["issuerDN"]),
|
||||
issuerUniqueID: map["issuerUniqueID"],
|
||||
issuerX500Principal: AndroidX500Principal.fromMap(map["issuerX500Principal"]),
|
||||
keyUsage: map["keyUsage"],
|
||||
notAfter: map["notAfter"],
|
||||
notBefore: map["notBefore"],
|
||||
serialNumber: map["serialNumber"],
|
||||
sigAlgName: map["sigAlgName"],
|
||||
sigAlgOID: map["sigAlgOID"],
|
||||
sigAlgParams: map["sigAlgParams"],
|
||||
signature: map["signature"],
|
||||
subjectDN: AndroidX509CertificatePrincipal.fromMap(map["subjectDN"]),
|
||||
subjectUniqueID: map["subjectUniqueID"],
|
||||
subjectX500Principal: AndroidX500Principal.fromMap(map["subjectX500Principal"]),
|
||||
TBSCertificate: map["TBSCertificate"],
|
||||
version: map["version"],
|
||||
criticalExtensionOIDs: map["criticalExtensionOIDs"],
|
||||
nonCriticalExtensionOIDs: map["nonCriticalExtensionOIDs"],
|
||||
encoded: map["encoded"],
|
||||
publicKey: AndroidX509CertificatePublicKey.fromMap(map["publicKey"]),
|
||||
type: map["type"],
|
||||
hasUnsupportedCriticalExtension: map["hasUnsupportedCriticalExtension"],
|
||||
valid: map["valid"]
|
||||
) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"basicConstraints": basicConstraints,
|
||||
"extendedKeyUsage": extendedKeyUsage,
|
||||
"issuerDN": issuerDN?.toMap(),
|
||||
"issuerUniqueID": issuerUniqueID,
|
||||
"issuerX500Principal": issuerX500Principal?.toMap(),
|
||||
"keyUsage": keyUsage,
|
||||
"notAfter": notAfter,
|
||||
"notBefore": notBefore,
|
||||
"serialNumber": serialNumber,
|
||||
"sigAlgName": sigAlgName,
|
||||
"sigAlgOID": sigAlgOID,
|
||||
"sigAlgParams": sigAlgParams,
|
||||
"signature": signature,
|
||||
"subjectDN": subjectDN?.toMap(),
|
||||
"subjectUniqueID": subjectUniqueID,
|
||||
"subjectX500Principal": subjectX500Principal?.toMap(),
|
||||
"TBSCertificate": TBSCertificate,
|
||||
"version": version,
|
||||
"criticalExtensionOIDs": criticalExtensionOIDs,
|
||||
"nonCriticalExtensionOIDs": nonCriticalExtensionOIDs,
|
||||
"encoded": encoded,
|
||||
"publicKey": publicKey?.toMap(),
|
||||
"type": type,
|
||||
"hasUnsupportedCriticalExtension": hasUnsupportedCriticalExtension,
|
||||
"valid": valid,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidX509CertificatePrincipal {
|
||||
String name;
|
||||
|
||||
AndroidX509CertificatePrincipal({
|
||||
this.name
|
||||
});
|
||||
|
||||
static AndroidX509CertificatePrincipal fromMap(Map<String, dynamic> map) {
|
||||
return map != null ? AndroidX509CertificatePrincipal(
|
||||
name: map["name"],
|
||||
) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"name": name,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidX500Principal {
|
||||
String name;
|
||||
Uint8List encoded;
|
||||
|
||||
AndroidX500Principal({
|
||||
this.name,
|
||||
this.encoded
|
||||
});
|
||||
|
||||
static AndroidX500Principal fromMap(Map<String, dynamic> map) {
|
||||
return map != null ? AndroidX500Principal(
|
||||
name: map["name"],
|
||||
encoded: map["encoded"],
|
||||
) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"name": name,
|
||||
"encoded": encoded,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidX509CertificatePublicKey {
|
||||
String algorithm;
|
||||
Uint8List encoded;
|
||||
String format;
|
||||
|
||||
AndroidX509CertificatePublicKey({
|
||||
this.algorithm,
|
||||
this.encoded,
|
||||
this.format
|
||||
});
|
||||
|
||||
static AndroidX509CertificatePublicKey fromMap(Map<String, dynamic> map) {
|
||||
return map != null ? AndroidX509CertificatePublicKey(
|
||||
algorithm: map["algorithm"],
|
||||
encoded: map["encoded"],
|
||||
format: map["format"],
|
||||
) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"algorithm": algorithm,
|
||||
"encoded": encoded,
|
||||
"format": format,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
}
|
|
@ -17,6 +17,10 @@ class WebViewOptions {
|
|||
return null;
|
||||
}
|
||||
|
||||
WebViewOptions copy() {
|
||||
return WebViewOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
@ -36,6 +40,10 @@ class BrowserOptions {
|
|||
return null;
|
||||
}
|
||||
|
||||
BrowserOptions copy() {
|
||||
return BrowserOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
@ -55,6 +63,10 @@ class ChromeSafariBrowserOptions {
|
|||
return null;
|
||||
}
|
||||
|
||||
ChromeSafariBrowserOptions copy() {
|
||||
return ChromeSafariBrowserOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return this.toMap();
|
||||
}
|
||||
|
@ -284,6 +296,17 @@ class InAppWebViewOptions
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
@override
|
||||
InAppWebViewOptions copy() {
|
||||
return InAppWebViewOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
InAppWebViewOptions copyWithValue(InAppWebViewOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return InAppWebViewOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
||||
///This class represents all the Android-only WebView options available.
|
||||
|
@ -681,6 +704,17 @@ class AndroidInAppWebViewOptions
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
@override
|
||||
AndroidInAppWebViewOptions copy() {
|
||||
return AndroidInAppWebViewOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
AndroidInAppWebViewOptions copyWithValue(AndroidInAppWebViewOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return AndroidInAppWebViewOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
||||
///This class represents all the iOS-only WebView options available.
|
||||
|
@ -789,6 +823,10 @@ class IOSInAppWebViewOptions
|
|||
///The default value is `1.0`.
|
||||
double minimumZoomScale;
|
||||
|
||||
///Configures how safe area insets are added to the adjusted content inset.
|
||||
///The default value is [IOSUIScrollViewContentInsetAdjustmentBehavior.NEVER].
|
||||
IOSUIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior;
|
||||
|
||||
IOSInAppWebViewOptions(
|
||||
{this.disallowOverScroll = false,
|
||||
this.enableViewportScale = false,
|
||||
|
@ -811,7 +849,8 @@ class IOSInAppWebViewOptions
|
|||
this.scrollsToTop = true,
|
||||
this.isPagingEnabled = false,
|
||||
this.maximumZoomScale = 1.0,
|
||||
this.minimumZoomScale = 1.0});
|
||||
this.minimumZoomScale = 1.0,
|
||||
this.contentInsetAdjustmentBehavior = IOSUIScrollViewContentInsetAdjustmentBehavior.NEVER});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -845,7 +884,8 @@ class IOSInAppWebViewOptions
|
|||
"scrollsToTop": scrollsToTop,
|
||||
"isPagingEnabled": isPagingEnabled,
|
||||
"maximumZoomScale": maximumZoomScale,
|
||||
"minimumZoomScale": minimumZoomScale
|
||||
"minimumZoomScale": minimumZoomScale,
|
||||
"contentInsetAdjustmentBehavior": contentInsetAdjustmentBehavior.toValue()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -889,6 +929,9 @@ class IOSInAppWebViewOptions
|
|||
options.isPagingEnabled = map["isPagingEnabled"];
|
||||
options.maximumZoomScale = map["maximumZoomScale"];
|
||||
options.minimumZoomScale = map["minimumZoomScale"];
|
||||
options.contentInsetAdjustmentBehavior =
|
||||
IOSUIScrollViewContentInsetAdjustmentBehavior.fromValue(
|
||||
map["contentInsetAdjustmentBehavior"]);
|
||||
return options;
|
||||
}
|
||||
|
||||
|
@ -901,6 +944,17 @@ class IOSInAppWebViewOptions
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
@override
|
||||
IOSInAppWebViewOptions copy() {
|
||||
return IOSInAppWebViewOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
IOSInAppWebViewOptions copyWithValue(IOSInAppWebViewOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return IOSInAppWebViewOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
||||
///This class represents all the cross-platform [InAppBrowser] options available.
|
||||
|
@ -953,6 +1007,17 @@ class InAppBrowserOptions
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
@override
|
||||
InAppBrowserOptions copy() {
|
||||
return InAppBrowserOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
InAppBrowserOptions copyWithValue(InAppBrowserOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return InAppBrowserOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
||||
///This class represents all the Android-only [InAppBrowser] options available.
|
||||
|
@ -1003,6 +1068,17 @@ class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
@override
|
||||
AndroidInAppBrowserOptions copy() {
|
||||
return AndroidInAppBrowserOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
AndroidInAppBrowserOptions copyWithValue(AndroidInAppBrowserOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return AndroidInAppBrowserOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
||||
///This class represents all the iOS-only [InAppBrowser] options available.
|
||||
|
@ -1079,6 +1155,17 @@ class IOSInAppBrowserOptions implements BrowserOptions, IosOptions {
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
@override
|
||||
IOSInAppBrowserOptions copy() {
|
||||
return IOSInAppBrowserOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
IOSInAppBrowserOptions copyWithValue(IOSInAppBrowserOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return IOSInAppBrowserOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
||||
///This class represents all the Android-only [ChromeSafariBrowser] options available.
|
||||
|
@ -1153,6 +1240,17 @@ class AndroidChromeCustomTabsOptions
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
@override
|
||||
AndroidChromeCustomTabsOptions copy() {
|
||||
return AndroidChromeCustomTabsOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
AndroidChromeCustomTabsOptions copyWithValue(AndroidChromeCustomTabsOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return AndroidChromeCustomTabsOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
||||
///This class represents all the iOS-only [ChromeSafariBrowser] options available.
|
||||
|
@ -1230,4 +1328,15 @@ class IOSSafariOptions implements ChromeSafariBrowserOptions, IosOptions {
|
|||
String toString() {
|
||||
return toMap().toString();
|
||||
}
|
||||
|
||||
@override
|
||||
IOSSafariOptions copy() {
|
||||
return IOSSafariOptions.fromMap(this.toMap());
|
||||
}
|
||||
|
||||
IOSSafariOptions copyWithValue(IOSSafariOptions webViewOptions) {
|
||||
var mergedMap = this.toMap();
|
||||
mergedMap.addAll(webViewOptions.toMap());
|
||||
return IOSSafariOptions.fromMap(mergedMap);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue