updated web support
This commit is contained in:
parent
61a439893b
commit
d0657c3b9a
|
@ -23,7 +23,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
|||
useHybridComposition: true,
|
||||
allowsInlineMediaPlayback: true,
|
||||
iframeAllow: "camera; microphone",
|
||||
iframeAllowFullscreen: true
|
||||
iframeAllowFullscreen: true,
|
||||
javaScriptCanOpenWindowsAutomatically: false
|
||||
);
|
||||
|
||||
PullToRefreshController? pullToRefreshController;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
window.addEventListener('load', function (event) {
|
||||
setTimeout(function () {
|
||||
console.log('test');
|
||||
window.open('https://google.com');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -6,7 +6,8 @@ window.flutter_inappwebview = {
|
|||
windows: {},
|
||||
isFullscreen: false,
|
||||
documentTitle: null,
|
||||
prepare: function () {
|
||||
functionMap: {},
|
||||
prepare: function (settings) {
|
||||
var iframe = document.getElementById(window.flutter_inappwebview.iframeId);
|
||||
|
||||
document.addEventListener('fullscreenchange', function(event) {
|
||||
|
@ -30,6 +31,14 @@ window.flutter_inappwebview = {
|
|||
window.flutter_inappwebview.windowAutoincrementId = 0;
|
||||
window.flutter_inappwebview.windows = {};
|
||||
|
||||
var url = iframe.src;
|
||||
try {
|
||||
url = iframe.contentWindow.location.href;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
window.flutter_inappwebview.nativeCommunication('onLoadStart', window.flutter_inappwebview.viewId, [url]);
|
||||
|
||||
try {
|
||||
var oldLogs = {
|
||||
'log': iframe.contentWindow.console.log,
|
||||
|
@ -58,24 +67,6 @@ window.flutter_inappwebview = {
|
|||
console.log(e);
|
||||
}
|
||||
|
||||
var url = iframe.src;
|
||||
try {
|
||||
url = iframe.contentWindow.location.href;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
window.flutter_inappwebview.nativeCommunication('onLoadStart', window.flutter_inappwebview.viewId, [url]);
|
||||
window.flutter_inappwebview.nativeCommunication('onLoadStop', window.flutter_inappwebview.viewId, [url]);
|
||||
|
||||
iframe.contentWindow.addEventListener('popstate', function (event) {
|
||||
var iframeUrl = iframe.src;
|
||||
try {
|
||||
iframeUrl = iframe.contentWindow.location.href;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
window.flutter_inappwebview.nativeCommunication('onUpdateVisitedHistory', window.flutter_inappwebview.viewId, [iframeUrl]);
|
||||
});
|
||||
try {
|
||||
var originalPushState = iframe.contentWindow.history.pushState;
|
||||
iframe.contentWindow.history.pushState = function (state, unused, url) {
|
||||
|
@ -88,6 +79,7 @@ window.flutter_inappwebview = {
|
|||
}
|
||||
window.flutter_inappwebview.nativeCommunication('onUpdateVisitedHistory', window.flutter_inappwebview.viewId, [iframeUrl]);
|
||||
};
|
||||
|
||||
var originalReplaceState = iframe.contentWindow.history.replaceState;
|
||||
iframe.contentWindow.history.replaceState = function (state, unused, url) {
|
||||
originalReplaceState.call(iframe.contentWindow.history, state, unused, url);
|
||||
|
@ -99,11 +91,7 @@ window.flutter_inappwebview = {
|
|||
}
|
||||
window.flutter_inappwebview.nativeCommunication('onUpdateVisitedHistory', window.flutter_inappwebview.viewId, [iframeUrl]);
|
||||
};
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
try {
|
||||
var originalOpen = iframe.contentWindow.open;
|
||||
iframe.contentWindow.open = function (url, target, windowFeatures) {
|
||||
var newWindow = originalOpen.call(iframe.contentWindow, ...arguments);
|
||||
|
@ -111,18 +99,13 @@ window.flutter_inappwebview = {
|
|||
window.flutter_inappwebview.windowAutoincrementId++;
|
||||
window.flutter_inappwebview.windows[windowId] = newWindow;
|
||||
window.flutter_inappwebview.nativeCommunication('onCreateWindow', window.flutter_inappwebview.viewId, [windowId, url, target, windowFeatures]).then(function(){}, function(handledByClient) {
|
||||
console.log(handledByClient);
|
||||
if (handledByClient) {
|
||||
newWindow.close();
|
||||
}
|
||||
});
|
||||
return newWindow;
|
||||
};
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
try {
|
||||
var originalPrint = iframe.contentWindow.print;
|
||||
iframe.contentWindow.print = function () {
|
||||
var iframeUrl = iframe.src;
|
||||
|
@ -134,31 +117,14 @@ window.flutter_inappwebview = {
|
|||
window.flutter_inappwebview.nativeCommunication('onPrint', window.flutter_inappwebview.viewId, [iframeUrl]);
|
||||
originalPrint.call(iframe.contentWindow);
|
||||
};
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
iframe.contentWindow.addEventListener('scroll', function (event) {
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
try {
|
||||
x = iframe.contentWindow.scrollX;
|
||||
y = iframe.contentWindow.scrollY;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
window.flutter_inappwebview.functionMap = {
|
||||
"window.open": iframe.contentWindow.open,
|
||||
"window.print": iframe.contentWindow.print,
|
||||
"window.history.pushState": iframe.contentWindow.history.pushState,
|
||||
"window.history.replaceState": iframe.contentWindow.history.replaceState,
|
||||
}
|
||||
window.flutter_inappwebview.nativeCommunication('onScrollChanged', window.flutter_inappwebview.viewId, [x, y]);
|
||||
});
|
||||
|
||||
iframe.contentWindow.addEventListener('focus', function (event) {
|
||||
window.flutter_inappwebview.nativeCommunication('onWindowFocus', window.flutter_inappwebview.viewId);
|
||||
});
|
||||
|
||||
iframe.contentWindow.addEventListener('blur', function (event) {
|
||||
window.flutter_inappwebview.nativeCommunication('onWindowBlur', window.flutter_inappwebview.viewId);
|
||||
});
|
||||
|
||||
try {
|
||||
var initialTitle = iframe.contentDocument.title;
|
||||
window.flutter_inappwebview.documentTitle = initialTitle;
|
||||
window.flutter_inappwebview.nativeCommunication('onTitleChanged', window.flutter_inappwebview.viewId, [initialTitle]);
|
||||
|
@ -172,11 +138,7 @@ window.flutter_inappwebview = {
|
|||
iframe.contentDocument.querySelector('title'),
|
||||
{ subtree: true, characterData: true, childList: true }
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
try {
|
||||
var oldPixelRatio = iframe.contentWindow.devicePixelRatio;
|
||||
iframe.contentWindow.addEventListener('resize', function (e) {
|
||||
var newPixelRatio = iframe.contentWindow.devicePixelRatio;
|
||||
|
@ -185,12 +147,70 @@ window.flutter_inappwebview = {
|
|||
oldPixelRatio = newPixelRatio;
|
||||
}
|
||||
});
|
||||
|
||||
iframe.contentWindow.addEventListener('popstate', function (event) {
|
||||
var iframeUrl = iframe.src;
|
||||
try {
|
||||
iframeUrl = iframe.contentWindow.location.href;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
window.flutter_inappwebview.nativeCommunication('onUpdateVisitedHistory', window.flutter_inappwebview.viewId, [iframeUrl]);
|
||||
});
|
||||
|
||||
iframe.contentWindow.addEventListener('scroll', function (event) {
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
try {
|
||||
x = iframe.contentWindow.scrollX;
|
||||
y = iframe.contentWindow.scrollY;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
window.flutter_inappwebview.nativeCommunication('onScrollChanged', window.flutter_inappwebview.viewId, [x, y]);
|
||||
});
|
||||
|
||||
iframe.contentWindow.addEventListener('focus', function (event) {
|
||||
window.flutter_inappwebview.nativeCommunication('onWindowFocus', window.flutter_inappwebview.viewId);
|
||||
});
|
||||
|
||||
iframe.contentWindow.addEventListener('blur', function (event) {
|
||||
window.flutter_inappwebview.nativeCommunication('onWindowBlur', window.flutter_inappwebview.viewId);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!settings.javaScriptCanOpenWindowsAutomatically) {
|
||||
iframe.contentWindow.open = function () {
|
||||
throw new Error('JavaScript cannot open windows automatically');
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
window.flutter_inappwebview.nativeCommunication('onLoadStop', window.flutter_inappwebview.viewId, [url]);
|
||||
});
|
||||
}
|
||||
},
|
||||
setSettings: function (settings, newSettings) {
|
||||
var iframe = window.flutter_inappwebview.iframe;
|
||||
try {
|
||||
if (settings.javaScriptCanOpenWindowsAutomatically != newSettings.javaScriptCanOpenWindowsAutomatically) {
|
||||
if (!newSettings.javaScriptCanOpenWindowsAutomatically) {
|
||||
iframe.contentWindow.open = function () {
|
||||
throw new Error('JavaScript cannot open windows automatically');
|
||||
};
|
||||
} else {
|
||||
iframe.contentWindow.open = window.flutter_inappwebview.functionMap["window.open"];
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
},
|
||||
reload: function () {
|
||||
var iframe = window.flutter_inappwebview.iframe;
|
||||
if (iframe != null && iframe.contentWindow != null) {
|
||||
|
@ -237,10 +257,8 @@ window.flutter_inappwebview = {
|
|||
var result = null;
|
||||
if (iframe != null) {
|
||||
try {
|
||||
result = iframe.contentWindow.eval(source);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
result = JSON.stringify(iframe.contentWindow.eval(source));
|
||||
} catch (e) {}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
|
|
@ -1552,7 +1552,7 @@ class InAppWebViewController
|
|||
|
||||
///Reloads the WebView.
|
||||
///
|
||||
///**NOTE**: on Web, if `window.location.reload()` is not accessible inside the iframe, it will reload using the iframe `src` attribute.
|
||||
///**NOTE for Web**: if `window.location.reload()` is not accessible inside the iframe, it will reload using the iframe `src` attribute.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.reload](https://developer.android.com/reference/android/webkit/WebView#reload()))
|
||||
|
@ -1565,6 +1565,8 @@ class InAppWebViewController
|
|||
|
||||
///Goes back in the history of the WebView.
|
||||
///
|
||||
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.goBack](https://developer.android.com/reference/android/webkit/WebView#goBack()))
|
||||
///- iOS ([Official API - WKWebView.goBack](https://developer.apple.com/documentation/webkit/wkwebview/1414952-goback))
|
||||
|
@ -1586,6 +1588,8 @@ class InAppWebViewController
|
|||
|
||||
///Goes forward in the history of the WebView.
|
||||
///
|
||||
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.goForward](https://developer.android.com/reference/android/webkit/WebView#goForward()))
|
||||
///- iOS ([Official API - WKWebView.goForward](https://developer.apple.com/documentation/webkit/wkwebview/1414993-goforward))
|
||||
|
@ -1607,6 +1611,8 @@ class InAppWebViewController
|
|||
|
||||
///Goes to the history item that is the number of steps away from the current item. Steps is negative if backward and positive if forward.
|
||||
///
|
||||
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.goBackOrForward](https://developer.android.com/reference/android/webkit/WebView#goBackOrForward(int)))
|
||||
///- iOS ([Official API - WKWebView.go](https://developer.apple.com/documentation/webkit/wkwebview/1414991-go))
|
||||
|
@ -1630,6 +1636,8 @@ class InAppWebViewController
|
|||
|
||||
///Navigates to a [WebHistoryItem] from the back-forward [WebHistory.list] and sets it as the current item.
|
||||
///
|
||||
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
|
@ -1654,9 +1662,12 @@ class InAppWebViewController
|
|||
|
||||
///Stops the WebView from loading.
|
||||
///
|
||||
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.stopLoading](https://developer.android.com/reference/android/webkit/WebView#stopLoading()))
|
||||
///- iOS ([Official API - WKWebView.stopLoading](https://developer.apple.com/documentation/webkit/wkwebview/1414981-stoploading))
|
||||
///- Web ([Official API - Window.stop](https://developer.mozilla.org/en-US/docs/Web/API/Window/stop))
|
||||
Future<void> stopLoading() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('stopLoading', args);
|
||||
|
@ -1677,6 +1688,8 @@ class InAppWebViewController
|
|||
///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".
|
||||
///
|
||||
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView ([Official API - WebView.evaluateJavascript](https://developer.android.com/reference/android/webkit/WebView#evaluateJavascript(java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)))
|
||||
///- iOS ([Official API - WKWebView.evaluateJavascript](https://developer.apple.com/documentation/webkit/wkwebview/3656442-evaluatejavascript))
|
||||
|
@ -1687,7 +1700,7 @@ class InAppWebViewController
|
|||
args.putIfAbsent('source', () => source);
|
||||
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
||||
var data = await _channel.invokeMethod('evaluateJavascript', args);
|
||||
if (data != null && defaultTargetPlatform == TargetPlatform.android) {
|
||||
if (data != null && (defaultTargetPlatform == TargetPlatform.android || kIsWeb)) {
|
||||
try {
|
||||
// try to json decode the data coming from JavaScript
|
||||
// otherwise return it as it is.
|
||||
|
|
|
@ -87,13 +87,17 @@ class InAppWebViewSettings
|
|||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
///- Web
|
||||
bool javaScriptEnabled;
|
||||
|
||||
///Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`.
|
||||
///
|
||||
///**NOTE for Web**: this setting will have effect only if the iframe has the same origin.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Android native WebView
|
||||
///- iOS
|
||||
///- Web
|
||||
bool javaScriptCanOpenWindowsAutomatically;
|
||||
|
||||
///Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`.
|
||||
|
@ -995,31 +999,31 @@ class InAppWebViewSettings
|
|||
///- iOS
|
||||
bool upgradeKnownHostsToHTTPS;
|
||||
|
||||
///Specifies a feature policy for the iframe. A list of origins the frame is allowed to display content from.
|
||||
///This attribute also accepts the values `self` and `src` which represent the origin in the iframe's src attribute.
|
||||
///The default value is `src`.
|
||||
///Specifies a feature policy for the `<iframe>`.
|
||||
///The policy defines what features are available to the `<iframe>` based on the origin of the request
|
||||
///(e.g. access to the microphone, camera, battery, web-share API, etc.).
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Web
|
||||
String? iframeAllow;
|
||||
|
||||
///A boolean value indicating whether the inline frame is willing to be placed into full screen mode.
|
||||
///Set to true if the `<iframe>` can activate fullscreen mode by calling the `requestFullscreen()` method.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Web
|
||||
bool? iframeAllowFullscreen;
|
||||
|
||||
///A DOMTokenList that reflects the sandbox HTML attribute, indicating extra restrictions on the behavior of the nested content.
|
||||
///Applies extra restrictions to the content in the frame.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Web
|
||||
String? iframeSandox;
|
||||
List<Sandbox>? iframeSandbox;
|
||||
|
||||
///A string that reflects the `referrerpolicy` HTML attribute indicating which referrer to use when fetching the linked resource.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Web
|
||||
String? iframeReferrerPolicy;
|
||||
ReferrerPolicy? iframeReferrerPolicy;
|
||||
|
||||
///A string that reflects the `name` HTML attribute, containing a name by which to refer to the frame.
|
||||
///
|
||||
|
@ -1027,7 +1031,7 @@ class InAppWebViewSettings
|
|||
///- Web
|
||||
String? iframeName;
|
||||
|
||||
///Specifies the Content Security Policy that an embedded document must agree to enforce upon itself.
|
||||
///A Content Security Policy enforced for the embedded resource.
|
||||
///
|
||||
///**Supported Platforms/Implementations**:
|
||||
///- Web
|
||||
|
@ -1155,7 +1159,7 @@ class InAppWebViewSettings
|
|||
this.upgradeKnownHostsToHTTPS = true,
|
||||
this.iframeAllow,
|
||||
this.iframeAllowFullscreen,
|
||||
this.iframeSandox,
|
||||
this.iframeSandbox,
|
||||
this.iframeReferrerPolicy,
|
||||
this.iframeName,
|
||||
this.iframeCsp,}) {
|
||||
|
@ -1303,7 +1307,7 @@ class InAppWebViewSettings
|
|||
"upgradeKnownHostsToHTTPS": upgradeKnownHostsToHTTPS,
|
||||
"iframeAllow": iframeAllow,
|
||||
"iframeAllowFullscreen": iframeAllowFullscreen,
|
||||
"iframeSandox": iframeSandox,
|
||||
"iframeSandbox": iframeSandbox?.map((e) => e.toValue()),
|
||||
"iframeReferrerPolicy": iframeReferrerPolicy,
|
||||
"iframeName": iframeName,
|
||||
"iframeCsp": iframeCsp,
|
||||
|
@ -1366,8 +1370,9 @@ class InAppWebViewSettings
|
|||
if (kIsWeb) {
|
||||
settings.iframeAllow = map["iframeAllow"];
|
||||
settings.iframeAllowFullscreen = map["iframeAllowFullscreen"];
|
||||
settings.iframeSandox = map["iframeSandox"];
|
||||
settings.iframeReferrerPolicy = map["iframeReferrerPolicy"];
|
||||
settings.iframeSandbox = (map["iframeSandbox"] as List<String?>?)
|
||||
?.map((e) => Sandbox.fromValue(e)) as List<Sandbox>?;
|
||||
settings.iframeReferrerPolicy = ReferrerPolicy.fromValue(map["iframeReferrerPolicy"]);
|
||||
settings.iframeName = map["iframeName"];
|
||||
settings.iframeCsp = map["iframeCsp"];
|
||||
}
|
||||
|
|
|
@ -10724,3 +10724,97 @@ class MediaPlaybackState {
|
|||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
///Class that describes what to allow in the iframe.
|
||||
class Sandbox {
|
||||
final String? _value;
|
||||
|
||||
const Sandbox._internal(this._value);
|
||||
|
||||
static final Set<Sandbox> values = [
|
||||
Sandbox.ALLOW_DOWNLOADS,
|
||||
Sandbox.ALLOW_FORMS,
|
||||
Sandbox.ALLOW_MODALS,
|
||||
Sandbox.ALLOW_ORIENTATION_LOCK,
|
||||
Sandbox.ALLOW_POINTER_LOCK,
|
||||
Sandbox.ALLOW_POPUPS,
|
||||
Sandbox.ALLOW_POPUPS_TO_ESCAPE_SANDBOX,
|
||||
Sandbox.ALLOW_PRESENTATION,
|
||||
Sandbox.ALLOW_SAME_ORIGIN,
|
||||
Sandbox.ALLOW_SCRIPTS,
|
||||
Sandbox.ALLOW_TOP_NAVIGATION,
|
||||
Sandbox.ALLOW_TOP_NAVIGATION_BY_USER_ACTIVATION,
|
||||
].toSet();
|
||||
|
||||
static Sandbox? fromValue(String? value) {
|
||||
if (value == null) {
|
||||
return _ALL;
|
||||
} else if (value == "") {
|
||||
return _NONE;
|
||||
}
|
||||
try {
|
||||
return Sandbox.values
|
||||
.firstWhere((element) => element.toValue() == value);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String? toValue() => _value;
|
||||
|
||||
@override
|
||||
String toString() => _value == null ? "allow-all" : (_value == "" ? "allow-none" : "");
|
||||
|
||||
static const _ALL = const Sandbox._internal(null);
|
||||
static const _NONE = const Sandbox._internal("");
|
||||
|
||||
///Allow all.
|
||||
static const ALLOW_ALL = const [_ALL];
|
||||
|
||||
///Allow none.
|
||||
static const ALLOW_NONE = const [_NONE];
|
||||
|
||||
///Allows for downloads to occur with a gesture from the user.
|
||||
static const ALLOW_DOWNLOADS = const Sandbox._internal("allow-downloads");
|
||||
|
||||
///Allows the resource to submit forms. If this keyword is not used, form submission is blocked.
|
||||
static const ALLOW_FORMS = const Sandbox._internal("allow-forms");
|
||||
|
||||
///Lets the resource open modal windows.
|
||||
static const ALLOW_MODALS = const Sandbox._internal("allow-modals");
|
||||
|
||||
///Lets the resource lock the screen orientation.
|
||||
static const ALLOW_ORIENTATION_LOCK = const Sandbox._internal("allow-orientation-lock");
|
||||
|
||||
///Lets the resource use the Pointer Lock API.
|
||||
static const ALLOW_POINTER_LOCK = const Sandbox._internal("allow-pointer-lock");
|
||||
|
||||
///Allows popups (such as `window.open()`, `target="_blank"`, or `showModalDialog()`).
|
||||
///If this keyword is not used, the popup will silently fail to open.
|
||||
static const ALLOW_POPUPS = const Sandbox._internal("allow-popups");
|
||||
|
||||
///Lets the sandboxed document open new windows without those windows inheriting the sandboxing.
|
||||
///For example, this can safely sandbox an advertisement without forcing the same restrictions upon the page the ad links to.
|
||||
static const ALLOW_POPUPS_TO_ESCAPE_SANDBOX = const Sandbox._internal("allow-popups-to-escape-sandbox");
|
||||
|
||||
///Lets the resource start a presentation session.
|
||||
static const ALLOW_PRESENTATION = const Sandbox._internal("allow-presentation");
|
||||
|
||||
///If this token is not used, the resource is treated as being from a special origin that always fails the
|
||||
///same-origin policy (potentially preventing access to data storage/cookies and some JavaScript APIs).
|
||||
static const ALLOW_SAME_ORIGIN = const Sandbox._internal("allow-same-origin");
|
||||
|
||||
///Lets the resource run scripts (but not create popup windows).
|
||||
static const ALLOW_SCRIPTS = const Sandbox._internal("allow-scripts");
|
||||
|
||||
///Lets the resource navigate the top-level browsing context (the one named `_top`).
|
||||
static const ALLOW_TOP_NAVIGATION = const Sandbox._internal("allow-top-navigation");
|
||||
|
||||
///Lets the resource navigate the top-level browsing context, but only if initiated by a user gesture.
|
||||
static const ALLOW_TOP_NAVIGATION_BY_USER_ACTIVATION = const Sandbox._internal("allow-top-navigation-by-user-activation");
|
||||
|
||||
bool operator ==(value) => value == _value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
|
@ -97,16 +97,28 @@ class InAppWebViewWebElement {
|
|||
|
||||
void prepare() {
|
||||
settings = initialSettings ?? InAppWebViewSettings();
|
||||
|
||||
Set<Sandbox> sandbox = Set.from(Sandbox.values);
|
||||
|
||||
if (!settings.javaScriptEnabled) {
|
||||
sandbox.remove(Sandbox.ALLOW_SCRIPTS);
|
||||
}
|
||||
|
||||
iframe.allow = settings.iframeAllow ?? iframe.allow;
|
||||
iframe.allowFullscreen = settings.iframeAllowFullscreen ?? iframe.allowFullscreen;
|
||||
if (settings.iframeSandox != null) {
|
||||
iframe.setAttribute("sandbox", settings.iframeSandox ?? "");
|
||||
}
|
||||
iframe.referrerPolicy = settings.iframeReferrerPolicy ?? iframe.referrerPolicy;
|
||||
iframe.referrerPolicy = settings.iframeReferrerPolicy?.toValue() ?? iframe.referrerPolicy;
|
||||
iframe.name = settings.iframeName ?? iframe.name;
|
||||
iframe.csp = settings.iframeCsp ?? iframe.csp;
|
||||
|
||||
bridgeJsObject.callMethod("prepare");
|
||||
if (settings.iframeSandbox != null && settings.iframeSandbox != Sandbox.ALLOW_ALL) {
|
||||
iframe.setAttribute("sandbox", settings.iframeSandbox!.map((e) => e.toValue()).join(" "));
|
||||
} else if (settings.iframeSandbox == Sandbox.ALLOW_ALL) {
|
||||
iframe.removeAttribute("sandbox");
|
||||
} else if (sandbox != Sandbox.values) {
|
||||
iframe.setAttribute("sandbox", sandbox.map((e) => e.toValue()).join(" "));
|
||||
}
|
||||
|
||||
bridgeJsObject.callMethod("prepare", [js.JsObject.jsify(settings.toMap())]);
|
||||
}
|
||||
|
||||
void makeInitialLoad() async {
|
||||
|
@ -179,18 +191,39 @@ class InAppWebViewWebElement {
|
|||
bridgeJsObject.callMethod("stopLoading");
|
||||
}
|
||||
|
||||
Set<Sandbox> getSandbox() {
|
||||
var sandbox = iframe.sandbox;
|
||||
Set<Sandbox> values = Set();
|
||||
if (sandbox != null) {
|
||||
for (int i = 0; i < sandbox.length; i++) {
|
||||
var token = Sandbox.fromValue(sandbox.item(i));
|
||||
if (token != null) {
|
||||
values.add(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
return values.isEmpty ? Set.from(Sandbox.values) : values;
|
||||
}
|
||||
|
||||
Future<void> setSettings(InAppWebViewSettings newSettings) async {
|
||||
Set<Sandbox> sandbox = getSandbox();
|
||||
|
||||
if (settings.javaScriptEnabled != newSettings.javaScriptEnabled) {
|
||||
if (!newSettings.javaScriptEnabled) {
|
||||
sandbox.remove(Sandbox.ALLOW_SCRIPTS);
|
||||
} else {
|
||||
sandbox.add(Sandbox.ALLOW_SCRIPTS);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.iframeAllow != newSettings.iframeAllow) {
|
||||
iframe.allow = newSettings.iframeAllow;
|
||||
}
|
||||
if (settings.iframeAllowFullscreen != newSettings.iframeAllowFullscreen) {
|
||||
iframe.allowFullscreen = newSettings.iframeAllowFullscreen;
|
||||
}
|
||||
if (settings.iframeSandox != newSettings.iframeSandox) {
|
||||
iframe.setAttribute("sandbox", newSettings.iframeSandox ?? "");
|
||||
}
|
||||
if (settings.iframeReferrerPolicy != newSettings.iframeReferrerPolicy) {
|
||||
iframe.referrerPolicy = newSettings.iframeReferrerPolicy;
|
||||
iframe.referrerPolicy = newSettings.iframeReferrerPolicy?.toValue();
|
||||
}
|
||||
if (settings.iframeName != newSettings.iframeName) {
|
||||
iframe.name = newSettings.iframeName;
|
||||
|
@ -198,6 +231,20 @@ class InAppWebViewWebElement {
|
|||
if (settings.iframeCsp != newSettings.iframeCsp) {
|
||||
iframe.csp = newSettings.iframeCsp;
|
||||
}
|
||||
|
||||
if (settings.iframeSandbox != newSettings.iframeSandbox) {
|
||||
var sandbox = newSettings.iframeSandbox;
|
||||
if (sandbox != null && sandbox != Sandbox.ALLOW_ALL) {
|
||||
iframe.setAttribute("sandbox", sandbox.map((e) => e.toValue()).join(" "));
|
||||
} else if (sandbox == Sandbox.ALLOW_ALL) {
|
||||
iframe.removeAttribute("sandbox");
|
||||
}
|
||||
} else if (sandbox != Sandbox.values) {
|
||||
iframe.setAttribute("sandbox", sandbox.map((e) => e.toValue()).join(" "));
|
||||
}
|
||||
|
||||
bridgeJsObject.callMethod("setSettings", [js.JsObject.jsify(settings.toMap()), js.JsObject.jsify(newSettings.toMap())]);
|
||||
|
||||
settings = newSettings;
|
||||
}
|
||||
|
||||
|
@ -326,4 +373,4 @@ class InAppWebViewWebElement {
|
|||
|
||||
await _channel.invokeMethod("onZoomScaleChanged", obj);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue