From 31dc73cfcea9289ba2723147369a3336a5625204 Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Fri, 8 Nov 2019 00:32:29 +0100 Subject: [PATCH] added new webview options --- .idea/workspace.xml | 202 +++++++++--------- CHANGELOG.md | 6 +- .../InAppWebView/InAppWebView.java | 103 ++++++++- .../InAppWebView/InAppWebViewOptions.java | 69 +++--- example/lib/inline_example.screen.dart | 3 +- ios/Classes/FlutterWebViewController.swift | 4 + ios/Classes/InAppWebView.swift | 84 +++++++- ios/Classes/InAppWebViewOptions.swift | 14 +- lib/src/in_app_webview.dart | 7 + lib/src/webview_options.dart | 59 +++-- 10 files changed, 367 insertions(+), 184 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index b71b49ee..a5a9789e 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -16,13 +16,15 @@ + - - + + + - + @@ -45,8 +47,8 @@ - - + + @@ -57,7 +59,7 @@ - + @@ -69,8 +71,8 @@ - - + + @@ -78,11 +80,11 @@ - + - - + + @@ -93,7 +95,7 @@ - + @@ -102,17 +104,17 @@ - + - + - - + + @@ -123,8 +125,8 @@ - - + + @@ -141,16 +143,6 @@ - .toValue - fromValue( - ?.toMap()); - fromMap - setOptions - fromValue - List< - debuggingEnabled - initialOp - injectScriptFile injectScriptUrlFile [InAppWebView] window javaScriptEnabled @@ -171,6 +163,16 @@ NAVIGATION onNavigationStateChange shouldInterceptFetchRequest + scheme + applicationNameForUserAgent + cacheMOde + inco + cacheEna + appCacheEnabled + appC + cache + customScheme + transparentBackground activity.getPreferences(0) @@ -240,17 +242,17 @@ - + @@ -489,7 +491,7 @@ - + @@ -503,7 +505,7 @@ - + @@ -511,7 +513,7 @@ - + @@ -742,19 +744,30 @@ - + - - - - - + + + + + + + + + + + + + + + + - + @@ -762,17 +775,10 @@ - + - - - - - - - - - + + @@ -781,38 +787,34 @@ - - + + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 9169ec81..a2231f6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,9 @@ - Added `onLoadResourceCustomScheme` event and `resourceCustomSchemes` option to set custom schemes that WebView must handle to load resources - Added `onTargetBlank` event and `useOnTargetBlank` option to manage links with `target="_blank"` - Added `ContentBlocker`, `ContentBlockerTrigger` and `ContentBlockerAction` classes and the `contentBlockers` option that allows to define a set of rules to use to block content in the WebView -- Added new WebView options: `minimumFontSize`, `debuggingEnabled`, `preferredContentMode` -- Added new Android WebView options: `allowContentAccess`, `allowFileAccess`, `allowFileAccessFromFileURLs`, `allowUniversalAccessFromFileURLs`, `appCacheEnabled`, `appCachePath`, `blockNetworkImage`, `blockNetworkLoads`, `cacheMode`, `cursiveFontFamily`, `defaultFixedFontSize`, `defaultFontSize`, `defaultTextEncodingName`, `disabledActionModeMenuItems`, `fantasyFontFamily`, `fixedFontFamily`, `forceDark`, `geolocationEnabled`, `layoutAlgorithm`, `loadWithOverviewMode`, `loadsImagesAutomatically`, `minimumLogicalFontSize`, `needInitialFocus`, `offscreenPreRaster`, `sansSerifFontFamily`, `serifFontFamily`, `standardFontFamily` -- Added new iOS WebView options: `applicationNameForUserAgent`, `isFraudulentWebsiteWarningEnabled`, `selectionGranularity`, `dataDetectorTypes` +- Added new WebView options: `minimumFontSize`, `debuggingEnabled`, `preferredContentMode`, `applicationNameForUserAgent`, `incognito`, `cacheEnabled` +- Added new Android WebView options: `allowContentAccess`, `allowFileAccess`, `allowFileAccessFromFileURLs`, `allowUniversalAccessFromFileURLs`, `appCachePath`, `blockNetworkImage`, `blockNetworkLoads`, `cacheMode`, `cursiveFontFamily`, `defaultFixedFontSize`, `defaultFontSize`, `defaultTextEncodingName`, `disabledActionModeMenuItems`, `fantasyFontFamily`, `fixedFontFamily`, `forceDark`, `geolocationEnabled`, `layoutAlgorithm`, `loadWithOverviewMode`, `loadsImagesAutomatically`, `minimumLogicalFontSize`, `needInitialFocus`, `offscreenPreRaster`, `sansSerifFontFamily`, `serifFontFamily`, `standardFontFamily`, `saveFormData`, `thirdPartyCookiesEnabled`, `hardwareAcceleration` +- Added new iOS WebView options: `isFraudulentWebsiteWarningEnabled`, `selectionGranularity`, `dataDetectorTypes`, `sharedCookiesEnabled` - Added `onGeolocationPermissionsShowPrompt` event and `GeolocationPermissionShowPromptResponse` class (available only for Android) - Added `startSafeBrowsing`, `setSafeBrowsingWhitelist` and `getSafeBrowsingPrivacyPolicyUrl` methods (available only for Android) - Added `clearSslPreferences` and `clearClientCertPreferences` methods (available only for Android) diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java index e5349026..ff3dfbe8 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java @@ -499,19 +499,28 @@ final public class InAppWebView extends InputAwareWebView { settings.setDatabaseEnabled(options.databaseEnabled); settings.setDomStorageEnabled(options.domStorageEnabled); - if (!options.userAgent.isEmpty()) + if (options.userAgent != null && !options.userAgent.isEmpty()) settings.setUserAgentString(options.userAgent); + else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) + settings.setUserAgentString(WebSettings.getDefaultUserAgent(getContext())); + + if (options.applicationNameForUserAgent != null && !options.applicationNameForUserAgent.isEmpty()) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + String userAgent = (options.userAgent != null && !options.userAgent.isEmpty()) ? options.userAgent :WebSettings.getDefaultUserAgent(getContext()); + String userAgentWithApplicationName = userAgent + " " + options.applicationNameForUserAgent; + settings.setUserAgentString(userAgentWithApplicationName); + } + } if (options.clearCache) clearAllCache(); else if (options.clearSessionCache) CookieManager.getInstance().removeSessionCookie(); - // Enable Thirdparty Cookies on >=Android 5.0 device if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - CookieManager.getInstance().setAcceptThirdPartyCookies(this, true); + CookieManager.getInstance().setAcceptThirdPartyCookies(this, options.thirdPartyCookiesEnabled); - settings.setLoadWithOverviewMode(true); + settings.setLoadWithOverviewMode(options.loadWithOverviewMode); settings.setUseWideViewPort(options.useWideViewPort); settings.setSupportZoom(options.supportZoom); settings.setTextZoom(options.textZoom); @@ -528,8 +537,8 @@ final public class InAppWebView extends InputAwareWebView { settings.setAllowFileAccess(options.allowFileAccess); settings.setAllowFileAccessFromFileURLs(options.allowFileAccessFromFileURLs); settings.setAllowUniversalAccessFromFileURLs(options.allowUniversalAccessFromFileURLs); - settings.setAppCacheEnabled(options.appCacheEnabled); - if (options.appCachePath != null && !options.appCachePath.isEmpty() && options.appCacheEnabled) + setCacheEnabled(options.cacheEnabled); + if (options.appCachePath != null && !options.appCachePath.isEmpty() && options.cacheEnabled) settings.setAppCachePath(options.appCachePath); settings.setBlockNetworkImage(options.blockNetworkImage); settings.setBlockNetworkLoads(options.blockNetworkLoads); @@ -548,7 +557,6 @@ final public class InAppWebView extends InputAwareWebView { settings.setGeolocationEnabled(options.geolocationEnabled); if (options.layoutAlgorithm != null) settings.setLayoutAlgorithm(options.layoutAlgorithm); - settings.setLoadWithOverviewMode(options.loadWithOverviewMode); settings.setLoadsImagesAutomatically(options.loadsImagesAutomatically); settings.setMinimumFontSize(options.minimumFontSize); settings.setMinimumLogicalFontSize(options.minimumLogicalFontSize); @@ -570,6 +578,13 @@ final public class InAppWebView extends InputAwareWebView { break; } } + settings.setSaveFormData(options.saveFormData); + if (options.incognito) + setIncognito(true); + if (options.hardwareAcceleration) + setLayerType(View.LAYER_TYPE_HARDWARE, null); + else + setLayerType(View.LAYER_TYPE_SOFTWARE, null); contentBlockerHandler.getRuleList().clear(); for (Map> contentBlocker : options.contentBlockers) { @@ -593,6 +608,49 @@ final public class InAppWebView extends InputAwareWebView { }); } + public void setIncognito(boolean enabled) { + WebSettings settings = getSettings(); + if (enabled) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + CookieManager.getInstance().removeAllCookies(null); + } else { + CookieManager.getInstance().removeAllCookie(); + } + + // Disable caching + settings.setCacheMode(WebSettings.LOAD_NO_CACHE); + settings.setAppCacheEnabled(false); + clearHistory(); + clearCache(true); + + // No form data or autofill enabled + clearFormData(); + settings.setSavePassword(false); + settings.setSaveFormData(false); + } + else { + settings.setCacheMode(WebSettings.LOAD_DEFAULT); + settings.setAppCacheEnabled(true); + settings.setSavePassword(true); + settings.setSaveFormData(true); + } + } + + public void setCacheEnabled(boolean enabled) { + WebSettings settings = getSettings(); + if (enabled) { + Context ctx = getContext(); + if (ctx != null) { + settings.setAppCachePath(ctx.getCacheDir().getAbsolutePath()); + settings.setCacheMode(WebSettings.LOAD_DEFAULT); + settings.setAppCacheEnabled(true); + } + } else { + settings.setCacheMode(WebSettings.LOAD_NO_CACHE); + settings.setAppCacheEnabled(false); + } + } + public void loadUrl(String url, MethodChannel.Result result) { if (!url.isEmpty()) { loadUrl(url); @@ -780,11 +838,22 @@ final public class InAppWebView extends InputAwareWebView { if (newOptionsMap.get("userAgent") != null && !options.userAgent.equals(newOptions.userAgent) && !newOptions.userAgent.isEmpty()) settings.setUserAgentString(newOptions.userAgent); + if (newOptionsMap.get("applicationNameForUserAgent") != null && !options.applicationNameForUserAgent.equals(newOptions.applicationNameForUserAgent) && !newOptions.applicationNameForUserAgent.isEmpty()) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + String userAgent = (newOptions.userAgent != null && !newOptions.userAgent.isEmpty()) ? newOptions.userAgent : WebSettings.getDefaultUserAgent(getContext()); + String userAgentWithApplicationName = userAgent + " " + options.applicationNameForUserAgent; + settings.setUserAgentString(userAgentWithApplicationName); + } + } + if (newOptionsMap.get("clearCache") != null && newOptions.clearCache) clearAllCache(); else if (newOptionsMap.get("clearSessionCache") != null && newOptions.clearSessionCache) CookieManager.getInstance().removeSessionCookie(); + if (newOptionsMap.get("thirdPartyCookiesEnabled") != null && options.thirdPartyCookiesEnabled != newOptions.thirdPartyCookiesEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + CookieManager.getInstance().setAcceptThirdPartyCookies(this, newOptions.thirdPartyCookiesEnabled); + if (newOptionsMap.get("useWideViewPort") != null && options.useWideViewPort != newOptions.useWideViewPort) settings.setUseWideViewPort(newOptions.useWideViewPort); @@ -835,12 +904,11 @@ final public class InAppWebView extends InputAwareWebView { if (newOptionsMap.get("allowUniversalAccessFromFileURLs") != null && options.allowUniversalAccessFromFileURLs != newOptions.allowUniversalAccessFromFileURLs) settings.setAllowUniversalAccessFromFileURLs(newOptions.allowUniversalAccessFromFileURLs); - if (newOptionsMap.get("appCacheEnabled") != null && options.appCacheEnabled != newOptions.appCacheEnabled) - settings.setAppCacheEnabled(newOptions.appCacheEnabled); + if (newOptionsMap.get("cacheEnabled") != null && options.cacheEnabled != newOptions.cacheEnabled) + setCacheEnabled(newOptions.cacheEnabled); if (newOptionsMap.get("appCachePath") != null && !options.appCachePath.equals(newOptions.appCachePath)) - if (newOptions.appCacheEnabled) - settings.setAppCachePath(newOptions.appCachePath); + settings.setAppCachePath(newOptions.appCachePath); if (newOptionsMap.get("blockNetworkImage") != null && options.blockNetworkImage != newOptions.blockNetworkImage) settings.setBlockNetworkImage(newOptions.blockNetworkImage); @@ -911,6 +979,19 @@ final public class InAppWebView extends InputAwareWebView { if (newOptionsMap.get("standardFontFamily") != null && !options.standardFontFamily.equals(newOptions.standardFontFamily)) settings.setStandardFontFamily(newOptions.standardFontFamily); + if (newOptionsMap.get("saveFormData") != null && options.saveFormData != newOptions.saveFormData) + settings.setSaveFormData(newOptions.saveFormData); + + if (newOptionsMap.get("incognito") != null && options.incognito != newOptions.incognito) + setIncognito(newOptions.incognito); + + if (newOptionsMap.get("hardwareAcceleration") != null && options.hardwareAcceleration != newOptions.hardwareAcceleration) { + if (newOptions.hardwareAcceleration) + setLayerType(View.LAYER_TYPE_HARDWARE, null); + else + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + if (newOptions.contentBlockers != null) { contentBlockerHandler.getRuleList().clear(); for (Map> contentBlocker : newOptions.contentBlockers) { diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java index 4168c34f..b06208a0 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java @@ -12,44 +12,46 @@ public class InAppWebViewOptions extends Options { public static final String LOG_TAG = "InAppWebViewOptions"; - public boolean useShouldOverrideUrlLoading = false; - public boolean useOnLoadResource = false; - public boolean useOnDownloadStart = false; - public boolean useOnTargetBlank = false; - public boolean clearCache = false; + public Boolean useShouldOverrideUrlLoading = false; + public Boolean useOnLoadResource = false; + public Boolean useOnDownloadStart = false; + public Boolean useOnTargetBlank = false; + public Boolean clearCache = false; public String userAgent = ""; - public boolean javaScriptEnabled = true; - public boolean debuggingEnabled = false; - public boolean javaScriptCanOpenWindowsAutomatically = false; - public boolean mediaPlaybackRequiresUserGesture = true; + public String applicationNameForUserAgent = ""; + public Boolean javaScriptEnabled = true; + public Boolean debuggingEnabled = false; + public Boolean javaScriptCanOpenWindowsAutomatically = false; + public Boolean mediaPlaybackRequiresUserGesture = true; public Integer textZoom = 100; public Integer minimumFontSize = 8; - public boolean verticalScrollBarEnabled = true; - public boolean horizontalScrollBarEnabled = true; + public Boolean verticalScrollBarEnabled = true; + public Boolean horizontalScrollBarEnabled = true; public List resourceCustomSchemes = new ArrayList<>(); public List>> contentBlockers = new ArrayList<>(); public Integer preferredContentMode = PreferredContentModeOptionType.RECOMMENDED.toValue(); public Boolean useShouldInterceptAjaxRequest = false; public Boolean useShouldInterceptFetchRequest = false; + public Boolean incognito = false; + public Boolean cacheEnabled = true; + public Boolean transparentBackground = false; - public boolean clearSessionCache = false; - public boolean builtInZoomControls = false; - public boolean displayZoomControls = false; - public boolean supportZoom = true; - public boolean databaseEnabled = false; - public boolean domStorageEnabled = false; - public boolean useWideViewPort = true; - public boolean safeBrowsingEnabled = true; - public boolean transparentBackground = false; + public Boolean clearSessionCache = false; + public Boolean builtInZoomControls = false; + public Boolean displayZoomControls = false; + public Boolean supportZoom = true; + public Boolean databaseEnabled = false; + public Boolean domStorageEnabled = false; + public Boolean useWideViewPort = true; + public Boolean safeBrowsingEnabled = true; public Integer mixedContentMode; - public boolean allowContentAccess = true; - public boolean allowFileAccess = true; - public boolean allowFileAccessFromFileURLs = true; - public boolean allowUniversalAccessFromFileURLs = true; - public boolean appCacheEnabled = true; + public Boolean allowContentAccess = true; + public Boolean allowFileAccess = true; + public Boolean allowFileAccessFromFileURLs = true; + public Boolean allowUniversalAccessFromFileURLs = true; public String appCachePath; - public boolean blockNetworkImage = false; - public boolean blockNetworkLoads = false; + public Boolean blockNetworkImage = false; + public Boolean blockNetworkLoads = false; public Integer cacheMode = WebSettings.LOAD_DEFAULT; public String cursiveFontFamily = "cursive"; public Integer defaultFixedFontSize = 16; @@ -59,14 +61,17 @@ public class InAppWebViewOptions extends Options { public String fantasyFontFamily = "fantasy"; public String fixedFontFamily = "monospace"; public Integer forceDark = 0; // WebSettings.FORCE_DARK_OFF - public boolean geolocationEnabled = true; + public Boolean geolocationEnabled = true; public WebSettings.LayoutAlgorithm layoutAlgorithm; - public boolean loadWithOverviewMode = true; - public boolean loadsImagesAutomatically = true; + public Boolean loadWithOverviewMode = true; + public Boolean loadsImagesAutomatically = true; public Integer minimumLogicalFontSize = 8; - public boolean needInitialFocus = true; - public boolean offscreenPreRaster = false; + public Boolean needInitialFocus = true; + public Boolean offscreenPreRaster = false; public String sansSerifFontFamily = "sans-serif"; public String serifFontFamily = "sans-serif"; public String standardFontFamily = "sans-serif"; + public Boolean saveFormData = true; + public Boolean thirdPartyCookiesEnabled = true; + public Boolean hardwareAcceleration = true; } diff --git a/example/lib/inline_example.screen.dart b/example/lib/inline_example.screen.dart index d748da14..2454cb3f 100755 --- a/example/lib/inline_example.screen.dart +++ b/example/lib/inline_example.screen.dart @@ -93,7 +93,7 @@ class _InlineExampleScreenState extends State { initialOptions: InAppWebViewWidgetOptions( inAppWebViewOptions: InAppWebViewOptions( debuggingEnabled: true, - clearCache: true, + //clearCache: true, useShouldOverrideUrlLoading: true, useOnTargetBlank: true, useOnLoadResource: true, @@ -113,7 +113,6 @@ class _InlineExampleScreenState extends State { ), androidInAppWebViewOptions: AndroidInAppWebViewOptions( databaseEnabled: true, - appCacheEnabled: true, domStorageEnabled: true, geolocationEnabled: true, //safeBrowsingEnabled: true, diff --git a/ios/Classes/FlutterWebViewController.swift b/ios/Classes/FlutterWebViewController.swift index 994b7dee..f8931b80 100755 --- a/ios/Classes/FlutterWebViewController.swift +++ b/ios/Classes/FlutterWebViewController.swift @@ -302,6 +302,10 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView { } result(true) break + case "removeFromSuperview": + webView!.removeFromSuperview() + result(true) + break default: result(FlutterMethodNotImplemented) break diff --git a/ios/Classes/InAppWebView.swift b/ios/Classes/InAppWebView.swift index 4388e010..7a3f9ca9 100755 --- a/ios/Classes/InAppWebView.swift +++ b/ios/Classes/InAppWebView.swift @@ -26,6 +26,19 @@ func convertToDictionary(text: String) -> [String: Any]? { return nil } +func JSONStringify(value: Any, prettyPrinted: Bool = false) -> String { + let options: JSONSerialization.WritingOptions = prettyPrinted ? .prettyPrinted : .init(rawValue: 0) + if JSONSerialization.isValidJSONObject(value) { + let data = try? JSONSerialization.data(withJSONObject: value, options: options) + if data != nil { + if let string = String(data: data!, encoding: .utf8) { + return string + } + } + } + return "" +} + let JAVASCRIPT_BRIDGE_NAME = "flutter_inappbrowser" // the message needs to be concatenated with '' in order to have the same behavior like on Android @@ -662,7 +675,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi let jscriptWebkitTouchCallout = WKUserScript(source: "document.body.style.webkitTouchCallout='none';", injectionTime: .atDocumentEnd, forMainFrameOnly: true) configuration.userContentController.addUserScript(jscriptWebkitTouchCallout) - let consoleLogJSScript = WKUserScript(source: consoleLogJS, injectionTime: .atDocumentStart, forMainFrameOnly: false) configuration.userContentController.addUserScript(consoleLogJSScript) configuration.userContentController.add(self, name: "consoleLog") @@ -699,18 +711,39 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi configuration.userContentController.addUserScript(interceptFetchRequestsJSScript) } + if #available(iOS 9.0, *) { + if ((options?.incognito)!) { + configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent() + } else if ((options?.cacheEnabled)!) { + configuration.websiteDataStore = WKWebsiteDataStore.default() + } + } - //keyboardDisplayRequiresUserAction = browserOptions?.keyboardDisplayRequiresUserAction + if #available(iOS 11.0, *) { + if((options?.sharedCookiesEnabled)!) { + // More info to sending cookies with WKWebView + // https://stackoverflow.com/questions/26573137/can-i-set-the-cookies-to-be-used-by-a-wkwebview/26577303#26577303 + // Set Cookies in iOS 11 and above, initialize websiteDataStore before setting cookies + // See also https://forums.developer.apple.com/thread/97194 + // check if websiteDataStore has not been initialized before + if(!(options?.incognito)! && !(options?.cacheEnabled)!) { + configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent() + } + for cookie in HTTPCookieStorage.shared.cookies ?? [] { + configuration.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: nil) + } + } + } configuration.suppressesIncrementalRendering = (options?.suppressesIncrementalRendering)! allowsBackForwardNavigationGestures = (options?.allowsBackForwardNavigationGestures)! if #available(iOS 9.0, *) { allowsLinkPreview = (options?.allowsLinkPreview)! configuration.allowsPictureInPictureMediaPlayback = (options?.allowsPictureInPictureMediaPlayback)! - if ((options?.applicationNameForUserAgent)! != "") { + if (options?.applicationNameForUserAgent != nil && (options?.applicationNameForUserAgent)! != "") { configuration.applicationNameForUserAgent = (options?.applicationNameForUserAgent)! } - if ((options?.userAgent)! != "") { + if (options?.userAgent != nil && (options?.userAgent)! != "") { customUserAgent = (options?.userAgent)! } } @@ -927,6 +960,25 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi } } + if #available(iOS 9.0, *) { + if (newOptionsMap["incognito"] != nil && options?.incognito != newOptions.incognito && newOptions.incognito) { + configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent() + } else if (newOptionsMap["cacheEnabled"] != nil && options?.cacheEnabled != newOptions.cacheEnabled && newOptions.cacheEnabled) { + configuration.websiteDataStore = WKWebsiteDataStore.default() + } + } + + if #available(iOS 11.0, *) { + if (newOptionsMap["sharedCookiesEnabled"] != nil && options?.sharedCookiesEnabled != newOptions.sharedCookiesEnabled && newOptions.sharedCookiesEnabled) { + if(!newOptions.incognito && !newOptions.cacheEnabled) { + configuration.websiteDataStore = WKWebsiteDataStore.nonPersistent() + } + for cookie in HTTPCookieStorage.shared.cookies ?? [] { + configuration.websiteDataStore.httpCookieStore.setCookie(cookie, completionHandler: nil) + } + } + } + if newOptionsMap["enableViewportScale"] != nil && options?.enableViewportScale != newOptions.enableViewportScale && newOptions.enableViewportScale { let jscript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);" evaluateJavaScript(jscript, completionHandler: nil) @@ -960,10 +1012,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi configuration.allowsInlineMediaPlayback = newOptions.allowsInlineMediaPlayback } - // if newOptionsMap["keyboardDisplayRequiresUserAction"] != nil && browserOptions?.keyboardDisplayRequiresUserAction != newOptions.keyboardDisplayRequiresUserAction { - // self.webView.keyboardDisplayRequiresUserAction = newOptions.keyboardDisplayRequiresUserAction - // } - if newOptionsMap["suppressesIncrementalRendering"] != nil && options?.suppressesIncrementalRendering != newOptions.suppressesIncrementalRendering { configuration.suppressesIncrementalRendering = newOptions.suppressesIncrementalRendering } @@ -1997,4 +2045,24 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi func clearMatches(completionHandler: ((Any?, Error?) -> Void)?) { evaluateJavaScript("wkwebview_ClearMatches();", completionHandler: completionHandler) } + + public override func removeFromSuperview() { + configuration.userContentController.removeScriptMessageHandler(forName: "consoleLog") + configuration.userContentController.removeScriptMessageHandler(forName: "consoleDebug") + configuration.userContentController.removeScriptMessageHandler(forName: "consoleError") + configuration.userContentController.removeScriptMessageHandler(forName: "consoleInfo") + configuration.userContentController.removeScriptMessageHandler(forName: "consoleWarn") + configuration.userContentController.removeScriptMessageHandler(forName: "callHandler") + configuration.userContentController.removeScriptMessageHandler(forName: "onFindResultReceived") + configuration.userContentController.removeScriptMessageHandler(forName: "onNavigationStateChange") + configuration.userContentController.removeAllUserScripts() + removeObserver(self, forKeyPath: "estimatedProgress") + super.removeFromSuperview() + uiDelegate = nil + navigationDelegate = nil + scrollView.delegate = nil + IAWController?.channel?.setMethodCallHandler(nil) + IABController?.webView = nil + IAWController?.webView = nil + } } diff --git a/ios/Classes/InAppWebViewOptions.swift b/ios/Classes/InAppWebViewOptions.swift index 0acc27d6..e2995c7e 100755 --- a/ios/Classes/InAppWebViewOptions.swift +++ b/ios/Classes/InAppWebViewOptions.swift @@ -17,6 +17,7 @@ public class InAppWebViewOptions: Options { var useOnTargetBlank = false var clearCache = false var userAgent = "" + var applicationNameForUserAgent = "" var javaScriptEnabled = true var debuggingEnabled = true var javaScriptCanOpenWindowsAutomatically = false @@ -25,13 +26,15 @@ public class InAppWebViewOptions: Options { var horizontalScrollBarEnabled = true var resourceCustomSchemes: [String] = [] var contentBlockers: [[String: [String : Any]]] = [] - var minimumFontSize = 0; + var minimumFontSize = 0 var useShouldInterceptAjaxRequest = false var useShouldInterceptFetchRequest = false + var incognito = false + var cacheEnabled = true + var transparentBackground = false var disallowOverScroll = false var enableViewportScale = false - //var keyboardDisplayRequiresUserAction = true var suppressesIncrementalRendering = false var allowsAirPlayForMediaPlayback = true var allowsBackForwardNavigationGestures = true @@ -39,12 +42,11 @@ public class InAppWebViewOptions: Options { var ignoresViewportScaleLimits = false var allowsInlineMediaPlayback = false var allowsPictureInPictureMediaPlayback = true - var transparentBackground = false - var applicationNameForUserAgent = ""; var isFraudulentWebsiteWarningEnabled = true; var selectionGranularity = 0; - var dataDetectorTypes: [String] = ["NONE"]; // WKDataDetectorTypeNone - var preferredContentMode = 0; + var dataDetectorTypes: [String] = ["NONE"] // WKDataDetectorTypeNone + var preferredContentMode = 0 + var sharedCookiesEnabled = false override init(){ super.init() diff --git a/lib/src/in_app_webview.dart b/lib/src/in_app_webview.dart index 54e117b3..174de218 100755 --- a/lib/src/in_app_webview.dart +++ b/lib/src/in_app_webview.dart @@ -325,6 +325,13 @@ class _InAppWebViewState extends State { super.didUpdateWidget(oldWidget); } + @override + void dispose(){ + super.dispose(); + if (Platform.isIOS) + _controller._channel.invokeMethod('removeFromSuperview'); + } + void _onPlatformViewCreated(int id) { _controller = InAppWebViewController(id, widget); if (widget.onWebViewCreated != null) { diff --git a/lib/src/webview_options.dart b/lib/src/webview_options.dart index 158ea309..ea78f562 100644 --- a/lib/src/webview_options.dart +++ b/lib/src/webview_options.dart @@ -43,6 +43,7 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti bool useOnTargetBlank; bool clearCache; String userAgent; + String applicationNameForUserAgent; bool javaScriptEnabled; bool debuggingEnabled; bool javaScriptCanOpenWindowsAutomatically; @@ -56,12 +57,15 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti InAppWebViewUserPreferredContentMode preferredContentMode; bool useShouldInterceptAjaxRequest; bool useShouldInterceptFetchRequest; + bool incognito; + bool cacheEnabled; + bool transparentBackground; InAppWebViewOptions({this.useShouldOverrideUrlLoading = false, this.useOnLoadResource = false, this.useOnDownloadStart = false, this.useOnTargetBlank = false, - this.clearCache = false, this.userAgent = "", this.javaScriptEnabled = true, this.debuggingEnabled = false, this.javaScriptCanOpenWindowsAutomatically = false, + this.clearCache = false, this.userAgent = "", this.applicationNameForUserAgent = "", this.javaScriptEnabled = true, this.debuggingEnabled = false, this.javaScriptCanOpenWindowsAutomatically = false, this.mediaPlaybackRequiresUserGesture = true, this.textZoom = 100, this.minimumFontSize, this.verticalScrollBarEnabled = true, this.horizontalScrollBarEnabled = true, this.resourceCustomSchemes = const [], this.contentBlockers = const [], this.preferredContentMode = InAppWebViewUserPreferredContentMode.RECOMMENDED, - this.useShouldInterceptAjaxRequest = false, this.useShouldInterceptFetchRequest = false}) { + this.useShouldInterceptAjaxRequest = false, this.useShouldInterceptFetchRequest = false, this.incognito = false, this.cacheEnabled = true, this.transparentBackground = false}) { if (this.minimumFontSize == null) this.minimumFontSize = Platform.isAndroid ? 8 : 0; assert(!this.resourceCustomSchemes.contains("http") && !this.resourceCustomSchemes.contains("https")); @@ -81,6 +85,7 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti "useOnTargetBlank": useOnTargetBlank, "clearCache": clearCache, "userAgent": userAgent, + "applicationNameForUserAgent": applicationNameForUserAgent, "javaScriptEnabled": javaScriptEnabled, "debuggingEnabled": debuggingEnabled, "javaScriptCanOpenWindowsAutomatically": javaScriptCanOpenWindowsAutomatically, @@ -92,7 +97,10 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti "contentBlockers": contentBlockersMapList, "preferredContentMode": preferredContentMode?.toValue(), "useShouldInterceptAjaxRequest": useShouldInterceptAjaxRequest, - "useShouldInterceptFetchRequest": useShouldInterceptFetchRequest + "useShouldInterceptFetchRequest": useShouldInterceptFetchRequest, + "incognito": incognito, + "cacheEnabled": cacheEnabled, + "transparentBackground": transparentBackground }; } @@ -115,7 +123,9 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti options.useOnTargetBlank = map["useOnTargetBlank"]; options.clearCache = map["clearCache"]; options.userAgent = map["userAgent"]; + options.applicationNameForUserAgent = map["applicationNameForUserAgent"]; options.javaScriptEnabled = map["javaScriptEnabled"]; + options.debuggingEnabled = map["debuggingEnabled"]; options.javaScriptCanOpenWindowsAutomatically = map["javaScriptCanOpenWindowsAutomatically"]; options.mediaPlaybackRequiresUserGesture = map["mediaPlaybackRequiresUserGesture"]; options.textZoom = map["textZoom"]; @@ -124,6 +134,11 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti options.resourceCustomSchemes = List.from(map["resourceCustomSchemes"] ?? []); options.contentBlockers = contentBlockers; options.preferredContentMode = InAppWebViewUserPreferredContentMode.fromValue(map["preferredContentMode"]); + options.useShouldInterceptAjaxRequest = map["useShouldInterceptAjaxRequest"]; + options.useShouldInterceptFetchRequest = map["useShouldInterceptFetchRequest"]; + options.incognito = map["incognito"]; + options.cacheEnabled = map["cacheEnabled"]; + options.transparentBackground = map["transparentBackground"]; return options; } } @@ -137,13 +152,11 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr bool domStorageEnabled; bool useWideViewPort; bool safeBrowsingEnabled; - bool transparentBackground; AndroidInAppWebViewMixedContentMode mixedContentMode; bool allowContentAccess; bool allowFileAccess; bool allowFileAccessFromFileURLs; bool allowUniversalAccessFromFileURLs; - bool appCacheEnabled; String appCachePath; bool blockNetworkImage; bool blockNetworkLoads; @@ -166,16 +179,19 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr String sansSerifFontFamily; String serifFontFamily; String standardFontFamily; + bool saveFormData; + bool thirdPartyCookiesEnabled; + bool hardwareAcceleration; AndroidInAppWebViewOptions({this.clearSessionCache = false, this.builtInZoomControls = false, this.displayZoomControls = false, this.supportZoom = true, this.databaseEnabled = false, - this.domStorageEnabled = false, this.useWideViewPort = true, this.safeBrowsingEnabled = true, this.transparentBackground = false, this.mixedContentMode, + this.domStorageEnabled = false, this.useWideViewPort = true, this.safeBrowsingEnabled = true, this.mixedContentMode, this.allowContentAccess = true, this.allowFileAccess = true, this.allowFileAccessFromFileURLs = true, this.allowUniversalAccessFromFileURLs = true, - this.appCacheEnabled = true, this.appCachePath, this.blockNetworkImage = false, this.blockNetworkLoads = false, this.cacheMode = AndroidInAppWebViewCacheMode.LOAD_DEFAULT, + this.appCachePath, this.blockNetworkImage = false, this.blockNetworkLoads = false, this.cacheMode = AndroidInAppWebViewCacheMode.LOAD_DEFAULT, this.cursiveFontFamily = "cursive", this.defaultFixedFontSize = 16, this.defaultFontSize = 16, this.defaultTextEncodingName = "UTF-8", this.disabledActionModeMenuItems, this.fantasyFontFamily = "fantasy", this.fixedFontFamily = "monospace", this.forceDark = AndroidInAppWebViewForceDark.FORCE_DARK_OFF, this.geolocationEnabled = true, this.layoutAlgorithm, this.loadWithOverviewMode = true, this.loadsImagesAutomatically = true, this.minimumLogicalFontSize = 8, this.needInitialFocus = true, this.offscreenPreRaster = false, this.sansSerifFontFamily = "sans-serif", this.serifFontFamily = "sans-serif", - this.standardFontFamily = "sans-serif" + this.standardFontFamily = "sans-serif", this.saveFormData = true, this.thirdPartyCookiesEnabled = true, this.hardwareAcceleration = true }); @override @@ -189,13 +205,11 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr "domStorageEnabled": domStorageEnabled, "useWideViewPort": useWideViewPort, "safeBrowsingEnabled": safeBrowsingEnabled, - "transparentBackground": transparentBackground, "mixedContentMode": mixedContentMode?.toValue(), "allowContentAccess": allowContentAccess, "allowFileAccess": allowFileAccess, "allowFileAccessFromFileURLs": allowFileAccessFromFileURLs, "allowUniversalAccessFromFileURLs": allowUniversalAccessFromFileURLs, - "appCacheEnabled": appCacheEnabled, "appCachePath": appCachePath, "blockNetworkImage": blockNetworkImage, "blockNetworkLoads": blockNetworkLoads, @@ -217,7 +231,10 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr "offscreenPreRaster": offscreenPreRaster, "sansSerifFontFamily": sansSerifFontFamily, "serifFontFamily": serifFontFamily, - "standardFontFamily": standardFontFamily + "standardFontFamily": standardFontFamily, + "saveFormData": saveFormData, + "thirdPartyCookiesEnabled": thirdPartyCookiesEnabled, + "hardwareAcceleration": hardwareAcceleration }; } @@ -232,13 +249,11 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr options.domStorageEnabled = map["domStorageEnabled"]; options.useWideViewPort = map["useWideViewPort"]; options.safeBrowsingEnabled = map["safeBrowsingEnabled"]; - options.transparentBackground = map["transparentBackground"]; options.mixedContentMode = AndroidInAppWebViewMixedContentMode.fromValue(map["mixedContentMode"]); options.allowContentAccess = map["allowContentAccess"]; options.allowFileAccess = map["allowFileAccess"]; options.allowFileAccessFromFileURLs = map["allowFileAccessFromFileURLs"]; options.allowUniversalAccessFromFileURLs = map["allowUniversalAccessFromFileURLs"]; - options.appCacheEnabled = map["appCacheEnabled"]; options.appCachePath = map["appCachePath"]; options.blockNetworkImage = map["blockNetworkImage"]; options.blockNetworkLoads = map["blockNetworkLoads"]; @@ -261,6 +276,9 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, Andr options.sansSerifFontFamily = map["sansSerifFontFamily"]; options.serifFontFamily = map["serifFontFamily"]; options.standardFontFamily = map["standardFontFamily"]; + options.saveFormData = map["saveFormData"]; + options.thirdPartyCookiesEnabled = map["thirdPartyCookiesEnabled"]; + options.hardwareAcceleration = map["hardwareAcceleration"]; return options; } } @@ -275,16 +293,15 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio bool ignoresViewportScaleLimits; bool allowsInlineMediaPlayback; bool allowsPictureInPictureMediaPlayback; - bool transparentBackground; - String applicationNameForUserAgent; bool isFraudulentWebsiteWarningEnabled; IosInAppWebViewSelectionGranularity selectionGranularity; List dataDetectorTypes; + bool sharedCookiesEnabled; IosInAppWebViewOptions({this.disallowOverScroll = false, this.enableViewportScale = false, this.suppressesIncrementalRendering = false, this.allowsAirPlayForMediaPlayback = true, this.allowsBackForwardNavigationGestures = true, this.allowsLinkPreview = true, this.ignoresViewportScaleLimits = false, this.allowsInlineMediaPlayback = false, - this.allowsPictureInPictureMediaPlayback = true, this.transparentBackground = false, this.applicationNameForUserAgent = "", this.isFraudulentWebsiteWarningEnabled = true, - this.selectionGranularity = IosInAppWebViewSelectionGranularity.DYNAMIC, this.dataDetectorTypes = const [IosInAppWebViewDataDetectorTypes.NONE] + this.allowsPictureInPictureMediaPlayback = true, this.isFraudulentWebsiteWarningEnabled = true, + this.selectionGranularity = IosInAppWebViewSelectionGranularity.DYNAMIC, this.dataDetectorTypes = const [IosInAppWebViewDataDetectorTypes.NONE], this.sharedCookiesEnabled = false }); @override @@ -304,11 +321,10 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio "ignoresViewportScaleLimits": ignoresViewportScaleLimits, "allowsInlineMediaPlayback": allowsInlineMediaPlayback, "allowsPictureInPictureMediaPlayback": allowsPictureInPictureMediaPlayback, - "transparentBackground": transparentBackground, - "applicationNameForUserAgent": applicationNameForUserAgent, "isFraudulentWebsiteWarningEnabled": isFraudulentWebsiteWarningEnabled, "selectionGranularity": selectionGranularity.toValue(), - "dataDetectorTypes": dataDetectorTypesList + "dataDetectorTypes": dataDetectorTypesList, + "sharedCookiesEnabled": sharedCookiesEnabled }; } @@ -330,11 +346,10 @@ class IosInAppWebViewOptions implements WebViewOptions, BrowserOptions, IosOptio options.ignoresViewportScaleLimits = map["ignoresViewportScaleLimits"]; options.allowsInlineMediaPlayback = map["allowsInlineMediaPlayback"]; options.allowsPictureInPictureMediaPlayback = map["allowsPictureInPictureMediaPlayback"]; - options.transparentBackground = map["transparentBackground"]; - options.applicationNameForUserAgent = map["applicationNameForUserAgent"]; options.isFraudulentWebsiteWarningEnabled = map["isFraudulentWebsiteWarningEnabled"]; options.selectionGranularity = IosInAppWebViewSelectionGranularity.fromValue(map["selectionGranularity"]); options.dataDetectorTypes = dataDetectorTypes; + options.sharedCookiesEnabled = map["sharedCookiesEnabled"]; return options; } }