updated web support
This commit is contained in:
parent
61a439893b
commit
d0657c3b9a
|
@ -23,7 +23,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
||||||
useHybridComposition: true,
|
useHybridComposition: true,
|
||||||
allowsInlineMediaPlayback: true,
|
allowsInlineMediaPlayback: true,
|
||||||
iframeAllow: "camera; microphone",
|
iframeAllow: "camera; microphone",
|
||||||
iframeAllowFullscreen: true
|
iframeAllowFullscreen: true,
|
||||||
|
javaScriptCanOpenWindowsAutomatically: false
|
||||||
);
|
);
|
||||||
|
|
||||||
PullToRefreshController? pullToRefreshController;
|
PullToRefreshController? pullToRefreshController;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
window.addEventListener('load', function (event) {
|
window.addEventListener('load', function (event) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
console.log('test');
|
console.log('test');
|
||||||
|
window.open('https://google.com');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -6,7 +6,8 @@ window.flutter_inappwebview = {
|
||||||
windows: {},
|
windows: {},
|
||||||
isFullscreen: false,
|
isFullscreen: false,
|
||||||
documentTitle: null,
|
documentTitle: null,
|
||||||
prepare: function () {
|
functionMap: {},
|
||||||
|
prepare: function (settings) {
|
||||||
var iframe = document.getElementById(window.flutter_inappwebview.iframeId);
|
var iframe = document.getElementById(window.flutter_inappwebview.iframeId);
|
||||||
|
|
||||||
document.addEventListener('fullscreenchange', function(event) {
|
document.addEventListener('fullscreenchange', function(event) {
|
||||||
|
@ -30,6 +31,14 @@ window.flutter_inappwebview = {
|
||||||
window.flutter_inappwebview.windowAutoincrementId = 0;
|
window.flutter_inappwebview.windowAutoincrementId = 0;
|
||||||
window.flutter_inappwebview.windows = {};
|
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 {
|
try {
|
||||||
var oldLogs = {
|
var oldLogs = {
|
||||||
'log': iframe.contentWindow.console.log,
|
'log': iframe.contentWindow.console.log,
|
||||||
|
@ -58,24 +67,6 @@ window.flutter_inappwebview = {
|
||||||
console.log(e);
|
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 {
|
try {
|
||||||
var originalPushState = iframe.contentWindow.history.pushState;
|
var originalPushState = iframe.contentWindow.history.pushState;
|
||||||
iframe.contentWindow.history.pushState = function (state, unused, url) {
|
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]);
|
window.flutter_inappwebview.nativeCommunication('onUpdateVisitedHistory', window.flutter_inappwebview.viewId, [iframeUrl]);
|
||||||
};
|
};
|
||||||
|
|
||||||
var originalReplaceState = iframe.contentWindow.history.replaceState;
|
var originalReplaceState = iframe.contentWindow.history.replaceState;
|
||||||
iframe.contentWindow.history.replaceState = function (state, unused, url) {
|
iframe.contentWindow.history.replaceState = function (state, unused, url) {
|
||||||
originalReplaceState.call(iframe.contentWindow.history, 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]);
|
window.flutter_inappwebview.nativeCommunication('onUpdateVisitedHistory', window.flutter_inappwebview.viewId, [iframeUrl]);
|
||||||
};
|
};
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var originalOpen = iframe.contentWindow.open;
|
var originalOpen = iframe.contentWindow.open;
|
||||||
iframe.contentWindow.open = function (url, target, windowFeatures) {
|
iframe.contentWindow.open = function (url, target, windowFeatures) {
|
||||||
var newWindow = originalOpen.call(iframe.contentWindow, ...arguments);
|
var newWindow = originalOpen.call(iframe.contentWindow, ...arguments);
|
||||||
|
@ -111,18 +99,13 @@ window.flutter_inappwebview = {
|
||||||
window.flutter_inappwebview.windowAutoincrementId++;
|
window.flutter_inappwebview.windowAutoincrementId++;
|
||||||
window.flutter_inappwebview.windows[windowId] = newWindow;
|
window.flutter_inappwebview.windows[windowId] = newWindow;
|
||||||
window.flutter_inappwebview.nativeCommunication('onCreateWindow', window.flutter_inappwebview.viewId, [windowId, url, target, windowFeatures]).then(function(){}, function(handledByClient) {
|
window.flutter_inappwebview.nativeCommunication('onCreateWindow', window.flutter_inappwebview.viewId, [windowId, url, target, windowFeatures]).then(function(){}, function(handledByClient) {
|
||||||
console.log(handledByClient);
|
|
||||||
if (handledByClient) {
|
if (handledByClient) {
|
||||||
newWindow.close();
|
newWindow.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return newWindow;
|
return newWindow;
|
||||||
};
|
};
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var originalPrint = iframe.contentWindow.print;
|
var originalPrint = iframe.contentWindow.print;
|
||||||
iframe.contentWindow.print = function () {
|
iframe.contentWindow.print = function () {
|
||||||
var iframeUrl = iframe.src;
|
var iframeUrl = iframe.src;
|
||||||
|
@ -134,9 +117,46 @@ window.flutter_inappwebview = {
|
||||||
window.flutter_inappwebview.nativeCommunication('onPrint', window.flutter_inappwebview.viewId, [iframeUrl]);
|
window.flutter_inappwebview.nativeCommunication('onPrint', window.flutter_inappwebview.viewId, [iframeUrl]);
|
||||||
originalPrint.call(iframe.contentWindow);
|
originalPrint.call(iframe.contentWindow);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
var initialTitle = iframe.contentDocument.title;
|
||||||
|
window.flutter_inappwebview.documentTitle = initialTitle;
|
||||||
|
window.flutter_inappwebview.nativeCommunication('onTitleChanged', window.flutter_inappwebview.viewId, [initialTitle]);
|
||||||
|
new MutationObserver(function(mutations) {
|
||||||
|
var title = mutations[0].target.nodeValue;
|
||||||
|
if (title != window.flutter_inappwebview.documentTitle) {
|
||||||
|
window.flutter_inappwebview.documentTitle = title;
|
||||||
|
window.flutter_inappwebview.nativeCommunication('onTitleChanged', window.flutter_inappwebview.viewId, [title]);
|
||||||
|
}
|
||||||
|
}).observe(
|
||||||
|
iframe.contentDocument.querySelector('title'),
|
||||||
|
{ subtree: true, characterData: true, childList: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
var oldPixelRatio = iframe.contentWindow.devicePixelRatio;
|
||||||
|
iframe.contentWindow.addEventListener('resize', function (e) {
|
||||||
|
var newPixelRatio = iframe.contentWindow.devicePixelRatio;
|
||||||
|
if(newPixelRatio !== oldPixelRatio){
|
||||||
|
window.flutter_inappwebview.nativeCommunication('onZoomScaleChanged', window.flutter_inappwebview.viewId, [oldPixelRatio, newPixelRatio]);
|
||||||
|
oldPixelRatio = newPixelRatio;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
iframe.contentWindow.addEventListener('popstate', function (event) {
|
||||||
|
var iframeUrl = iframe.src;
|
||||||
|
try {
|
||||||
|
iframeUrl = iframe.contentWindow.location.href;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
window.flutter_inappwebview.nativeCommunication('onUpdateVisitedHistory', window.flutter_inappwebview.viewId, [iframeUrl]);
|
||||||
|
});
|
||||||
|
|
||||||
iframe.contentWindow.addEventListener('scroll', function (event) {
|
iframe.contentWindow.addEventListener('scroll', function (event) {
|
||||||
var x = 0;
|
var x = 0;
|
||||||
|
@ -157,40 +177,40 @@ window.flutter_inappwebview = {
|
||||||
iframe.contentWindow.addEventListener('blur', function (event) {
|
iframe.contentWindow.addEventListener('blur', function (event) {
|
||||||
window.flutter_inappwebview.nativeCommunication('onWindowBlur', window.flutter_inappwebview.viewId);
|
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]);
|
|
||||||
new MutationObserver(function(mutations) {
|
|
||||||
var title = mutations[0].target.nodeValue;
|
|
||||||
if (title != window.flutter_inappwebview.documentTitle) {
|
|
||||||
window.flutter_inappwebview.documentTitle = title;
|
|
||||||
window.flutter_inappwebview.nativeCommunication('onTitleChanged', window.flutter_inappwebview.viewId, [title]);
|
|
||||||
}
|
|
||||||
}).observe(
|
|
||||||
iframe.contentDocument.querySelector('title'),
|
|
||||||
{ subtree: true, characterData: true, childList: true }
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var oldPixelRatio = iframe.contentWindow.devicePixelRatio;
|
if (!settings.javaScriptCanOpenWindowsAutomatically) {
|
||||||
iframe.contentWindow.addEventListener('resize', function (e) {
|
iframe.contentWindow.open = function () {
|
||||||
var newPixelRatio = iframe.contentWindow.devicePixelRatio;
|
throw new Error('JavaScript cannot open windows automatically');
|
||||||
if(newPixelRatio !== oldPixelRatio){
|
};
|
||||||
window.flutter_inappwebview.nativeCommunication('onZoomScaleChanged', window.flutter_inappwebview.viewId, [oldPixelRatio, newPixelRatio]);
|
|
||||||
oldPixelRatio = newPixelRatio;
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(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 () {
|
reload: function () {
|
||||||
var iframe = window.flutter_inappwebview.iframe;
|
var iframe = window.flutter_inappwebview.iframe;
|
||||||
if (iframe != null && iframe.contentWindow != null) {
|
if (iframe != null && iframe.contentWindow != null) {
|
||||||
|
@ -237,10 +257,8 @@ window.flutter_inappwebview = {
|
||||||
var result = null;
|
var result = null;
|
||||||
if (iframe != null) {
|
if (iframe != null) {
|
||||||
try {
|
try {
|
||||||
result = iframe.contentWindow.eval(source);
|
result = JSON.stringify(iframe.contentWindow.eval(source));
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1552,7 +1552,7 @@ class InAppWebViewController
|
||||||
|
|
||||||
///Reloads the WebView.
|
///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**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView ([Official API - WebView.reload](https://developer.android.com/reference/android/webkit/WebView#reload()))
|
///- 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.
|
///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**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView ([Official API - WebView.goBack](https://developer.android.com/reference/android/webkit/WebView#goBack()))
|
///- 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))
|
///- 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.
|
///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**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView ([Official API - WebView.goForward](https://developer.android.com/reference/android/webkit/WebView#goForward()))
|
///- 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))
|
///- 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.
|
///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**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView ([Official API - WebView.goBackOrForward](https://developer.android.com/reference/android/webkit/WebView#goBackOrForward(int)))
|
///- 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))
|
///- 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.
|
///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**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView
|
///- Android native WebView
|
||||||
///- iOS
|
///- iOS
|
||||||
|
@ -1654,9 +1662,12 @@ class InAppWebViewController
|
||||||
|
|
||||||
///Stops the WebView from loading.
|
///Stops the WebView from loading.
|
||||||
///
|
///
|
||||||
|
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
|
||||||
|
///
|
||||||
///**Supported Platforms/Implementations**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView ([Official API - WebView.stopLoading](https://developer.android.com/reference/android/webkit/WebView#stopLoading()))
|
///- 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))
|
///- 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 {
|
Future<void> stopLoading() async {
|
||||||
Map<String, dynamic> args = <String, dynamic>{};
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
await _channel.invokeMethod('stopLoading', args);
|
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
|
///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".
|
||||||
///
|
///
|
||||||
|
///**NOTE for Web**: this method will have effect only if the iframe has the same origin.
|
||||||
|
///
|
||||||
///**Supported Platforms/Implementations**:
|
///**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)))
|
///- 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))
|
///- 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('source', () => source);
|
||||||
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
args.putIfAbsent('contentWorld', () => contentWorld?.toMap());
|
||||||
var data = await _channel.invokeMethod('evaluateJavascript', args);
|
var data = await _channel.invokeMethod('evaluateJavascript', args);
|
||||||
if (data != null && defaultTargetPlatform == TargetPlatform.android) {
|
if (data != null && (defaultTargetPlatform == TargetPlatform.android || kIsWeb)) {
|
||||||
try {
|
try {
|
||||||
// try to json decode the data coming from JavaScript
|
// try to json decode the data coming from JavaScript
|
||||||
// otherwise return it as it is.
|
// otherwise return it as it is.
|
||||||
|
|
|
@ -87,13 +87,17 @@ class InAppWebViewSettings
|
||||||
///**Supported Platforms/Implementations**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView
|
///- Android native WebView
|
||||||
///- iOS
|
///- iOS
|
||||||
|
///- Web
|
||||||
bool javaScriptEnabled;
|
bool javaScriptEnabled;
|
||||||
|
|
||||||
///Set to `true` to allow JavaScript open windows without user interaction. The default value is `false`.
|
///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**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Android native WebView
|
///- Android native WebView
|
||||||
///- iOS
|
///- iOS
|
||||||
|
///- Web
|
||||||
bool javaScriptCanOpenWindowsAutomatically;
|
bool javaScriptCanOpenWindowsAutomatically;
|
||||||
|
|
||||||
///Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`.
|
///Set to `true` to prevent HTML5 audio or video from autoplaying. The default value is `true`.
|
||||||
|
@ -995,31 +999,31 @@ class InAppWebViewSettings
|
||||||
///- iOS
|
///- iOS
|
||||||
bool upgradeKnownHostsToHTTPS;
|
bool upgradeKnownHostsToHTTPS;
|
||||||
|
|
||||||
///Specifies a feature policy for the iframe. A list of origins the frame is allowed to display content from.
|
///Specifies a feature policy for the `<iframe>`.
|
||||||
///This attribute also accepts the values `self` and `src` which represent the origin in the iframe's src attribute.
|
///The policy defines what features are available to the `<iframe>` based on the origin of the request
|
||||||
///The default value is `src`.
|
///(e.g. access to the microphone, camera, battery, web-share API, etc.).
|
||||||
///
|
///
|
||||||
///**Supported Platforms/Implementations**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Web
|
///- Web
|
||||||
String? iframeAllow;
|
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**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Web
|
///- Web
|
||||||
bool? iframeAllowFullscreen;
|
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**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Web
|
///- Web
|
||||||
String? iframeSandox;
|
List<Sandbox>? iframeSandbox;
|
||||||
|
|
||||||
///A string that reflects the `referrerpolicy` HTML attribute indicating which referrer to use when fetching the linked resource.
|
///A string that reflects the `referrerpolicy` HTML attribute indicating which referrer to use when fetching the linked resource.
|
||||||
///
|
///
|
||||||
///**Supported Platforms/Implementations**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Web
|
///- Web
|
||||||
String? iframeReferrerPolicy;
|
ReferrerPolicy? iframeReferrerPolicy;
|
||||||
|
|
||||||
///A string that reflects the `name` HTML attribute, containing a name by which to refer to the frame.
|
///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
|
///- Web
|
||||||
String? iframeName;
|
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**:
|
///**Supported Platforms/Implementations**:
|
||||||
///- Web
|
///- Web
|
||||||
|
@ -1155,7 +1159,7 @@ class InAppWebViewSettings
|
||||||
this.upgradeKnownHostsToHTTPS = true,
|
this.upgradeKnownHostsToHTTPS = true,
|
||||||
this.iframeAllow,
|
this.iframeAllow,
|
||||||
this.iframeAllowFullscreen,
|
this.iframeAllowFullscreen,
|
||||||
this.iframeSandox,
|
this.iframeSandbox,
|
||||||
this.iframeReferrerPolicy,
|
this.iframeReferrerPolicy,
|
||||||
this.iframeName,
|
this.iframeName,
|
||||||
this.iframeCsp,}) {
|
this.iframeCsp,}) {
|
||||||
|
@ -1303,7 +1307,7 @@ class InAppWebViewSettings
|
||||||
"upgradeKnownHostsToHTTPS": upgradeKnownHostsToHTTPS,
|
"upgradeKnownHostsToHTTPS": upgradeKnownHostsToHTTPS,
|
||||||
"iframeAllow": iframeAllow,
|
"iframeAllow": iframeAllow,
|
||||||
"iframeAllowFullscreen": iframeAllowFullscreen,
|
"iframeAllowFullscreen": iframeAllowFullscreen,
|
||||||
"iframeSandox": iframeSandox,
|
"iframeSandbox": iframeSandbox?.map((e) => e.toValue()),
|
||||||
"iframeReferrerPolicy": iframeReferrerPolicy,
|
"iframeReferrerPolicy": iframeReferrerPolicy,
|
||||||
"iframeName": iframeName,
|
"iframeName": iframeName,
|
||||||
"iframeCsp": iframeCsp,
|
"iframeCsp": iframeCsp,
|
||||||
|
@ -1366,8 +1370,9 @@ class InAppWebViewSettings
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
settings.iframeAllow = map["iframeAllow"];
|
settings.iframeAllow = map["iframeAllow"];
|
||||||
settings.iframeAllowFullscreen = map["iframeAllowFullscreen"];
|
settings.iframeAllowFullscreen = map["iframeAllowFullscreen"];
|
||||||
settings.iframeSandox = map["iframeSandox"];
|
settings.iframeSandbox = (map["iframeSandbox"] as List<String?>?)
|
||||||
settings.iframeReferrerPolicy = map["iframeReferrerPolicy"];
|
?.map((e) => Sandbox.fromValue(e)) as List<Sandbox>?;
|
||||||
|
settings.iframeReferrerPolicy = ReferrerPolicy.fromValue(map["iframeReferrerPolicy"]);
|
||||||
settings.iframeName = map["iframeName"];
|
settings.iframeName = map["iframeName"];
|
||||||
settings.iframeCsp = map["iframeCsp"];
|
settings.iframeCsp = map["iframeCsp"];
|
||||||
}
|
}
|
||||||
|
|
|
@ -10724,3 +10724,97 @@ class MediaPlaybackState {
|
||||||
@override
|
@override
|
||||||
int get hashCode => _value.hashCode;
|
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() {
|
void prepare() {
|
||||||
settings = initialSettings ?? InAppWebViewSettings();
|
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.allow = settings.iframeAllow ?? iframe.allow;
|
||||||
iframe.allowFullscreen = settings.iframeAllowFullscreen ?? iframe.allowFullscreen;
|
iframe.allowFullscreen = settings.iframeAllowFullscreen ?? iframe.allowFullscreen;
|
||||||
if (settings.iframeSandox != null) {
|
iframe.referrerPolicy = settings.iframeReferrerPolicy?.toValue() ?? iframe.referrerPolicy;
|
||||||
iframe.setAttribute("sandbox", settings.iframeSandox ?? "");
|
|
||||||
}
|
|
||||||
iframe.referrerPolicy = settings.iframeReferrerPolicy ?? iframe.referrerPolicy;
|
|
||||||
iframe.name = settings.iframeName ?? iframe.name;
|
iframe.name = settings.iframeName ?? iframe.name;
|
||||||
iframe.csp = settings.iframeCsp ?? iframe.csp;
|
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 {
|
void makeInitialLoad() async {
|
||||||
|
@ -179,18 +191,39 @@ class InAppWebViewWebElement {
|
||||||
bridgeJsObject.callMethod("stopLoading");
|
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 {
|
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) {
|
if (settings.iframeAllow != newSettings.iframeAllow) {
|
||||||
iframe.allow = newSettings.iframeAllow;
|
iframe.allow = newSettings.iframeAllow;
|
||||||
}
|
}
|
||||||
if (settings.iframeAllowFullscreen != newSettings.iframeAllowFullscreen) {
|
if (settings.iframeAllowFullscreen != newSettings.iframeAllowFullscreen) {
|
||||||
iframe.allowFullscreen = newSettings.iframeAllowFullscreen;
|
iframe.allowFullscreen = newSettings.iframeAllowFullscreen;
|
||||||
}
|
}
|
||||||
if (settings.iframeSandox != newSettings.iframeSandox) {
|
|
||||||
iframe.setAttribute("sandbox", newSettings.iframeSandox ?? "");
|
|
||||||
}
|
|
||||||
if (settings.iframeReferrerPolicy != newSettings.iframeReferrerPolicy) {
|
if (settings.iframeReferrerPolicy != newSettings.iframeReferrerPolicy) {
|
||||||
iframe.referrerPolicy = newSettings.iframeReferrerPolicy;
|
iframe.referrerPolicy = newSettings.iframeReferrerPolicy?.toValue();
|
||||||
}
|
}
|
||||||
if (settings.iframeName != newSettings.iframeName) {
|
if (settings.iframeName != newSettings.iframeName) {
|
||||||
iframe.name = newSettings.iframeName;
|
iframe.name = newSettings.iframeName;
|
||||||
|
@ -198,6 +231,20 @@ class InAppWebViewWebElement {
|
||||||
if (settings.iframeCsp != newSettings.iframeCsp) {
|
if (settings.iframeCsp != newSettings.iframeCsp) {
|
||||||
iframe.csp = 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;
|
settings = newSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue