<头><元字符集=utf-8"><title>Iframe(域B)</title><script type="text/javascript";src=dialogs.js"></script>头部><身体><h1>Iframe(域B)</h1><script type="text/javascript">alert('alert() 从 iframe.html 转发');confirm('confirm() 通过回调从 iframe.html 转发', (result) => {console.log('confirm() result via callback: ', result);});prompt('prompt() 通过回调从 iframe.html 转发', null, (result) => {console.log('prompt() result via callback: ', result);});(异步() => {var result1 = await confirm('confirm() 通过承诺从 iframe.html 转发');console.log('confirm() result via promise:', result1);var result2 = await prompt('prompt() 通过 promise 从 iframe.html 转发');console.log('prompt() result via promise:', result2);})();</html>
dialogs.js
(function() {变量 ID = 1,商店 = {},isIframe = (window === window.parent || window.opener) ?假:真;//发信息var sendMessage = 函数(windowToSend,数据){windowToSend.postMessage(JSON.stringify(data), '*');};//覆盖confirm() 和prompt() 的助手var processInteractiveDialog = 函数(数据,回调){发送消息(父母,数据);如果(回调)store[data.id] = 回调;别的return new Promise(resolve => { store[data.id] = resolve; })};//覆盖原生对话框函数如果(isIframe){//警报()window.alert = 函数(消息){var data = { event : 'dialog', type : 'alert', message : message };发送消息(父母,数据);};//确认()window.confirm = 函数(消息,回调){var data = { event : 'dialog', type : 'confirm', id : id++, message : message };返回 processInteractiveDialog(data, callback);};//迅速的()window.prompt = 函数(消息,值,回调){var data = { event : 'dialog', type : 'prompt', id : id++, message : message, value : value ||'' };返回 processInteractiveDialog(data, callback);};}//监听消息window.addEventListener('message', function(event) {尝试 {var data = JSON.parse(event.data);}捕捉(错误){返回;}if (!data || typeof data !='object')返回;if (data.event !='dialog' || !data.type)返回;//从 iframe 到父级的初始消息如果(!isIframe){//警报()如果(数据类型=='警报')警报(数据.消息)//确认()否则如果(数据类型=='确认'){var data = { event : 'dialog', type : 'confirm', id : data.id, result : confirm(data.message) };发送消息(事件源,数据);}//迅速的()否则如果(数据类型=='提示'){var data = { event : 'dialog', type : 'prompt', id : data.id, result : prompt(data.message, data.value) };发送消息(事件源,数据);}}//从父级到 iframe 的响应消息别的 {//确认()如果(数据类型=='确认'){存储[data.id](data.result);删除商店[data.id];}//迅速的()否则如果(数据类型=='提示'){存储[data.id](data.result);删除商店[data.id];}}}, 错误的);})();
Apps script web app works in <iframe>. It seems Chrome is no longer supporting alert(), confirm(), Promote these functions on the web app.
Any workaround to this?
Chrome Version 92.0.4515.107 (Official Build) (64-bit) -- does not work
Edge Version 91.0.864.71 (Official build) (64-bit) -- works
Tried replacing alert() with window.alert(), but still does not work.
解决方案
This is absurd and subjective decision of Google to remove alert(), confirm(), and prompt() for cross origin iframes. And they called it "feature". And justification is very poor - see "motivation" bellow. A very weak reason for removing such an important feature! Community and developers should protest!
Send message via Window.postMessage() from iframe to parent and show dialog via parent page. It is very elegant hack and shame on Google because before Chrome version 92 client saw alert dialog e.g. An embedded page iframe.com" says: ... (which was correct - client see real domain which invoked alert) but now with postMessage solution client will see a lie e.g. The page example.com" says: ... but alert was not invoked by example.com. Stupid google decision caused them to achieve the opposite effect - client will be much more confused now. Google's decision was hasty and they didn't think about the consequences. In case of prompt() and confirm() it is a little bit tricky via Window.postMessage() because we need to send result from top back to iframe.
What Google will do next? Disable Window.postMessage()? Déjà vu. We are back in Internet Explorer era... developers waste time by doing stupid hacks.
With code bellow you can use overridden native alert(), confirm() and prompt() in cross origin iframe with minimum code change. There is no change for alert() usage. I case of confirm() and prompt() just add "await" keyword before it or feel free to use callback way in case you can not switch easily your sync functions to async functions. See all usage examples in iframe.html bellow.
Everything bad comes with something good - now I gained with this solution an advantage that iframe domain is not revealed (domain from address bar is now used in dialogs).