Trick To Get Qt QWebView Bridge从Webkit IFRAME(本地页面) [英] Trick To Get Qt QWebView Bridge Accessible from Webkit IFRAME (Local Pages)

查看:259
本文介绍了Trick To Get Qt QWebView Bridge从Webkit IFRAME(本地页面)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



http://stackoverflow.com/a/4979636/105539 ​​



不过,我现在有将IFRAME引入页面,因此有一个子文档。问题是,我无法获取子文档连接到C ++桥。



Webkit似乎有很多安全控制,当进行Javascript通信使用本地文件而不是Web服务器时,子文档和父文档。通过Javascript的所有方式的父和子调用无法工作,直到我偶然发现使用 postMessage()的HTML5的复杂性。在这一点上,我可以建立通信,但它是通过消息,而不是原生的Javascript函数调用。



有一种技术在Qt中,我可以建立一个桥梁C +以及在QWebView小部件内的IFRAME内部加载的文档,并且不使用HTML5 postMessage() API?



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

  void MainWindow :: on_webView_loadFinished(bool arg1)
{
if(arg1 == true){
QWebFrame * iframe = ui-> webView-> page() - > mainFrame() - > findFirstElement(iframe)。
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)。
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)。
connect(frame,& QWebFrame :: javaScriptWindowObjectCleared,this,& MainWindow :: attachJavascript);
if(iframe){
connect(iframe,& QWebFrame :: javaScriptWindowObjectCleared,this,& MainWindow :: attachJavascript);
}
}


解决方案

是一种折中的三种不同技术:



选项A



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



选项B



与使用file://访问的页面的Chrome浏览器及其安全控件不同,Qt的WebKit版本会让你调用 window.parent.foo()如果父文档包含函数 foo()。从那里,你可以调用cpp对象来执行任务。这是稍微间接的,但不像 postMessage() API一样是间接的。



/ strong>



如果父文档具有一个名为 cpp 的对象一个例子),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 ++。

My Qt C++ (Qt 5.5) application uses a QWebView widget. After a lot of confusion and hard work, I have managed to get the QtWebKit Bridge technique to work and now have my Webkit document (local pages, no web server) to be able to call the C++ functions. The resources for you on that are:

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

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

Now, however, I have introduced an IFRAME into the page, and so have a child document. Trouble is, I'm not able to get the child document to connect to that C++ bridge.

Webkit seems to have a whole lot of security controls when doing Javascript communication between child and parent documents when local files are used instead of web servers. All manner of parent and child calling via Javascript failed to work until I stumbled on the complexities of using the postMessage() API of HTML5. At that point, I could get communication established, but it's through messages and not native Javascript function calls.

Is there a technique in Qt where I can establish a bridge between C++ and a document loaded inside an IFRAME inside the QWebView widget, and without using the HTML5 postMessage() API?

Note that one thing I've been able to do is access the IFRAME in code like the following, but the cpp object never appears in Javascript in the iframe, even if I load it from jQuery as $(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);
  }
}

解决方案

There are three different techniques for a compromise:

Option A

HTML5 supports a postMessage() API to transfer messages from children IFRAME documents to their parent documents, and it works even with local pages (like with file://). This is a little slower because it's an indirect technique of message passing and interpretation.

Option B

Unlike your Chrome browser with its security controls on pages accessed with file://, Qt's version of WebKit will let you call window.parent.foo() if the parent document contains a function foo(). From there, you can call the cpp object to do tasks. This is slightly indirect, but not as indirect as the postMessage() API.

Option C

If the parent document has an object called cpp (your C++ injected object that you created, as an example), Qt's version of WebKit will let you call var cpp = window.parent.cpp; in order for the IFRAME to have access to the cpp.

One extra suggestion I would have is, if you're testing a WebKit interface in Chrome before being deployed through Qt, you could use an if (window.parent.cpp) (iframe document) and an if (cpp) (parent document) in order to determine if this is loading through Qt or Chrome, and then, if loaded through Chrome, fake a result through a Javascript file (like a kind of polyfill) just so that your Chrome GUI tests work okay until you're ready to hook it up to the C++ in Qt.

这篇关于Trick To Get Qt QWebView Bridge从Webkit IFRAME(本地页面)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆