问题原因:
Chrome的新版本删除了对 iframe跨域 origin中 alert()
、confirm()
和 prompt()
的支持。
相关文档:https://www.chromestatus.com/feature/5148698084376576
解决方法:
通过Window.postMessage()
从iframe发送消息到父页面,并通过父页面显示对话框。
实现代码:
https://example-a.com/parent.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Parent (domain A)</title>
<script type="text/javascript" src="dialogs.js"></script>
</head>
<body>
<h1>Parent (domain A)</h1>
<iframe src="https://example-b.com/iframe.html">
</body>
</html>
https://example-b.com/iframe.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Iframe (domain B)</title>
<script type="text/javascript" src="dialogs.js"></script>
</head>
<body>
<h1>Iframe (domain B)</h1>
<script type="text/javascript">
alert('alert() forwarded from iframe.html');
confirm('confirm() forwarded from iframe.html via callback', (result) => {
console.log('confirm() result via callback: ', result);
});
prompt('prompt() forwarded from iframe.html via callback', null, (result) => {
console.log('prompt() result via callback: ', result);
});
(async () => {
var result1 = await confirm('confirm() forwarded from iframe.html via promise');
console.log('confirm() result via promise: ', result1);
var result2 = await prompt('prompt() forwarded from iframe.html via promise');
console.log('prompt() result via promise: ', result2);
})();
</script>
</body>
</html>
dialogs.js
(function() {
var id = 1,
store = {},
isIframe = (window === window.parent || window.opener) ? false : true;
// Send message
var sendMessage = function(windowToSend, data) {
windowToSend.postMessage(JSON.stringify(data), '*');
};
// Helper for overridden confirm() and prompt()
var processInteractiveDialog = function(data, callback) {
sendMessage(parent, data);
if (callback)
store[data.id] = callback;
else
return new Promise(resolve => { store[data.id] = resolve; })
};
// Override native dialog functions
if (isIframe) {
// alert()
window.alert = function(message) {
var data = { event : 'dialog', type : 'alert', message : message };
sendMessage(parent, data);
};
// confirm()
window.confirm = function(message, callback) {
var data = { event : 'dialog', type : 'confirm', id : id++, message : message };
return processInteractiveDialog(data, callback);
};
// prompt()
window.prompt = function(message, value, callback) {
var data = { event : 'dialog', type : 'prompt', id : id++, message : message, value : value || '' };
return processInteractiveDialog(data, callback);
};
}
// Listen to messages
window.addEventListener('message', function(event) {
try {
var data = JSON.parse(event.data);
}
catch (error) {
return;
}
if (!data || typeof data != 'object')
return;
if (data.event != 'dialog' || !data.type)
return;
// Initial message from iframe to parent
if (!isIframe) {
// alert()
if (data.type == 'alert')
alert(data.message)
// confirm()
else if (data.type == 'confirm') {
var data = { event : 'dialog', type : 'confirm', id : data.id, result : confirm(data.message) };
sendMessage(event.source, data);
}
// prompt()
else if (data.type == 'prompt') {
var data = { event : 'dialog', type : 'prompt', id : data.id, result : prompt(data.message, data.value) };
sendMessage(event.source, data);
}
}
// Response message from parent to iframe
else {
// confirm()
if (data.type == 'confirm') {
store[data.id](data.result);
delete store[data.id];
}
// prompt()
else if (data.type == 'prompt') {
store[data.id](data.result);
delete store[data.id];
}
}
}, false);
})();
或者可以将chrome降到92版本以下,可以使用--disable -features="SuppressDifferentOriginSubframeJSDialogs"
特性。
使用方法:
"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable -features="SuppressDifferentOriginSubframeJSDialogs"
或者
添加谷歌浏览器的快捷方式中,如下图: