Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt WebKit
  4. QWebFrame::evaluateJavaScript crash
Forum Updated to NodeBB v4.3 + New Features

QWebFrame::evaluateJavaScript crash

Scheduled Pinned Locked Moved Qt WebKit
11 Posts 2 Posters 5.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    janfaroe
    wrote on last edited by
    #2

    Alrightie then. Since my case is rather specific (I need to evaluate a function call in a 3rd party JS chunk, and don't really care about the DOM as such - I just need the code to run), I ended up using QScriptEngine instead with a very sparse dummy DOM injected in the script engine instance, and then running the desired method.

    Not sure what the issue with QWebKit is here (threading?), but QScriptEngine works for me in this case.

    Others having the same issue (but needing a full DOM) might be interested in http://www.envjs.com, implementing a full DOM. The project https://qt.gitorious.org/qt-labs/qtscript-browser-env puts this in a Qt context as a QScriptEngine plugin, although the project is not compiling for Qt5.x. Should be easy to fix though.

    1 Reply Last reply
    0
    • B Offline
      B Offline
      brcontainer
      wrote on last edited by
      #3

      occurs only in debug mode?

      QT project: https://github.com/brcontainer/qt-helper

      1 Reply Last reply
      0
      • J Offline
        J Offline
        janfaroe
        wrote on last edited by
        #4

        In release as well.

        1 Reply Last reply
        0
        • B Offline
          B Offline
          brcontainer
          wrote on last edited by brcontainer
          #5

          I think the QWebFrame::setContent does not work well, it is equivalent to setHTML but is a little more advanced, so has no way to set the content of a page has loaded.

          The right thing would be this:

          QWebPage *page = ui->webview->page();
          QString scriptContent = "<scr" + "ipt>function HelloWorld() { alert&#40;'Hello World!!!'&#41;; }</sc" + "ript>";
          QByteArray injectScript = QString(scriptContent).toUtf8();
          
          page->mainFrame()->setContent(injectScript, "text/html");@
          

          But for your purpose this will not work, the right would you use another type of injection, such as the very "evaluateScript", like this:

          QString injectionJS = "(function() { var new = document.createElement('scr" + "ipt');";
          injectionJS +=  "new.inner" + "HTML = String((" + scriptContent + "));";
          injectionJS +=  "document.body.appendChild(new)";
          injectionJS +=  "});";
          
          page->mainFrame()->evaluateJavaScript(injectionJS);
          

          It's true

          Sounds like a bug. Please go to http://bugreports.qt-project.org/
          After create an issue, post your link here.

          Thanks!

          QT project: https://github.com/brcontainer/qt-helper

          1 Reply Last reply
          0
          • J Offline
            J Offline
            janfaroe
            wrote on last edited by
            #6

            Did it really crash on evaluating this?

            1 Reply Last reply
            0
            • B Offline
              B Offline
              brcontainer
              wrote on last edited by
              #7

              Not the evaluateScript that causes the "crash", but using the incorrect way QwebFrame::setContent. He apparently simulates the loading of a file, but if the page is already loaded it fails to load again.

              Same is not true-if the "crash" the QwebFrame::setContent would not work for what you want to do, because it would wipe the entire page and its original content would be lost.

              View this would be the proper way to work with QwebFrame::setContent does:

              @QwebFrame::setContent (QString("<scr"+"ipt>content</scr"+"ipt>").toUtf8()," text/html");@

              What I mean is that it seems that server to create a home page (as in Chrome have the "SpeedDial")


              For you to achieve your goal, I recommend doing something like this:

              https://gist.github.com/brcontainer/98016ee3655cfa535e8e (I fixed my example here)

              I tested, no crash using evaluateScript.

              QT project: https://github.com/brcontainer/qt-helper

              1 Reply Last reply
              0
              • J Offline
                J Offline
                janfaroe
                wrote on last edited by
                #8

                Hm, the thing is, my approach works in most cases. The JS gets loaded and run. But when it meets certain injections (they are LARGE all of them - several MB of minified JS code), it crashes (as in the application dies, with a crash report and all, as in the one I've shown).

                As you can see in the crash report, the culprit has to do with a string destructor after my call to QWebFrame::evaluateJavaScript(). For some reason I don't think it's related to the way the JS is loaded.

                In any case, I'll try your approach at the earliest convenience; but for now QScript works for me.Thanks!

                1 Reply Last reply
                0
                • B Offline
                  B Offline
                  brcontainer
                  wrote on last edited by
                  #9

                  Got it, then it is a limitation of reading time with the QtWebKit runtime.

                  Perhaps the process for files only work if the injection was asynchronous, but the QtWebKit does not support multiprocess (as is Chrome).

                  Why do not you do this:

                  1. Create um custom protocol in "QNetWorkAccessManager::createRequest", like "qrc:", eg. @janfaore://@

                  2. Save your Javascript in an file located in "User folder" (in Window c:\Users\USER_NAME\Local Datac\AppData\Local\project_user_data)

                  3. After save, inject saved file by your custom protocol, like this: @janfaore://myfile.js@

                  4. Set an interval/timeout before perform: @QWebFrame::evaluateScript("custom_function();");@

                  QNetWorkAccessManager example:

                  @QNetworkReply * netWork::createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData) {
                  const QString scheme = request.url().scheme().toLower().trimmed();
                  if ("janfaore" == scheme) {
                  return [YOUR CUSTOM QNetworkReply];
                  }

                  QNetWorkAccessManager::createRequest(op, request, outgoingData);
                  

                  }@

                  Note: Maybe need reimplement QNetWorkReply (create an custom QNetWorkReply).

                  QT project: https://github.com/brcontainer/qt-helper

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    janfaroe
                    wrote on last edited by
                    #10

                    I appreciate your efforts in trying to help, but the problem is not loading the scripts (which are online resources that change regularly). I have no problem with this being asynchronous. The function I need to call via evaluateScript() is very, very simple and short (a few string manipulations), and a timeout in that context is very inlikely.

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      brcontainer
                      wrote on last edited by
                      #11

                      Is that you said that major routes injected with "the evaluate" that caused the "crash", by this thought that if you create yourself a custom protocol like in "Firefox", you could throw huge scripts and the "Main Thread" (windows) would not crash.

                      Using "evaluateScript", you inject only this:

                      @< script src="janfaore://myfile.js"></ script >@

                      After use QTimer::singleShot() for evaluate your function.

                      QT project: https://github.com/brcontainer/qt-helper

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved