javascript - 使 Qt QWebView Bridge 可从 Webkit IFRAME(本地页面)访问的技巧

标签 javascript c++ html qt iframe

我的 Qt C++ (Qt 5.5) 应用程序使用 QWebView 小部件。经过大量的困惑和艰苦的工作,我设法让 QtWebKit Bridge 技术发挥作用,现在我的 Webkit 文档(本地页面,没有 Web 服务器)能够调用 C++ 函数。适合您的资源是:

http://doc.qt.io/qt-5/qtwebkit-bridge.html

https://stackoverflow.com/a/4979636/105539

但是,现在我已经在页面中引入了一个 IFRAME,因此有了一个子文档。问题是,我无法让子文档连接到那个 C++ 桥。

当使用本地文件而不是 Web 服务器时,在子文档和父文档之间进行 Javascript 通信时,Webkit 似乎有很多安全控制。在我偶然发现使用 HTML5 的 postMessage() API 的复杂性之前,所有通过 Javascript 进行的父子调用都无法正常工作。那时,我可以建立通信,但它是通过消息而不是本地 Javascript 函数调用。

Qt 中是否有一种技术可以在不使用 HTML5 postMessage() API 的情况下在 C++ 和 QWebView 小部件内的 IFRAME 中加载的文档之间建立桥梁?

请注意,我能够做的一件事是在如下代码中访问 IFRAME,但 cpp 对象从未出现在 iframe 的 Javascript 中,即使我从 jQuery 加载它也是如此作为 $(document).ready(function(){ setTimeout('testIfCPPLoaded();',100); });.

void MainWindow::on_webView_loadFinished(bool arg1)
{
  if (arg1 == true) {
    QWebFrame *iframe = ui->webView->page()->mainFrame()->findFirstElement("iframe").webFrame();
    if (iframe) {
      connect(iframe,&QWebFrame::javaScriptWindowObjectCleared,this,&MainWindow::attachJavascript);
    }
  }
}

void MainWindow::attachJavascript()
{
  QWebFrame *frame = ui->webView->page()->mainFrame();
  QWebFrame *iframe = ui->webView->page()->mainFrame()->findFirstElement("iframe").webFrame();
  frame->addToJavaScriptWindowObject(QString("cpp"), this);
  if (iframe) {
    iframe->addToJavaScriptWindowObject(QString("cpp"),this);
  }
}

void MainWindow::on_webView_urlChanged(const QUrl &arg1)
{
  QWebFrame *frame = ui->webView->page()->mainFrame();
  QWebFrame *iframe = ui->webView->page()->mainFrame()->findFirstElement("iframe").webFrame();
  connect(frame, &QWebFrame::javaScriptWindowObjectCleared, this, &MainWindow::attachJavascript);
  if (iframe) {
    connect(iframe,&QWebFrame::javaScriptWindowObjectCleared, this, &MainWindow::attachJavascript);
  }
}

最佳答案

存在三种不同的妥协技术:

选项A

HTML5 支持 postMessage()将消息从子 IFRAME 文档传输到其父文档的 API,它甚至适用于本地页面(如 file://)。这有点慢,因为它是一种间接的消息传递和解释技术。

选项 B

与 Chrome 浏览器对通过 file://访问的页面进行安全控制不同,Qt 版本的 WebKit 允许您调用 window.parent.foo()如果父文档包含函数 foo() .从那里,您可以调用 cpp 对象来执行任务。这有点间接,但不像 postMessage() 那样间接。 API。

选项 C

如果父文档有一个名为 cpp 的对象(例如,您创建的 C++ 注入(inject)对象),Qt 版本的 WebKit 将允许您调用 var cpp = window.parent.cpp;以便 IFRAME 能够访问 cpp。

我还有一个额外的建议是,如果您在通过 Qt 部署之前在 Chrome 中测试 WebKit 界面,您可以使用 if (window.parent.cpp) (iframe 文档)和一个 if (cpp) (父文档)以确定这是通过 Qt 还是 Chrome 加载,然后,如果通过 Chrome 加载,则通过 Javascript 文件(如一种 polyfill)伪造结果,这样您的 Chrome GUI 测试就可以正常工作,直到您准备好将它连接到 Qt 中的 C++。

关于javascript - 使 Qt QWebView Bridge 可从 Webkit IFRAME(本地页面)访问的技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33599474/

相关文章:

javascript - 交替背景图像之间的间距

javascript - 复选框事件监听器未触发

javascript - 如何检查实际事件元素的类别

javascript - jQuery 单击按钮即可中止所有 AJAX 请求(查询)

c++ - 在 SDL 中编写 X-Bitmap 加载程序?

c++ - 类继承后不可访问

jquery - jquery如何获取文本框的值

android - 特殊字符显示为问号哈希

javascript - Jquery动画三个按钮来进行开关

native 代码中的 Android Binder