一个关于 iframe 很艹蛋的前端需求

2021 年 2 月 2 日
 biguokang

业务是这样的

我们用 iframe 调用了 [被调用方] 的页面,然后 [被调用方] 页面一些 a 标签的 target 是“blank”的,这就导致点击他们的 a 标签会打开新的 tab

而现在的需求是,在 iframe 里的任何操作,都 [ [不允许弹出新 tab 或者新窗口] ] ,如果 [被调用方] 的页面的确是要打开新 tab 的,那就改为在本地页面跳转。

正常来说是无法实现的,因为跨域,而且 [被调用方] 肯定不会改代码的,所以只能写了个浏览器插件,通过注入代码的形式强行把网页里所有的 a 标签的 target 改为 self,这样 a 标签就全都是本地跳转

但是 [被调用方] 网页里面的业务不一定全是用 a 标签来打开新 tab,他们可能一些业务是用 js 来打开新 tab 的(类似于 window.open 这种,我尝试在插件里把 window.open 覆写成 window.location.href,但也只是部分按钮实现了,有些还是会跳出新页面)

现在问题如下: 1.被调用方是肯定不会改代码的,这个无解

2.已经能通过写浏览器插件的方式来注入代码强改客户代码的 a 标签(因为被调用方是不同域的,而且非互联网项目,装插件的设备也就那么几台,也不麻烦)

3.不能说这玩意不能做,因为项目跑在超高分大屏(电影院银幕大小)上,网页全屏显示,他有这种需求是因为打开新 tab 会强制关掉网页全屏,导致观感不好

然后如何完美实现??(虽然以我的见解这玩意是无法实现的,用浏览器插件来搞已经很仁至义尽了)

9968 次点击
所在节点    程序员
51 条回复
SlipStupig
2021 年 2 月 2 日
父页面往子页面做事件注入,监听点击事件并且 Hook 掉一些事件和函数,在父页面创建一个事件监听器,然后定义一个 receiveMessage 函数,子页面通过 window.postMessage 做跨域通信,父页面就能知道具体的点击事件了,新 tab 可以先请求页面然后覆盖掉原始的 body,这要不用跳转直接刷新了,思路仅供参考哈
Osk
2021 年 2 月 2 日
chrome 的 --kiosk 模式试试?
ByteRan
2021 年 2 月 2 日
写个浏览器的壳?
cheng6563
2021 年 2 月 2 日
服务端也可以搞个[被调用方] 的代理程序,然后注入代码。可能比浏览器插件好用点?
meepo3927
2021 年 2 月 2 日
用 Electron ? 没实践过,只是提供一个思路。

或者 nginx 做代理,把 iframe 代理到 [被调用方] 的域上,这样 iframe 就是同域了,不知能否解决。
yoshiyuki
2021 年 2 月 2 日
nginx 或者 nodejs 来代理被调用页面,使用 replace 把 target 替换掉
biguokang
2021 年 2 月 2 日
@SlipStupig 一开始和你想法一样,但是实际项目情况,注入不了,因为子页面是跨域的,contentDocoument 是 null 的,直接操作 contentWindow 直接报跨域错误,所以后来才想着写浏览器插件来注入代码才改的了子页面的逻辑。。。。。而且你想使用 postMessage 来通信,需要改被调用方的代码来接收的,但是实际场景被调用方的代码他们是不能改的。。。。如果可以改被调用方的业务代码,也不会有那么多事了
zenxds
2021 年 2 月 2 日
有些还是会跳出新页面?要具体看下有些是什么情况,比如 document.createElement 创建的 a 标签,需要把 document.createElement 也重写了
mknightoy
2021 年 2 月 2 日
浏览器关掉跨域保护不就完了么,反正都是展示用的不需要跨域保护
SlipStupig
2021 年 2 月 2 日
@biguokang 关闭浏览器的跨域选项或者用 Nginx 做代理,都可以啊
agee
2021 年 2 月 2 日
自己做个套壳浏览器,就可以自己处理所有打开新窗口事件,这样不需要管网页上的代码了。理论上好像是这样,没具体试过。
winterx
2021 年 2 月 2 日
难道就只有我想知道为什么被调用方不肯改代码?
SakuraKuma
2021 年 2 月 2 日
支持 nginx 反代,把 target 都干掉
除非额外有骚操作 js 跳转之类的
biguokang
2021 年 2 月 2 日
@winterx 我也想知道,但是人家就是那样,无解
stillyu
2021 年 2 月 2 日
设置浏览器禁止打开弹出窗口?
DrakeXiang
2021 年 2 月 2 日
有浏览器扩展强制在同一个 tab 打开新页面
SystemLight
2021 年 2 月 2 日
为什么不把 iframe 中内容读取出来,然后动态修改里面内容 再呈现呢 ?
msmmbl
2021 年 2 月 2 日
可以用 nw.js 的话,他有一个 new-win-policy 和 navigation 事件可以控制跳转行为。
leo108
2021 年 2 月 2 日
window.open = function(url) { location.href = url }
window.open('https://v2ex.com')
ciqulover
2021 年 2 月 2 日
既然都有浏览器插件了 咋还动不了 iframe 跳转逻辑呢?直接 intercept 掉 iframe 内的 script 加载返回体,正则全局替换 window.open,如果内联在 html 里的 script 代码,用 mutation observer 劫持替换就行。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://study.congcong.us/t/750642

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX