Bug 38450 - [Qt] Problem loading multiple pages at once.
Summary: [Qt] Problem loading multiple pages at once.
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: 420+
Hardware: PC Windows XP
: P5 Critical
Assignee: Nobody
URL:
Keywords: Qt, QtTriaged
Depends on:
Blocks:
 
Reported: 2010-05-02 23:36 PDT by Sean
Modified: 2014-01-29 07:46 PST (History)
8 users (show)

See Also:


Attachments
Gtk testcase (1.60 KB, text/x-csrc)
2010-05-18 07:28 PDT, Kent Hansen
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Sean 2010-05-02 23:36:12 PDT
If you try to load two pages at the same time, on two separate QWebViews, you run into some very strange issues.  I think this may be some annoying threading issue deep within the core, but I'm a noob and don't really know.


Here is a quick test case that makes two QWebViews that each load digg.com.  It logs the output in two QTextEdit windows.

-------------
main.cpp
-------------
#include <QtGui/QApplication>
#include "logger.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    for (int i = 0; i < 2; ++i)
    {
        Logger *log = new Logger();
        QWebView *web = new QWebView();
        QObject::connect(web, SIGNAL(loadFinished(bool)), log, SLOT(onLoadFinished(bool)));
        web->load(QUrl("http://digg.com"));
        log->show();
    }

    return a.exec();
}

------------
logger.h
------------
#ifndef LOGGER_H
#define LOGGER_H

#include <QTextEdit>
#include <QWebView>
#include <QWebFrame>

class Logger : public QTextEdit
{
Q_OBJECT
public:
    Logger(QWidget *p = 0) : QTextEdit(p) {}
public slots:
    void onLoadFinished(bool ok)
    {
        if (ok)
            this->append("Load successful");
        else
            this->append("Load failed");

        QString html = ((QWebView*)sender())->page()->mainFrame()->toHtml();
        int htmlSize = (html.isNull() || html.isEmpty()) ? 0 : html.length();
        this->append(QString("Html size: %1").arg(htmlSize));
    }
};

#endif // LOGGER_H

--


-- Expected Output: --

*Log 1 and 2*
Load successful
Html size: 92735


-- Actual Output: --

*Log 1*
Load successful
Html size: 92735

*Log 2*
Load successful
Html size: 2057
Load successful
Html size: 92571
Load successful
Html size: 92735


-


Other notes:

This appears to work as expected for google.com (your results may vary), but digg.com and other websites will fail.  Not sure what the common factor is.
Comment 1 Markus Goetz 2010-05-03 00:11:46 PDT
Which Qt version are you using?
Comment 2 Sean 2010-05-03 11:25:53 PDT
4.6.2
Comment 3 Sean 2010-05-03 16:37:40 PDT
Okay, this is an obvious issue with the JavaScript core.  With JS disabled, the expected results are obtained.

However, permanently disabling JS is an ugly hack that is not an option for many applications.

This should perhaps be the #1 issue to fix for QtWebKit in my opinion.  When two separate QWebViews can't even load a page and parse JavaScript simultaneously without disrupting each other in subtle ways, how can we expect tabbed browsers to operate correctly?
Comment 4 Kent Hansen 2010-05-06 03:21:26 PDT
I can reproduce on Linux against trunk (r58872).
Comment 5 Kent Hansen 2010-05-06 09:21:43 PDT
digg.com creates several iframes. Every time a frame has loaded, this is reported to FrameLoaderClientQt. And FrameLoaderClientQt::postProgressFinishedNotification() decides to emit loadFinished() for more than one frame.

Modifying the testcase to connect to view->page()->mainFrame()'s loadFinished() signal reveals that it's the "Load successful, Html size: 2057" that comes from the mainframe of one view, the two other signals are due to other frames.
Comment 6 Sean 2010-05-06 12:01:54 PDT
Not saying your hypothesis is wrong, in fact it makes a lot of sense, but just wondering how come one of the Loggers only emits 1 load while the other does many?  Theoretically they are loading the same page...?
Comment 7 Sean 2010-05-06 12:08:37 PDT
Also I think the HTML size 2057 is === to an empty string (iirc the MAX_STRING "buffer" is like 2058 or something?), because when I try to print it, it's blank.
Comment 8 Kent Hansen 2010-05-18 07:28:37 PDT
Created attachment 56371 [details]
Gtk testcase

Similar testcase for Gtk. Output:

0x960a808 load status changed: 0
0x960a8e0 load status changed: 0
0x960a808 load status changed: 1
0x960a8e0 load status changed: 1
0x960a8e0 load status changed: 2
load_finished_cb(0x960a8e0, 0x9625b80)
0x960a808 load status changed: 3
0x960a8e0 load status changed: 3
load_finished_cb(0x960a8e0, 0x963c2f0)
0x960a808 load status changed: 2
load_finished_cb(0x960a808, 0x9621f80)

So load-finished is emitted twice for one of the views.
And the load-status change order seems fishy for one of the views too (WEBKIT_LOAD_FINISHED before WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT). With only one view this is the output (which is fine):

0x9bdb808 load status changed: 0
0x9bdb808 load status changed: 1
0x9bdb808 load status changed: 3
0x9bdb808 load status changed: 2
load_finished_cb(0x9bdb808, 0x9bf3380)

Either Qt and Gtk are both doing something wrong, or the bug is deeper in WebCore. For sure, WebCore/loader/ProgressTracker.cpp is calling finalProgressComplete() more than once; this is what causes the multiple loadFinished() / load-finished signals. ProgressTracker is associated with a Page, not Frame, so that seems wrong.
For what it's worth, it looks like the page is eventually loading correctly in both views, it's just the progress notification that's incorrect.
Could it be that digg lazily creates some frames/content from JS, and the WebKit loader can't anticipate this?

Who wants to try it with a WebView on Mac to see how many times a WebViewProgressFinishedNotification is posted?
Comment 9 Allan Sandfeld Jensen 2012-12-04 01:54:55 PST
I am pretty sure this is expected behavior. A scripted webpage can finish loading, then fire a timeout that causes more content to be required to be loaded, and then finish loading that, finishing a second time. 

Pages that dynamically loads content is going to finish loading several times.
Comment 10 Jocelyn Turcotte 2012-12-04 02:08:41 PST
(In reply to comment #9)
> I am pretty sure this is expected behavior. A scripted webpage can finish loading, then fire a timeout that causes more content to be required to be loaded, and then finish loading that, finishing a second time. 
> 
> Pages that dynamically loads content is going to finish loading several times.

loadFinished should only be emitted at the end of provisional load, there should be no signal after the initial load. Unless if a new subframe is created, which produces the behavior explained in comment #5.