Added scriptHtmlTagAttributes optional argument to injectJavascriptFileFromUrl WebView method, Added cssLinkHtmlTagAttributes optional argument to injectCSSFileFromUrl WebView method

This commit is contained in:
Lorenzo Pichilli 2021-02-09 21:11:50 +01:00
parent bbb2af8275
commit 0e4e16562d
11 changed files with 432 additions and 23 deletions

View File

@ -13,6 +13,8 @@
- Added `handlesURLScheme`, `createPdf`, `createWebArchiveData` iOS-specific WebView methods - Added `handlesURLScheme`, `createPdf`, `createWebArchiveData` iOS-specific WebView methods
- Added `iosAnimated` optional argument to `zoomBy` WebView method - Added `iosAnimated` optional argument to `zoomBy` WebView method
- Added `screenshotConfiguration` optional argument to `takeScreenshot` WebView method - Added `screenshotConfiguration` optional argument to `takeScreenshot` WebView method
- Added `scriptHtmlTagAttributes` optional argument to `injectJavascriptFileFromUrl` WebView method
- Added `cssLinkHtmlTagAttributes` optional argument to `injectCSSFileFromUrl` WebView method
- Updated integration tests - Updated integration tests
- Merge "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu)) - Merge "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu))
- Merge "Added missing field 'headers' which returned by WebResourceResponse.toMap()" [#490](https://github.com/pichillilorenzo/flutter_inappwebview/pull/490) (thanks to [Doflatango](https://github.com/Doflatango)) - Merge "Added missing field 'headers' which returned by WebResourceResponse.toMap()" [#490](https://github.com/pichillilorenzo/flutter_inappwebview/pull/490) (thanks to [Doflatango](https://github.com/Doflatango))
@ -38,7 +40,7 @@
### BREAKING CHANGES ### BREAKING CHANGES
- Minimum Flutter version required is `1.22.0` and Dart SDK `>=2.12.0-0 <3.0.0` - Minimum Flutter version required is `1.22.2` and Dart SDK `>=2.12.0-0 <3.0.0`
- iOS Xcode version `>= 12` - iOS Xcode version `>= 12`
- Removed `debuggingEnabled` WebView option; on Android you should use now the `AndroidInAppWebViewController.setWebContentsDebuggingEnabled(bool debuggingEnabled)` static method; on iOS, debugging is always enabled - Removed `debuggingEnabled` WebView option; on Android you should use now the `AndroidInAppWebViewController.setWebContentsDebuggingEnabled(bool debuggingEnabled)` static method; on iOS, debugging is always enabled
- `allowUniversalAccessFromFileURLs` and `allowFileAccessFromFileURLs` WebView options moved from Android-specific options to cross-platform options - `allowUniversalAccessFromFileURLs` and `allowFileAccessFromFileURLs` WebView options moved from Android-specific options to cross-platform options

View File

@ -1,7 +1,10 @@
# Flutter InAppWebView Plugin [![Share on Twitter](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Flutter%20InAppBrowser%20plugin!&url=https://github.com/pichillilorenzo/flutter_inappwebview&hashtags=flutter,flutterio,dart,dartlang,webview) [![Share on Facebook](https://img.shields.io/badge/share-facebook-blue.svg?longCache=true&style=flat&colorB=%234267b2)](https://www.facebook.com/sharer/sharer.php?u=https%3A//github.com/pichillilorenzo/flutter_inappwebview) # Flutter InAppWebView Plugin [![Share on Twitter](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Flutter%20InAppBrowser%20plugin!&url=https://github.com/pichillilorenzo/flutter_inappwebview&hashtags=flutter,flutterio,dart,dartlang,webview) [![Share on Facebook](https://img.shields.io/badge/share-facebook-blue.svg?longCache=true&style=flat&colorB=%234267b2)](https://www.facebook.com/sharer/sharer.php?u=https%3A//github.com/pichillilorenzo/flutter_inappwebview)
[![Pub](https://img.shields.io/pub/v/flutter_inappwebview.svg)](https://pub.dartlang.org/packages/flutter_inappwebview) [![Pub](https://img.shields.io/pub/v/flutter_inappwebview.svg)](https://pub.dartlang.org/packages/flutter_inappwebview)
[![Awesome Flutter](https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square)](https://stackoverflow.com/questions/tagged/flutter+webview?sort=votes) [![pub points](https://badges.bar/flutter_inappwebview/pub%20points)](https://pub.dev/packages/flutter_inappwebview/score)
[![popularity](https://badges.bar/flutter_inappwebview/popularity)](https://pub.dev/packages/flutter_inappwebview/score)
[![likes](https://badges.bar/flutter_inappwebview/likes)](https://pub.dev/packages/flutter_inappwebview/score)
[![Awesome Flutter](https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square)](https://stackoverflow.com/questions/tagged/flutter-inappwebview)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](/LICENSE) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](/LICENSE)
[![Donate to this project using Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.me/LorenzoPichilli) [![Donate to this project using Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.me/LorenzoPichilli)
@ -22,6 +25,8 @@ Note that the API shown in this `README.md` file shows only a **part** of the do
So, here you could have methods, options, and events that **aren't published/released yet**! So, here you could have methods, options, and events that **aren't published/released yet**!
If you need a specific version, please change the **GitHub branch** of this repository to your version or use the **online [API Reference](https://pub.dartlang.org/documentation/flutter_inappwebview/latest/)** (recommended). If you need a specific version, please change the **GitHub branch** of this repository to your version or use the **online [API Reference](https://pub.dartlang.org/documentation/flutter_inappwebview/latest/)** (recommended).
Also, check the [example/integration_test/webview_flutter_test.dart](https://github.com/pichillilorenzo/flutter_inappwebview/blob/master/example/integration_test/webview_flutter_test.dart) file for code examples.
## Articles/Resources ## Articles/Resources
- [InAppWebView: The Real Power of WebViews in Flutter](https://medium.com/flutter-community/inappwebview-the-real-power-of-webviews-in-flutter-c6d52374209d?source=friends_link&sk=cb74487219bcd85e610a670ee0b447d0) - [InAppWebView: The Real Power of WebViews in Flutter](https://medium.com/flutter-community/inappwebview-the-real-power-of-webviews-in-flutter-c6d52374209d?source=friends_link&sk=cb74487219bcd85e610a670ee0b447d0)
@ -426,9 +431,9 @@ Screenshots:
* `goTo({required WebHistoryItem historyItem})`: Navigates to a `WebHistoryItem` from the back-forward `WebHistory.list` and sets it as the current item. * `goTo({required WebHistoryItem historyItem})`: Navigates to a `WebHistoryItem` from the back-forward `WebHistory.list` and sets it as the current item.
* `injectCSSCode({required String source})`: Injects CSS into the WebView. * `injectCSSCode({required String source})`: Injects CSS into the WebView.
* `injectCSSFileFromAsset({required String assetFilePath})`: Injects a CSS file into the WebView from the flutter assets directory. * `injectCSSFileFromAsset({required String assetFilePath})`: Injects a CSS file into the WebView from the flutter assets directory.
* `injectCSSFileFromUrl({required String urlFile})`: Injects an external CSS file into the WebView from a defined url. * `injectCSSFileFromUrl({required String urlFile, CSSLinkHtmlTagAttributes? cssLinkHtmlTagAttributes})`: Injects an external CSS file into the WebView from a defined url.
* `injectJavascriptFileFromAsset({required String assetFilePath})`: Injects a JavaScript file into the WebView from the flutter assets directory. * `injectJavascriptFileFromAsset({required String assetFilePath})`: Injects a JavaScript file into the WebView from the flutter assets directory.
* `injectJavascriptFileFromUrl({required String urlFile})`: Injects an external JavaScript file into the WebView from a defined url. * `injectJavascriptFileFromUrl({required String urlFile, ScriptHtmlTagAttributes? scriptHtmlTagAttributes})`: Injects an external JavaScript file into the WebView from a defined url.
* `isLoading`: Check if the WebView instance is in a loading state. * `isLoading`: Check if the WebView instance is in a loading state.
* `loadData({required String data, String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", String androidHistoryUrl = "about:blank"})`: Loads the given data into this WebView. * `loadData({required String data, String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", String androidHistoryUrl = "about:blank"})`: Loads the given data into this WebView.
* `loadFile({required String assetFilePath, Map<String, String> headers = const {}})`: Loads the given `assetFilePath` with optional headers specified as a map from name to value. * `loadFile({required String assetFilePath, Map<String, String> headers = const {}})`: Loads the given `assetFilePath` with optional headers specified as a map from name to value.

View File

@ -1523,7 +1523,7 @@ final public class InAppWebView extends InputAwareWebView {
return (options != null) ? options.getRealOptions(this) : null; return (options != null) ? options.getRealOptions(this) : null;
} }
public void injectDeferredObject(String source, @Nullable final String contentWorldName, String jsWrapper, final MethodChannel.Result result) { public void injectDeferredObject(String source, @Nullable final String contentWorldName, String jsWrapper, @Nullable final MethodChannel.Result result) {
String scriptToInject = source; String scriptToInject = source;
if (jsWrapper != null) { if (jsWrapper != null) {
org.json.JSONArray jsonEsc = new org.json.JSONArray(); org.json.JSONArray jsonEsc = new org.json.JSONArray();
@ -1577,18 +1577,95 @@ final public class InAppWebView extends InputAwareWebView {
injectDeferredObject(source, contentWorldName, null, result); injectDeferredObject(source, contentWorldName, null, result);
} }
public void injectJavascriptFileFromUrl(String urlFile) { public void injectJavascriptFileFromUrl(String urlFile, @Nullable Map<String, Object> scriptHtmlTagAttributes) {
String jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document);"; String scriptAttributes = "";
if (scriptHtmlTagAttributes != null) {
String typeAttr = (String) scriptHtmlTagAttributes.get("type");
if (typeAttr != null) {
scriptAttributes += " script.type = '" + typeAttr.replaceAll("'", "\\\\'") + "'; ";
}
String idAttr = (String) scriptHtmlTagAttributes.get("id");
if (idAttr != null) {
scriptAttributes += " script.id = '" + idAttr.replaceAll("'", "\\\\'") + "'; ";
}
Boolean asyncAttr = (Boolean) scriptHtmlTagAttributes.get("async");
if (asyncAttr != null && asyncAttr) {
scriptAttributes += " script.async = true; ";
}
Boolean deferAttr = (Boolean) scriptHtmlTagAttributes.get("defer");
if (deferAttr != null && deferAttr) {
scriptAttributes += " script.defer = true; ";
}
String crossOriginAttr = (String) scriptHtmlTagAttributes.get("crossOrigin");
if (crossOriginAttr != null) {
scriptAttributes += " script.crossOrigin = '" + crossOriginAttr.replaceAll("'", "\\\\'") + "'; ";
}
String integrityAttr = (String) scriptHtmlTagAttributes.get("integrity");
if (integrityAttr != null) {
scriptAttributes += " script.integrity = '" + integrityAttr.replaceAll("'", "\\\\'") + "'; ";
}
Boolean noModuleAttr = (Boolean) scriptHtmlTagAttributes.get("noModule");
if (noModuleAttr != null && noModuleAttr) {
scriptAttributes += " script.noModule = true; ";
}
String nonceAttr = (String) scriptHtmlTagAttributes.get("nonce");
if (nonceAttr != null) {
scriptAttributes += " script.nonce = '" + nonceAttr.replaceAll("'", "\\\\'") + "'; ";
}
String referrerPolicyAttr = (String) scriptHtmlTagAttributes.get("referrerPolicy");
if (referrerPolicyAttr != null) {
scriptAttributes += " script.referrerPolicy = '" + referrerPolicyAttr.replaceAll("'", "\\\\'") + "'; ";
}
}
String jsWrapper = "(function(d) { var script = d.createElement('script'); " + scriptAttributes +
" script.src = %s; d.body.appendChild(script); })(document);";
injectDeferredObject(urlFile, null, jsWrapper, null); injectDeferredObject(urlFile, null, jsWrapper, null);
} }
public void injectCSSCode(String source) { public void injectCSSCode(String source) {
String jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %s; d.body.appendChild(c); })(document);"; String jsWrapper = "(function(d) { var style = d.createElement('style'); style.innerHTML = %s; d.body.appendChild(style); })(document);";
injectDeferredObject(source, null, jsWrapper, null); injectDeferredObject(source, null, jsWrapper, null);
} }
public void injectCSSFileFromUrl(String urlFile) { public void injectCSSFileFromUrl(String urlFile, @Nullable Map<String, Object> cssLinkHtmlTagAttributes) {
String jsWrapper = "(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %s; d.head.appendChild(c); })(document);"; String cssLinkAttributes = "";
String alternateStylesheet = "";
if (cssLinkHtmlTagAttributes != null) {
String idAttr = (String) cssLinkHtmlTagAttributes.get("id");
if (idAttr != null) {
cssLinkAttributes += " link.id = '" + idAttr.replaceAll("'", "\\\\'") + "'; ";
}
String mediaAttr = (String) cssLinkHtmlTagAttributes.get("media");
if (mediaAttr != null) {
cssLinkAttributes += " link.media = '" + mediaAttr.replaceAll("'", "\\\\'") + "'; ";
}
String crossOriginAttr = (String) cssLinkHtmlTagAttributes.get("crossOrigin");
if (crossOriginAttr != null) {
cssLinkAttributes += " link.crossOrigin = '" + crossOriginAttr.replaceAll("'", "\\\\'") + "'; ";
}
String integrityAttr = (String) cssLinkHtmlTagAttributes.get("integrity");
if (integrityAttr != null) {
cssLinkAttributes += " link.integrity = '" + integrityAttr.replaceAll("'", "\\\\'") + "'; ";
}
String referrerPolicyAttr = (String) cssLinkHtmlTagAttributes.get("referrerPolicy");
if (referrerPolicyAttr != null) {
cssLinkAttributes += " link.referrerPolicy = '" + referrerPolicyAttr.replaceAll("'", "\\\\'") + "'; ";
}
Boolean disabledAttr = (Boolean) cssLinkHtmlTagAttributes.get("disabled");
if (disabledAttr != null && disabledAttr) {
cssLinkAttributes += " link.disabled = true; ";
}
Boolean alternateAttr = (Boolean) cssLinkHtmlTagAttributes.get("alternate");
if (alternateAttr != null && alternateAttr) {
alternateStylesheet = "alternate ";
}
String titleAttr = (String) cssLinkHtmlTagAttributes.get("title");
if (titleAttr != null) {
cssLinkAttributes += " link.title = '" + titleAttr.replaceAll("'", "\\\\'") + "'; ";
}
}
String jsWrapper = "(function(d) { var link = d.createElement('link'); link.rel='" + alternateStylesheet + "stylesheet'; link.type='text/css'; " +
cssLinkAttributes + " link.href = %s; d.head.appendChild(link); })(document);";
injectDeferredObject(urlFile, null, jsWrapper, null); injectDeferredObject(urlFile, null, jsWrapper, null);
} }

View File

@ -84,7 +84,8 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
case "injectJavascriptFileFromUrl": case "injectJavascriptFileFromUrl":
if (webView != null) { if (webView != null) {
String urlFile = (String) call.argument("urlFile"); String urlFile = (String) call.argument("urlFile");
webView.injectJavascriptFileFromUrl(urlFile); Map<String, Object> scriptHtmlTagAttributes = (Map<String, Object>) call.argument("scriptHtmlTagAttributes");
webView.injectJavascriptFileFromUrl(urlFile, scriptHtmlTagAttributes);
} }
result.success(true); result.success(true);
break; break;
@ -98,7 +99,8 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle
case "injectCSSFileFromUrl": case "injectCSSFileFromUrl":
if (webView != null) { if (webView != null) {
String urlFile = (String) call.argument("urlFile"); String urlFile = (String) call.argument("urlFile");
webView.injectCSSFileFromUrl(urlFile); Map<String, Object> cssLinkHtmlTagAttributes = (Map<String, Object>) call.argument("cssLinkHtmlTagAttributes");
webView.injectCSSFileFromUrl(urlFile, cssLinkHtmlTagAttributes);
} }
result.success(true); result.success(true);
break; break;

View File

@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-02-09 01:23:18.308862","version":"1.26.0-18.0.pre.90"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-02-09 21:00:13.907504","version":"1.26.0-18.0.pre.90"}

View File

@ -115,6 +115,9 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
this.url = url ?? ''; this.url = url ?? '';
}); });
}, },
androidOnPermissionRequest: (InAppWebViewController controller, String origin, List<String> resources) async {
return PermissionRequestResponse(resources: resources, action: PermissionRequestResponseAction.GRANT);
},
shouldOverrideUrlLoading: (controller, shouldOverrideUrlLoadingRequest) async { shouldOverrideUrlLoading: (controller, shouldOverrideUrlLoadingRequest) async {
var url = shouldOverrideUrlLoadingRequest.url; var url = shouldOverrideUrlLoadingRequest.url;
var uri = Uri.parse(url); var uri = Uri.parse(url);

View File

@ -14,6 +14,12 @@
<excludeFolder url="file://$MODULE_DIR$/example/flutter_plugin/.dart_tool" /> <excludeFolder url="file://$MODULE_DIR$/example/flutter_plugin/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/flutter_plugin/.pub" /> <excludeFolder url="file://$MODULE_DIR$/example/flutter_plugin/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/flutter_plugin/build" /> <excludeFolder url="file://$MODULE_DIR$/example/flutter_plugin/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/device_info/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/device_info/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/device_info/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/device_info/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/device_info/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/device_info/example/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/.dart_tool" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/.pub" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/build" /> <excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/flutter_downloader/build" />

View File

@ -2303,18 +2303,76 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
} }
} }
public func injectJavascriptFileFromUrl(urlFile: String) { public func injectJavascriptFileFromUrl(urlFile: String, scriptHtmlTagAttributes: [String:Any?]?) {
let jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %@; d.body.appendChild(c); })(document);" var scriptAttributes = ""
if let scriptHtmlTagAttributes = scriptHtmlTagAttributes {
if let typeAttr = scriptHtmlTagAttributes["type"] as? String {
scriptAttributes += " script.type = '\(typeAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let idAttr = scriptHtmlTagAttributes["id"] as? String {
scriptAttributes += " script.id = '\(idAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let asyncAttr = scriptHtmlTagAttributes["async"] as? Bool, asyncAttr {
scriptAttributes += " script.async = true; "
}
if let deferAttr = scriptHtmlTagAttributes["defer"] as? Bool, deferAttr {
scriptAttributes += " script.defer = true; "
}
if let crossOriginAttr = scriptHtmlTagAttributes["crossOrigin"] as? String {
scriptAttributes += " script.crossOrigin = '\(crossOriginAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let integrityAttr = scriptHtmlTagAttributes["integrity"] as? String {
scriptAttributes += " script.integrity = '\(integrityAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let noModuleAttr = scriptHtmlTagAttributes["noModule"] as? Bool, noModuleAttr {
scriptAttributes += " script.noModule = true; "
}
if let nonceAttr = scriptHtmlTagAttributes["nonce"] as? String {
scriptAttributes += " script.nonce = '\(nonceAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let referrerPolicyAttr = scriptHtmlTagAttributes["referrerPolicy"] as? String {
scriptAttributes += " script.referrerPolicy = '\(referrerPolicyAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
}
let jsWrapper = "(function(d) { var script = d.createElement('script'); \(scriptAttributes) script.src = %@; d.body.appendChild(script); })(document);"
injectDeferredObject(source: urlFile, contentWorldName: nil, withWrapper: jsWrapper, result: nil) injectDeferredObject(source: urlFile, contentWorldName: nil, withWrapper: jsWrapper, result: nil)
} }
public func injectCSSCode(source: String) { public func injectCSSCode(source: String) {
let jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %@; d.body.appendChild(c); })(document);" let jsWrapper = "(function(d) { var style = d.createElement('style'); style.innerHTML = %@; d.body.appendChild(style); })(document);"
injectDeferredObject(source: source, contentWorldName: nil, withWrapper: jsWrapper, result: nil) injectDeferredObject(source: source, contentWorldName: nil, withWrapper: jsWrapper, result: nil)
} }
public func injectCSSFileFromUrl(urlFile: String) { public func injectCSSFileFromUrl(urlFile: String, cssLinkHtmlTagAttributes: [String:Any?]?) {
let jsWrapper = "(function(d) { var c = d.createElement('link'); c.rel='stylesheet', c.type='text/css'; c.href = %@; d.body.appendChild(c); })(document);" var cssLinkAttributes = ""
var alternateStylesheet = ""
if let cssLinkHtmlTagAttributes = cssLinkHtmlTagAttributes {
if let idAttr = cssLinkHtmlTagAttributes["id"] as? String {
cssLinkAttributes += " link.id = '\(idAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let mediaAttr = cssLinkHtmlTagAttributes["media"] as? String {
cssLinkAttributes += " link.media = '\(mediaAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let crossOriginAttr = cssLinkHtmlTagAttributes["crossOrigin"] as? String {
cssLinkAttributes += " link.crossOrigin = '\(crossOriginAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let integrityAttr = cssLinkHtmlTagAttributes["integrity"] as? String {
cssLinkAttributes += " link.integrity = '\(integrityAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let referrerPolicyAttr = cssLinkHtmlTagAttributes["referrerPolicy"] as? String {
cssLinkAttributes += " link.referrerPolicy = '\(referrerPolicyAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
if let disabledAttr = cssLinkHtmlTagAttributes["disabled"] as? Bool, disabledAttr {
cssLinkAttributes += " link.disabled = true; "
}
if let alternateAttr = cssLinkHtmlTagAttributes["alternate"] as? Bool, alternateAttr {
alternateStylesheet = "alternate "
}
if let titleAttr = cssLinkHtmlTagAttributes["title"] as? String {
cssLinkAttributes += " link.title = '\(titleAttr.replacingOccurrences(of: "\'", with: "\\'"))'; "
}
}
let jsWrapper = "(function(d) { var link = d.createElement('link'); link.rel='\(alternateStylesheet)stylesheet', link.type='text/css'; \(cssLinkAttributes) link.href = %@; d.body.appendChild(link); })(document);"
injectDeferredObject(source: urlFile, contentWorldName: nil, withWrapper: jsWrapper, result: nil) injectDeferredObject(source: urlFile, contentWorldName: nil, withWrapper: jsWrapper, result: nil)
} }

View File

@ -80,7 +80,8 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
break break
case "injectJavascriptFileFromUrl": case "injectJavascriptFileFromUrl":
let urlFile = arguments!["urlFile"] as! String let urlFile = arguments!["urlFile"] as! String
webView?.injectJavascriptFileFromUrl(urlFile: urlFile) let scriptHtmlTagAttributes = arguments!["scriptHtmlTagAttributes"] as? [String:Any?]
webView?.injectJavascriptFileFromUrl(urlFile: urlFile, scriptHtmlTagAttributes: scriptHtmlTagAttributes)
result(true) result(true)
break break
case "injectCSSCode": case "injectCSSCode":
@ -90,7 +91,8 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
break break
case "injectCSSFileFromUrl": case "injectCSSFileFromUrl":
let urlFile = arguments!["urlFile"] as! String let urlFile = arguments!["urlFile"] as! String
webView?.injectCSSFileFromUrl(urlFile: urlFile) let cssLinkHtmlTagAttributes = arguments!["cssLinkHtmlTagAttributes"] as? [String:Any?]
webView?.injectCSSFileFromUrl(urlFile: urlFile, cssLinkHtmlTagAttributes: cssLinkHtmlTagAttributes)
result(true) result(true)
break break
case "reload": case "reload":

View File

@ -1382,17 +1382,20 @@ class InAppWebViewController {
///Injects an external JavaScript file into the WebView from a defined url. ///Injects an external JavaScript file into the WebView from a defined url.
/// ///
///[scriptHtmlTagAttributes] represents the possible the `<script>` HTML attributes to be set.
///
///**NOTE**: This method shouldn't be called in the [WebView.onWebViewCreated] or [WebView.onLoadStart] events, ///**NOTE**: This method shouldn't be called in the [WebView.onWebViewCreated] or [WebView.onLoadStart] events,
///because, in these events, the [WebView] is not ready to handle it yet. ///because, in these events, the [WebView] is not ready to handle it yet.
///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events ///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events
///where you know the page is ready "enough". ///where you know the page is ready "enough".
Future<void> injectJavascriptFileFromUrl({required String urlFile}) async { Future<void> injectJavascriptFileFromUrl({required String urlFile, ScriptHtmlTagAttributes? scriptHtmlTagAttributes}) async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('urlFile', () => urlFile); args.putIfAbsent('urlFile', () => urlFile);
args.putIfAbsent('scriptHtmlTagAttributes', () => scriptHtmlTagAttributes?.toMap());
await _channel.invokeMethod('injectJavascriptFileFromUrl', args); await _channel.invokeMethod('injectJavascriptFileFromUrl', args);
} }
///Injects a JavaScript file into the WebView from the flutter assets directory. ///Evaluates the content of a JavaScript file into the WebView from the flutter assets directory.
/// ///
///**NOTE**: This method shouldn't be called in the [WebView.onWebViewCreated] or [WebView.onLoadStart] events, ///**NOTE**: This method shouldn't be called in the [WebView.onWebViewCreated] or [WebView.onLoadStart] events,
///because, in these events, the [WebView] is not ready to handle it yet. ///because, in these events, the [WebView] is not ready to handle it yet.
@ -1418,13 +1421,16 @@ class InAppWebViewController {
///Injects an external CSS file into the WebView from a defined url. ///Injects an external CSS file into the WebView from a defined url.
/// ///
///[cssLinkHtmlTagAttributes] represents the possible CSS stylesheet `<link>` HTML attributes to be set.
///
///**NOTE**: This method shouldn't be called in the [WebView.onWebViewCreated] or [WebView.onLoadStart] events, ///**NOTE**: This method shouldn't be called in the [WebView.onWebViewCreated] or [WebView.onLoadStart] events,
///because, in these events, the [WebView] is not ready to handle it yet. ///because, in these events, the [WebView] is not ready to handle it yet.
///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events ///Instead, you should call this method, for example, inside the [WebView.onLoadStop] event or in any other events
///where you know the page is ready "enough". ///where you know the page is ready "enough".
Future<void> injectCSSFileFromUrl({required String urlFile}) async { Future<void> injectCSSFileFromUrl({required String urlFile, CSSLinkHtmlTagAttributes? cssLinkHtmlTagAttributes}) async {
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('urlFile', () => urlFile); args.putIfAbsent('urlFile', () => urlFile);
args.putIfAbsent('cssLinkHtmlTagAttributes', () => cssLinkHtmlTagAttributes?.toMap());
await _channel.invokeMethod('injectCSSFileFromUrl', args); await _channel.invokeMethod('injectCSSFileFromUrl', args);
} }

View File

@ -4914,3 +4914,251 @@ class WebArchiveFormat {
@override @override
int get hashCode => _value.hashCode; int get hashCode => _value.hashCode;
} }
///Class that represents the `crossorigin` content attribute on media elements is a CORS settings attribute.
class CrossOriginHtmlAttribute {
final String _value;
const CrossOriginHtmlAttribute._internal(this._value);
static final Set<CrossOriginHtmlAttribute> values = [
CrossOriginHtmlAttribute.ANONYMOUS,
CrossOriginHtmlAttribute.USE_CREDENTIALS,
].toSet();
static CrossOriginHtmlAttribute? fromValue(String? value) {
if (value != null) {
try {
return CrossOriginHtmlAttribute.values.firstWhere(
(element) => element.toValue() == value);
} catch (e) {
return null;
}
}
return null;
}
String toValue() => _value;
@override
String toString() => _value;
///CORS requests for this element will have the credentials flag set to 'same-origin'.
static const ANONYMOUS = const CrossOriginHtmlAttribute._internal("anonymous");
///CORS requests for this element will have the credentials flag set to 'include'.
static const USE_CREDENTIALS = const CrossOriginHtmlAttribute._internal("use-credentials");
bool operator ==(value) => value == _value;
@override
int get hashCode => _value.hashCode;
}
///Class that represents which Referrer header to send when fetching a resource `<link>` or a `<script>` (or resources fetched by the `<script>`).
///Used by [ScriptHtmlTagAttributes] and [CSSLinkHtmlTagAttributes].
class ReferrerPolicyHtmlAttribute {
final String _value;
const ReferrerPolicyHtmlAttribute._internal(this._value);
static final Set<ReferrerPolicyHtmlAttribute> values = [
ReferrerPolicyHtmlAttribute.NO_REFERRER,
ReferrerPolicyHtmlAttribute.NO_REFERRER_WHEN_DOWNGRADE,
ReferrerPolicyHtmlAttribute.ORIGIN,
ReferrerPolicyHtmlAttribute.ORIGIN_WHEN_CROSS_ORIGIN,
ReferrerPolicyHtmlAttribute.SAME_ORIGIN,
ReferrerPolicyHtmlAttribute.STRICT_ORIGIN,
ReferrerPolicyHtmlAttribute.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
ReferrerPolicyHtmlAttribute.UNSAFE_URL,
].toSet();
static ReferrerPolicyHtmlAttribute? fromValue(String? value) {
if (value != null) {
try {
return ReferrerPolicyHtmlAttribute.values.firstWhere(
(element) => element.toValue() == value);
} catch (e) {
return null;
}
}
return null;
}
String toValue() => _value;
@override
String toString() => _value;
///The Referer header will not be sent.
static const NO_REFERRER = const ReferrerPolicyHtmlAttribute._internal("no-referrer");
///The Referer header will not be sent to origins without TLS (HTTPS).
static const NO_REFERRER_WHEN_DOWNGRADE = const ReferrerPolicyHtmlAttribute._internal("no-referrer-when-downgrade");
///The sent referrer will be limited to the origin of the referring page: its scheme, host, and port.
static const ORIGIN = const ReferrerPolicyHtmlAttribute._internal("origin");
///The referrer sent to other origins will be limited to the scheme, the host, and the port.
///Navigations on the same origin will still include the path.
static const ORIGIN_WHEN_CROSS_ORIGIN = const ReferrerPolicyHtmlAttribute._internal("origin-when-cross-origin");
///A referrer will be sent for same origin, but cross-origin requests will contain no referrer information.
static const SAME_ORIGIN = const ReferrerPolicyHtmlAttribute._internal("same-origin");
///Only send the origin of the document as the referrer when the protocol security level stays the same (e.g. HTTPS -> HTTPS),
///but don't send it to a less secure destination (e.g. HTTPS -> HTTP).
static const STRICT_ORIGIN = const ReferrerPolicyHtmlAttribute._internal("strict-origin");
///Send a full URL when performing a same-origin request, but only send the origin when the protocol security level stays the same (e.g.HTTPS -> HTTPS),
///and send no header to a less secure destination (e.g. HTTPS -> HTTP).
static const STRICT_ORIGIN_WHEN_CROSS_ORIGIN = const ReferrerPolicyHtmlAttribute._internal("strict-origin-when-cross-origin");
///The referrer will include the origin and the path (but not the fragment, password, or username).
///This value is unsafe, because it leaks origins and paths from TLS-protected resources to insecure origins.
static const UNSAFE_URL = const ReferrerPolicyHtmlAttribute._internal("unsafe-url");
bool operator ==(value) => value == _value;
@override
int get hashCode => _value.hashCode;
}
///Class that represents the possible the `<script>` HTML attributes to be set used by [InAppWebViewController.injectJavascriptFileFromUrl].
class ScriptHtmlTagAttributes {
///This attribute indicates the type of script represented. The value of this attribute will be in one of the following categories.
///The default value is `text/javascript`.
String type;
///The HTML [id] attribute is used to specify a unique id for the `<script>` HTML element.
String? id;
///For classic scripts, if the [async] attribute is present,
///then the classic script will be fetched in parallel to parsing and evaluated as soon as it is available.
///
///For module scripts, if the [async] attribute is present then the scripts and all their dependencies will be executed in the defer queue,
///therefore they will get fetched in parallel to parsing and evaluated as soon as they are available.
///
///This attribute allows the elimination of parser-blocking JavaScript where the browser
///would have to load and evaluate scripts before continuing to parse.
///[defer] has a similar effect in this case.
///
///This is a boolean attribute: the presence of a boolean attribute on an element represents the true value,
///and the absence of the attribute represents the false value.
bool? async;
///This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed, but before firing `DOMContentLoaded`.
///
///Scripts with the [defer] attribute will prevent the `DOMContentLoaded` event from firing until the script has loaded and finished evaluating.
///
///Scripts with the [defer] attribute will execute in the order in which they appear in the document.
///
///This attribute allows the elimination of parser-blocking JavaScript where the browser would have to load and evaluate scripts before continuing to parse.
///[async] has a similar effect in this case.
bool? defer;
///Normal script elements pass minimal information to the `window.onerror` for scripts which do not pass the standard CORS checks.
///To allow error logging for sites which use a separate domain for static media, use this attribute.
CrossOriginHtmlAttribute? crossOrigin;
///This attribute contains inline metadata that a user agent can use to verify that a fetched resource has been delivered free of unexpected manipulation.
String? integrity;
///This Boolean attribute is set to indicate that the script should not be executed in browsers that support ES2015 modules in effect,
///this can be used to serve fallback scripts to older browsers that do not support modular JavaScript code.
bool? noModule;
///A cryptographic nonce (number used once) to whitelist scripts in a script-src Content-Security-Policy.
///The server must generate a unique nonce value each time it transmits a policy.
///It is critical to provide a nonce that cannot be guessed as bypassing a resource's policy is otherwise trivial.
String? nonce;
///Indicates which referrer to send when fetching the script, or resources fetched by the script.
ReferrerPolicyHtmlAttribute? referrerPolicy;
ScriptHtmlTagAttributes({this.type = "text/javascript", this.id, this.async, this.defer, this.crossOrigin, this.integrity, this.noModule, this.nonce, this.referrerPolicy});
Map<String, dynamic> toMap() {
return {
"type": this.type,
"id": this.id,
"async": this.async,
"defer": this.defer,
"crossOrigin": this.crossOrigin?.toValue(),
"integrity": this.integrity,
"noModule": this.noModule,
"nonce": this.nonce,
"referrerPolicy": this.referrerPolicy?.toValue(),
};
}
Map<String, dynamic> toJson() {
return this.toMap();
}
@override
String toString() {
return toMap().toString();
}
}
///Class that represents the possible CSS stylesheet `<link>` HTML attributes to be set used by [InAppWebViewController.injectCSSFileFromUrl].
class CSSLinkHtmlTagAttributes {
///The HTML [id] attribute is used to specify a unique id for the `<link>` HTML element.
String? id;
///This attribute specifies the media that the linked resource applies to. Its value must be a media type / media query.
///This attribute is mainly useful when linking to external stylesheets it allows the user agent to pick the best adapted one for the device it runs on.
String? media;
///Normal script elements pass minimal information to the `window.onerror` for scripts which do not pass the standard CORS checks.
///To allow error logging for sites which use a separate domain for static media, use this attribute.
CrossOriginHtmlAttribute? crossOrigin;
///This attribute contains inline metadata that a user agent can use to verify that a fetched resource has been delivered free of unexpected manipulation.
String? integrity;
///Indicates which referrer to send when fetching the script, or resources fetched by the script.
ReferrerPolicyHtmlAttribute? referrerPolicy;
///The [disabled] Boolean attribute indicates whether or not the described stylesheet should be loaded and applied to the document.
///If [disabled] is specified in the HTML when it is loaded, the stylesheet will not be loaded during page load.
///Instead, the stylesheet will be loaded on-demand, if and when the [disabled] attribute is changed to `false` or removed.
///
///Setting the [disabled] property in the DOM causes the stylesheet to be removed from the document's `DocumentOrShadowRoot.styleSheets` list.
bool? disabled;
///Specify alternative style sheets.
bool? alternate;
///The title attribute has special semantics on the `<link>` element.
///When used on a `<link rel="stylesheet">` it defines a preferred or an alternate stylesheet.
///Incorrectly using it may cause the stylesheet to be ignored.
String? title;
CSSLinkHtmlTagAttributes({this.id, this.media, this.crossOrigin, this.integrity, this.referrerPolicy, this.disabled, this.alternate, this.title});
Map<String, dynamic> toMap() {
return {
"id": this.id,
"media": this.media,
"crossOrigin": this.crossOrigin?.toValue(),
"integrity": this.integrity,
"referrerPolicy": this.referrerPolicy?.toValue(),
"disabled": this.disabled,
"alternate": this.alternate,
"title": this.title,
};
}
Map<String, dynamic> toJson() {
return this.toMap();
}
@override
String toString() {
return toMap().toString();
}
}