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. The script on this page appears to have a problem
Forum Updated to NodeBB v4.3 + New Features

The script on this page appears to have a problem

Scheduled Pinned Locked Moved Qt WebKit
18 Posts 2 Posters 14.7k 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.
  • I Offline
    I Offline
    imahgin
    wrote on last edited by
    #1

    First I want to apologize for my bad English. I'm a Newbie and this is my first post. Be patient with me :)

    I'm facing this issue when using some jQuery code into my hybrid application.
    I found that this message is thrown whenever the script takes long time.
    'Saint Google' points me to QWebPage::shouldInterruptJavaScript() and it seems that the way to override this message is reimplementing this slot.
    I did it but now, the script behavior it's not the desired. It seems like the slot it's called and interrupts the script although I always return false. The more annoying issue is that if I try to debug my custom slot, it's never been called!!!

    I should point out that the applications is running in a special scenario. The main application creates a form with a QWebView widget embedded. Different DLLs are called and a pointer to this form it's passed so they can use the QWebView widget.

    This is the original DLL code, where uiExt is the pointer to the form where the WebView is implemented.
    Everything works fine except the annoying script's message :(
    @
    Html::Html(Ui::Form *uiExt)
    {
    ui=uiExt;

    ui->webView->load(QUrl("inf.html"));      
    page=ui->webView->page();                  
    frame=page->mainFrame();                    
    connect( frame, SIGNAL(javaScriptWindowObjectCleared()),this, SLOT(populateJavaScriptWindowObject()) ); 
    

    }
    @

    This is the modified code using my custom class:

    @
    Html::Html(Ui::Form *uiExt)
    {
    ui=uiExt;
    mypage=new CustomPage(ui->webView);
    ui->webView->load(QUrl("inf.html"));
    frame=mypage->mainFrame();
    connect( frame, SIGNAL(javaScriptWindowObjectCleared()),this, SLOT(populateJavaScriptWindowObject()) );
    }

    @

    This is my reimplemented QWebPage to override the slot

    CustomPage.h

    @
    #ifndef CUSTOMPAGE_H
    #define CUSTOMPAGE_H

    #include <QWebPage>
    #include <QWebView>

    class CustomPage : public QWebPage
    {
    Q_OBJECT
    public:
    CustomPage(QWebView *parent=0);

    signals:

    public slots:
    bool shouldInterruptJavaScript();

    };

    #endif // CUSTOMPAGE_H
    @

    CustomPage.cpp

    @
    #include "custompage.h"

    CustomPage::CustomPage(QWebView *parent) : QWebPage(parent)
    {
    parent->setPage(this);
    }

    bool CustomPage::shouldInterruptJavaScript()
    {
    //return QWebPage::shouldInterruptJavaScript(); //original slot
    return false; //to avoid the annoying message
    }
    @

    As I stated, using this approach, CustomPage::shouldInterruptJavaScript() it's never called although the script's behavior it's not normal.

    What I'm missing?

    Thx in advance.

    1 Reply Last reply
    0
    • I Offline
      I Offline
      imahgin
      wrote on last edited by
      #2

      I finally found the cause of the issue.
      As I stated, this code belongs to a DLL. The main application (.exe) calls this DLL and pass it a pointer to the form where the QWebView is contained.

      The purpose of this method is to have a main Widget created in the main (exe) application and share the embedded QWebView Widget, so whenever a call to a DLL is performed, this pointer is passed thus allowing the DLL to access to the QWebView to show its own content.
      Once the DLL is done, it returns back the control to the main application.

      The problem here is that I'm a newbie coming from VC++ and I probably inherit some bad manners. To my understand this code it's like a semi-modal dialog but I don't even create a dialog, I simply use the 'dialog' that the main application passes as a pointer. The DLL then perform their own actions and interacts with the user using the QWebView Widget.
      In VC++ this is achieved using the DoEvents() function that must be called in the main loop.

      In my project, I used a main loop that runs the DLL's code until the user exits the application (DLL)
      If I want to process the DLL's events, I need to place a QApplication::processEvents() so the loop looks like this:

      @ do
      {
      QApplication::processEvents();
      ht->processHtml();
      }while((ht->iAction==-1)||(ht->iAction==iMenu));
      @

      ht is my object that contains all the code to process the event handler. processHtml contains some code for retrieving data (I'll change the way to do this) and the while declarative contains the conditions to end the loop.
      Obviously this code is always performing multiple calls to processEvents but this way works like a charm in VC++. In Qt, this recurrent function call, takes more than 50% of the CPU usage and that's the reason why the script message error appears!!!!
      However, this doesn't explain why my own ShouldInterruptJavaScript slot it's never called.

      I'm now considering to set up a timer to avoid this massive CPU usage.
      Anyway I guess there are better approach to solve this issue.
      I accept suggestions :)

      1 Reply Last reply
      0
      • A Offline
        A Offline
        AcerExtensa
        wrote on last edited by
        #3

        @this way works like a charm in VC++@
        oh please, stop lying... clean endless loop eat 100% CPU everywhere...
        And if you Develop with Qt(compiled with VS) in VS - YOU ARE using VC++. Qt is a set of libraries, framework(if you wish) and not a kind of compiler interpreter or something wild else...

        So, just use method that was found for a long long time ago: use Sleep(1) in endless loop if it eats to much CPU!

        God is Real unless explicitly declared as Integer.

        1 Reply Last reply
        0
        • I Offline
          I Offline
          imahgin
          wrote on last edited by
          #4

          Yeap, you are absolutely right. I forgot to mention the Sleep which, of course, I use in VC++. Sorry, it's my fault. But it doesn't take 100% CPU, I guess it depends on the platform or microprocessor architecture but in modern computers it only takes about 50% (which confirms what happened to me)

          In fact, in the last part of my post I mentioned some kind of solution using something similar to the Sleep() function: a timer. What is the best way to achieve this in Qt? I read something about QThread::msleep or QWaitCondition but I don't know if it's better build my own timer.

          1 Reply Last reply
          0
          • A Offline
            A Offline
            AcerExtensa
            wrote on last edited by
            #5

            I'm just using WINAPI Sleep(mseconds) on Win platforms and usleep() on *nix... have never had problems with them...

            God is Real unless explicitly declared as Integer.

            1 Reply Last reply
            0
            • I Offline
              I Offline
              imahgin
              wrote on last edited by
              #6

              And something native in Qt? Is there a Sleep() function in Qt?
              As I can see there are some tricks like those I mentioned before or even the QTest:qWait() function.
              Maybe QThreat is the best way but in such case I need to reimplement the function because it's static protected.

              1 Reply Last reply
              0
              • A Offline
                A Offline
                AcerExtensa
                wrote on last edited by
                #7

                Here is the QTest:qSleep source:
                @void QTest::qSleep(int ms)
                {
                QTEST_ASSERT(ms > 0);

                #ifdef Q_OS_WIN
                Sleep(uint(ms));
                #else
                struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
                nanosleep(&ts, NULL);
                #endif
                }@

                bq. Sleeps for ms milliseconds, blocking execution of the
                test. qSleep() will not do any event processing and leave your test
                unresponsive. Network communication might time out while
                sleeping. Use qWait() to do non-blocking sleeping.

                About qWait:
                bq. Waits for ms milliseconds. While waiting, events will be processed and
                your test will stay responsive to user interface events or network communication.

                God is Real unless explicitly declared as Integer.

                1 Reply Last reply
                0
                • I Offline
                  I Offline
                  imahgin
                  wrote on last edited by
                  #8

                  Thx AcerExtensa.

                  In fact, while I'm posting, I'm modifying my code to include QTest:qWait().
                  This method includes events processor which is what I'm looking for.

                  1 Reply Last reply
                  0
                  • I Offline
                    I Offline
                    imahgin
                    wrote on last edited by
                    #9

                    Well, it seems this issue is solved (thx AcerExtensa again)
                    I use the QTest:qWait() function and did the trick but instead of import QTest, I had to include <QtTest/QTest> and then include qtestlib in the project.

                    Anyway this left unresolved why I can't reimplement ShouldInterruptJavaScript().
                    What's wrong with my custom QWebPage?

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      AcerExtensa
                      wrote on last edited by
                      #10

                      bq. Warning: Because of binary compatibility constraints, this function is not virtual. If you want to provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript() slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.

                      Your implementation is correct for Qt 4.8... which version are you using actually?

                      God is Real unless explicitly declared as Integer.

                      1 Reply Last reply
                      0
                      • I Offline
                        I Offline
                        imahgin
                        wrote on last edited by
                        #11

                        4.7.4. And if I create an object derived from CustomPage and set a degug point in ShouldInterr....., this slot it's never called. What is more susprising is the fact that using my custom class, the "The script on this page appears to have a problem" message it's never displayed but, instead, the script ceases to work normally.

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          AcerExtensa
                          wrote on last edited by
                          #12

                          I need to go for today.. will test this tomorrow...

                          God is Real unless explicitly declared as Integer.

                          1 Reply Last reply
                          0
                          • I Offline
                            I Offline
                            imahgin
                            wrote on last edited by
                            #13

                            Thx. I'll try to determine the cause of this strange behavior.

                            1 Reply Last reply
                            0
                            • A Offline
                              A Offline
                              AcerExtensa
                              wrote on last edited by
                              #14

                              Hi, I've tested this function today and it does work properly... So, the problem is in your code somewhere...

                              Here is the test project: "WebPageTest.tar.gz":http://vip2006.net/WebPageTest.tar.gz

                              Just run it and click Test button... in about 20-30 second you will get function name printed in output...

                              God is Real unless explicitly declared as Integer.

                              1 Reply Last reply
                              0
                              • I Offline
                                I Offline
                                imahgin
                                wrote on last edited by
                                #15

                                Ok, I'll check it out and compare with my code.
                                Thanks again

                                1 Reply Last reply
                                0
                                • I Offline
                                  I Offline
                                  imahgin
                                  wrote on last edited by
                                  #16

                                  Well, I've tried out your code and... Obviously works fine :)
                                  When I start your script, the custom "ShouldInterru..." slot is called after 10-15 seconds (as expected).
                                  Surprisingly, when I get the script error message in my code (not always), is displayed after 1 or 2 seconds. In fact I though this was the normal behavior.

                                  In order to check if there were something I missed in my html code, I modified my code to call your html from my DLL and... the "ShouldInterrupt..." it's never called!!!!!!.
                                  And what is most strange, neither with the original class or the custom one. The application simply freezes.

                                  This takes me to square one. There must be something I'm doing terrifyingly wrong in my code.
                                  As I stated previously I'm calling a DLL and passing a pointer to the form which contains the QWebPage.

                                  To discard an issue in this call I'm gonna try to recreate the same issue in the EXE application and override the "ShouldInterr..." slot.

                                  1 Reply Last reply
                                  0
                                  • I Offline
                                    I Offline
                                    imahgin
                                    wrote on last edited by
                                    #17

                                    Today I've tried to reproduce again the problem using the code AcerExtensa sent me and it takes more than 1 minute to "ShouldInterruptJavaScript" to be called the first time. I don't know if this is a normal behavior (I'm debugging the code). After such time, the slot it's triggered every 15 seconds (as expected). Friday (when I tried this the very first time, the slot was called after just 15 seconds).

                                    Anyway in my case, the problem I think it's a different one.
                                    My project consists in a main application (EXE) and different DLLs. The EXE creates a window with a WebView Widget. This main application interacts with the user using this Widget so I must connect the javaScriptWindowObjectCleared signal with the populateJavaScriptWindowObject slot.

                                    @
                                    connect(ui.webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),this, SLOT(populateJavaScriptWindowObject()));
                                    @

                                    Whenever a DLL is called, the main application pass it a pointer to the WebView so it can perform the same action thus allowing the interaction through the same WebView.
                                    Before doing that I disconnect the signal:

                                    @
                                    disconnect(ui.webView->page()->mainFrame());
                                    @

                                    Probably this is where I screwed up. I guess I'm not disconnecting the signal properly and there are some abnormal behavior behind this. Maybe the Script error I get is not from the DLL's side but the EXE side. This could be the reason why my ShouldInterruptJavaScript slot is never called (in the DLL side).

                                    With this in mind, I tried this at home:
                                    @
                                    disconnect(ui.webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),this, SLOT(populateJavaScriptWindowObject()));
                                    @
                                    but the same occurs.

                                    Things seems to change when I tried this:
                                    @ui.webView->page()->disconnect();@

                                    Unfortunately my HDD crashed and now I'm recovering the mess so I can't confirm the problem is solved.

                                    1 Reply Last reply
                                    0
                                    • I Offline
                                      I Offline
                                      imahgin
                                      wrote on last edited by
                                      #18

                                      Finally I discovered what was causing the issue.
                                      The problem is the way I use QWebView. In my project I have a main application (exe) that creates a QWebView widget. In order to interact with it I connect javaScriptWindowObjectCleared with populateJavaScriptWindowObject

                                      @connect(ui.webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),this, SLOT(populateJavaScriptWindowObject()));
                                      @

                                      In the html side I call my slot using this way

                                      @

                                      a href=""onClick=" javaskript:setCommand('INF');MyEXE.submit()">ELEMENTOS</a>
                                      @

                                      (Note: I deliberate misspelled the <a> & javascript tag in this post to avoid errors in the preview)

                                      So whenever the user clicks in this option my function MyExe.submit() is called in the EXE side.
                                      This function calls a DLL and passes a pointer to the QWebView but before doing that I disconnect the signal in the EXE

                                      @
                                      void MyEXE::submit()
                                      {
                                      ...
                                      QLibrary myLib("C:\Users\mahg\Documents\Qt\DLL\debug\DLL_Test2.dll");
                                      typedef int (MyDLL)(Ui::Form, int);
                                      MyDLL myDLL = (MyDLL) myLib.resolve("Dll");
                                      if (myDLL)
                                      {
                                      ...
                                      disconnect(ui.webView->page()->mainFrame(),0,0,0);
                                      int i=myDLL(&ui);
                                      ...
                                      }
                                      ...
                                      }
                                      @

                                      Note: the original code I wrote to disconnect was:
                                      @
                                      disconnect(ui.webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),this, SLOT(populateJavaScriptWindowObject()));
                                      @

                                      Then, the DLL connects the signal javaScriptWindowObjectCleared with its own populateJavaScriptWindowObject and interacts with the user through the QWebView.
                                      So far everything worked fine but there is a problem with the ShouldInterruptJavaScript. This function is triggered if the JavaScript code takes long time, but I discovered that the trigger doesn't occurs in the DLL but in the EXE.
                                      This only occurs if I call the DLL inside the function MyEXE::submit(). If I call it outside this function everything works fine.
                                      I guess Qt can't disconnect theses slots if we are still processing some code inside the slot called from the html

                                      Is this a normal behavior?
                                      I can override the ShouldInterruptJavaScript in the main (EXE) code but this is not fair for me.
                                      If there is no workaround for this I could try to call the DLL outside the MyEXE::submit()

                                      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