JavaScript访问html页面内嵌不同源iframe报错 js: Uncaught SecurityError: Blocked a frame with origin...

最近遇到一个棘手的bug,App 中有一个网页内嵌了一个iframe,这个iframe一个类似客服机器人聊天窗口的弹出框,嵌在主网页某一个位置,是和主网页不同源的,需要获取iframe中的areatext元素,当用户点击的时候,弹出一个软键盘,供用户输入。
环境:
SUSE seld15, QT5.15.0
参考文档:
https://javascript.info/cross-window-communication
https://developer.mozilla.org/zh-CN/docs/Web/API/HTML_DOM_API

问题分析:

通常情况下, 针对主网页,如果想获取鼠标当前点击的元素,通过
在WebView::mouseReleaseEvent()中添加JS代码,从网页中读取document.activeElement.tagName,来确定当前点击的元素名称。

    QString eTagName = QString();
    QString tagNameCode = QStringLiteral("function getTagName(){" \
            "return document.activeElement.tagName;" \
            "}" \
            "getTagName();" \
            );

    page()->runJavaScript(tagNameCode, [&eTagName](const QVariant &v) { eTagName = v.toString(); });
    while (eTagName.isEmpty())
    {
        QApplication::processEvents();
    }
    if(eTagName.trimmed().compare("INPUT", Qt::CaseInsensitive) == 0 ||
      eTagName.trimmed().compare("TEXTAREA", Qt::CaseInsensitive) == 0 )
    {
   ...
   //pop up the soft keyboard.
    }

但是如果点击的位置是一个HTMLIFrameElement元素,document.activeElement.tagName就会总是返回IFRAME,无论点击iFrame的哪个位置。这时,需要通过getElementById()获取iframe元素,得到其document,(document.getElementById(‘genesys-mxg-frame’).contentWindow.document), 然后就可以像主网页一样访问iframe内部的元素,但是如果iframe的URL和主网页URL不同协议,域名或者端口号,浏览器就不允许访问,报SecurityError:

js: Uncaught SecurityError: Blocked a frame with origin “https://www.xxx.us” from accessing a frame with origin “https://yyy.cloud”. Protocols, domains, and ports must match.

When we access something inside the embedded window, the browser checks if the iframe has the same origin.

An iframe tag hosts a separate embedded window, with its own separate document and window objects.

We can access them using properties:
iframe.contentWindow to get the window inside the iframe.
iframe.contentDocument to get the document inside the iframe, shorthand for iframe.contentWindow.document.

The “Same Origin” policy states that:

if we have a reference to another window, e.g. a popup created by > window.open or a window inside iframe, and that window comes from the same origin, then we have full access to that window.
otherwise, if it comes from another origin, then we can’t access the content of that window: variables, document, anything. The only exception is location: we can change it (thus redirecting the user). But we cannot read location (so we can’t see where the user is now, no information leak).

为避开浏览器同源策略所做的尝试:

  1. Tried to disable same-origin policy from browser side, but it does not work on both linux and windows OS.
    https://stackoverflow.com/questions/3102819/disable-same-origin-policy-in-chrome
  2. Tried to disable cross-origin rules by setting the two parameters QWebEngineSettings::LocalContentCanAccessRemoteUrls & QWebEngineSettings::LocalContentCanAccessFileUrls as true in WebView::WebView () after setting page, but it does not work. Also tried higher Qt version, Qt5.15.4 and Qt6.5.1, both have the same behavior with Qt5.15.0.

Work around:

由于无法获取iframe内部元素信息,但是可以通过document.getElementById('genesys-mxg-frame').getBoundingClientRect();获取iframe的位置坐标信息,
其中,x,y,left,top,width,height,bottom,right取值方式如下,可参考https://javascript.info/coordinates
在这里插入图片描述
也可以获取iframe其他信息,如document.getElementById(‘genesys-mxg-frame’).attribute等。
所以该问题的备用解决方案是通过iframe BoundingClientRect信息,计算出需要弹出软键盘的区域,然后通过QMouseEvent的localPos()方法取得x,y坐标,获取鼠标当前点击位置,对比是否在范围内,如果是,进行后续动作,弹出软键盘。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值