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

2021-02-02 15:49:46 +08:00
 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 会强制关掉网页全屏,导致观感不好

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

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

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

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

https://www.v2ex.com/t/750642

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

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

© 2021 V2EX