1/*
2    Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
3
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17    Boston, MA 02110-1301, USA.
18*/
19
20#include "util.h"
21
22#include <QtTest/QtTest>
23#include <stdio.h>
24
25#if defined(HAVE_QTQUICK) && HAVE_QTQUICK
26#include "private/qquickwebview_p.h"
27#include "private/qwebloadrequest_p.h"
28#endif
29
30void addQtWebProcessToPath()
31{
32    // Since tests won't find ./QtWebProcess, add it to PATH (at the end to prevent surprises).
33    // QWP_PATH should be defined by qmake.
34    qputenv("PATH", qgetenv("PATH") + ":" + QWP_PATH);
35}
36
37/**
38 * Starts an event loop that runs until the given signal is received.
39 * Optionally the event loop
40 * can return earlier on a timeout.
41 *
42 * \return \p true if the requested signal was received
43 *         \p false on timeout
44 */
45bool waitForSignal(QObject* obj, const char* signal, int timeout)
46{
47    QEventLoop loop;
48    QObject::connect(obj, signal, &loop, SLOT(quit()));
49    QTimer timer;
50    QSignalSpy timeoutSpy(&timer, SIGNAL(timeout()));
51    if (timeout > 0) {
52        QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
53        timer.setSingleShot(true);
54        timer.start(timeout);
55    }
56    loop.exec();
57    return timeoutSpy.isEmpty();
58}
59
60static void messageHandler(QtMsgType type, const QMessageLogContext&, const QString& message)
61{
62    if (type == QtCriticalMsg) {
63        fprintf(stderr, "%s\n", qPrintable(message));
64        return;
65    }
66    // Do nothing
67}
68
69void suppressDebugOutput()
70{
71    qInstallMessageHandler(messageHandler); \
72    if (qgetenv("QT_WEBKIT_SUPPRESS_WEB_PROCESS_OUTPUT").isEmpty()) \
73        qputenv("QT_WEBKIT_SUPPRESS_WEB_PROCESS_OUTPUT", "1");
74}
75
76#if defined(HAVE_QTQUICK) && HAVE_QTQUICK
77bool waitForLoadSucceeded(QQuickWebView* webView, int timeout)
78{
79    QEventLoop loop;
80    LoadSpy loadSpy(webView);
81    QObject::connect(&loadSpy, SIGNAL(loadSucceeded()), &loop, SLOT(quit()));
82    QTimer timer;
83    QSignalSpy timeoutSpy(&timer, SIGNAL(timeout()));
84    if (timeout > 0) {
85        QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
86        timer.setSingleShot(true);
87        timer.start(timeout);
88    }
89    loop.exec();
90    return timeoutSpy.isEmpty();
91}
92
93bool waitForLoadFailed(QQuickWebView* webView, int timeout)
94{
95    QEventLoop loop;
96    LoadSpy loadSpy(webView);
97    QObject::connect(&loadSpy, SIGNAL(loadFailed()), &loop, SLOT(quit()));
98    QTimer timer;
99    QSignalSpy timeoutSpy(&timer, SIGNAL(timeout()));
100    if (timeout > 0) {
101        QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
102        timer.setSingleShot(true);
103        timer.start(timeout);
104    }
105    loop.exec();
106    return timeoutSpy.isEmpty();
107}
108
109bool waitForViewportReady(QQuickWebView* webView, int timeout)
110{
111    // The viewport is locked until the first frame of a page load is rendered.
112    // The QQuickView needs to be shown for this to succeed.
113    return waitForSignal(webView->experimental(), SIGNAL(loadVisuallyCommitted()), timeout);
114}
115
116LoadSpy::LoadSpy(QQuickWebView* webView)
117{
118    connect(webView, SIGNAL(loadingChanged(QWebLoadRequest*)), SLOT(onLoadingChanged(QWebLoadRequest*)));
119}
120
121void LoadSpy::onLoadingChanged(QWebLoadRequest* loadRequest)
122{
123    if (loadRequest->status() == QQuickWebView::LoadSucceededStatus)
124        emit loadSucceeded();
125    else if (loadRequest->status() == QQuickWebView::LoadFailedStatus)
126        emit loadFailed();
127}
128
129LoadStartedCatcher::LoadStartedCatcher(QQuickWebView* webView)
130    : m_webView(webView)
131{
132    connect(m_webView, SIGNAL(loadingChanged(QWebLoadRequest*)), this, SLOT(onLoadingChanged(QWebLoadRequest*)));
133}
134
135void LoadStartedCatcher::onLoadingChanged(QWebLoadRequest* loadRequest)
136{
137    if (loadRequest->status() == QQuickWebView::LoadStartedStatus) {
138        QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
139
140        QCOMPARE(m_webView->loading(), true);
141    }
142}
143#endif
144