~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 program 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 program; 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
 
 
21
#include "config.h"
 
22
#include "QtDialogRunner.h"
 
23
 
 
24
#include "WKRetainPtr.h"
 
25
#include "WKStringQt.h"
 
26
#include "qquickwebview_p_p.h"
 
27
#include "qwebpermissionrequest_p.h"
 
28
#include <QtQml/QQmlComponent>
 
29
#include <QtQml/QQmlContext>
 
30
#include <QtQml/QQmlEngine>
 
31
#include <QtQuick/QQuickItem>
 
32
#include <wtf/PassOwnPtr.h>
 
33
 
 
34
namespace WebKit {
 
35
 
 
36
QtDialogRunner::QtDialogRunner(QQuickWebView* webView)
 
37
    : QEventLoop()
 
38
    , m_webView(webView)
 
39
    , m_wasAccepted(false)
 
40
{
 
41
}
 
42
 
 
43
QtDialogRunner::~QtDialogRunner()
 
44
{
 
45
}
 
46
 
 
47
// All dialogs need a way to support the state of the
 
48
// dialog being done/finished/dismissed. This is handled
 
49
// in the dialog base context.
 
50
class DialogContextBase : public QObject {
 
51
    Q_OBJECT
 
52
 
 
53
public:
 
54
    DialogContextBase()
 
55
        : QObject()
 
56
        , m_dismissed(false)
 
57
    {
 
58
    }
 
59
 
 
60
public Q_SLOTS:
 
61
    // Allows clients to call dismiss() directly, while also
 
62
    // being able to hook up signals to automatically also
 
63
    // dismiss the dialog since it's a slot.
 
64
 
 
65
    void dismiss()
 
66
    {
 
67
        m_dismissed = true;
 
68
        emit dismissed();
 
69
    }
 
70
 
 
71
Q_SIGNALS:
 
72
    void dismissed();
 
73
 
 
74
private:
 
75
    // We store the dismissed state so that run() can check to see if a
 
76
    // dialog has already been dismissed before spinning an event loop.
 
77
    bool m_dismissed;
 
78
    friend void QtDialogRunner::run();
 
79
};
 
80
 
 
81
class DialogContextObject : public DialogContextBase {
 
82
    Q_OBJECT
 
83
    Q_PROPERTY(QString message READ message CONSTANT)
 
84
    Q_PROPERTY(QString defaultValue READ defaultValue CONSTANT)
 
85
 
 
86
public:
 
87
    DialogContextObject(const QString& message, const QString& defaultValue = QString())
 
88
        : DialogContextBase()
 
89
        , m_message(message)
 
90
        , m_defaultValue(defaultValue)
 
91
    {
 
92
        connect(this, SIGNAL(accepted(QString)), SLOT(dismiss()));
 
93
        connect(this, SIGNAL(rejected()), SLOT(dismiss()));
 
94
    }
 
95
    QString message() const { return m_message; }
 
96
    QString defaultValue() const { return m_defaultValue; }
 
97
 
 
98
public Q_SLOTS:
 
99
    void accept(const QString& result = QString()) { emit accepted(result); }
 
100
    void reject() { emit rejected(); }
 
101
 
 
102
Q_SIGNALS:
 
103
    void accepted(const QString& result);
 
104
    void rejected();
 
105
 
 
106
private:
 
107
    QString m_message;
 
108
    QString m_defaultValue;
 
109
};
 
110
 
 
111
class BaseAuthenticationContextObject : public DialogContextBase {
 
112
    Q_OBJECT
 
113
    Q_PROPERTY(QString hostname READ hostname CONSTANT)
 
114
    Q_PROPERTY(QString prefilledUsername READ prefilledUsername CONSTANT)
 
115
 
 
116
public:
 
117
    BaseAuthenticationContextObject(const QString& hostname, const QString& prefilledUsername)
 
118
        : DialogContextBase()
 
119
        , m_hostname(hostname)
 
120
        , m_prefilledUsername(prefilledUsername)
 
121
    {
 
122
        connect(this, SIGNAL(accepted(QString, QString)), SLOT(dismiss()));
 
123
        connect(this, SIGNAL(rejected()), SLOT(dismiss()));
 
124
    }
 
125
 
 
126
    QString hostname() const { return m_hostname; }
 
127
    QString prefilledUsername() const { return m_prefilledUsername; }
 
128
 
 
129
public Q_SLOTS:
 
130
    void accept(const QString& username, const QString& password) { emit accepted(username, password); }
 
131
    void reject() { emit rejected(); }
 
132
 
 
133
Q_SIGNALS:
 
134
    void accepted(const QString& username, const QString& password);
 
135
    void rejected();
 
136
 
 
137
private:
 
138
    QString m_hostname;
 
139
    QString m_prefilledUsername;
 
140
};
 
141
 
 
142
class HttpAuthenticationDialogContextObject : public BaseAuthenticationContextObject {
 
143
    Q_OBJECT
 
144
    Q_PROPERTY(QString realm READ realm CONSTANT)
 
145
 
 
146
public:
 
147
    HttpAuthenticationDialogContextObject(const QString& hostname, const QString& realm, const QString& prefilledUsername)
 
148
        : BaseAuthenticationContextObject(hostname, prefilledUsername)
 
149
        , m_realm(realm)
 
150
    {
 
151
    }
 
152
 
 
153
    QString realm() const { return m_realm; }
 
154
 
 
155
private:
 
156
    QString m_realm;
 
157
};
 
158
 
 
159
class ProxyAuthenticationDialogContextObject : public BaseAuthenticationContextObject {
 
160
    Q_OBJECT
 
161
    Q_PROPERTY(quint16 port READ port CONSTANT)
 
162
 
 
163
public:
 
164
    ProxyAuthenticationDialogContextObject(const QString& hostname, quint16 port, const QString& prefilledUsername)
 
165
        : BaseAuthenticationContextObject(hostname, prefilledUsername)
 
166
        , m_port(port)
 
167
    {
 
168
    }
 
169
 
 
170
    quint16 port() const { return m_port; }
 
171
 
 
172
private:
 
173
    quint16 m_port;
 
174
};
 
175
 
 
176
class CertificateVerificationDialogContextObject : public DialogContextBase {
 
177
    Q_OBJECT
 
178
    Q_PROPERTY(QString hostname READ hostname CONSTANT)
 
179
 
 
180
public:
 
181
    CertificateVerificationDialogContextObject(const QString& hostname)
 
182
        : DialogContextBase()
 
183
        , m_hostname(hostname)
 
184
    {
 
185
        connect(this, SIGNAL(accepted()), SLOT(dismiss()));
 
186
        connect(this, SIGNAL(rejected()), SLOT(dismiss()));
 
187
    }
 
188
 
 
189
    QString hostname() const { return m_hostname; }
 
190
 
 
191
public Q_SLOTS:
 
192
    void accept() { emit accepted(); }
 
193
    void reject() { emit rejected(); }
 
194
 
 
195
Q_SIGNALS:
 
196
    void accepted();
 
197
    void rejected();
 
198
 
 
199
private:
 
200
    QString m_hostname;
 
201
};
 
202
 
 
203
class FilePickerContextObject : public DialogContextBase {
 
204
    Q_OBJECT
 
205
    Q_PROPERTY(QStringList fileList READ fileList CONSTANT)
 
206
    Q_PROPERTY(bool allowMultipleFiles READ allowMultipleFiles CONSTANT)
 
207
 
 
208
public:
 
209
    FilePickerContextObject(const QStringList& selectedFiles, bool allowMultiple)
 
210
        : DialogContextBase()
 
211
        , m_allowMultiple(allowMultiple)
 
212
        , m_fileList(selectedFiles)
 
213
    {
 
214
        connect(this, SIGNAL(fileSelected(QStringList)), SLOT(dismiss()));
 
215
        connect(this, SIGNAL(rejected()), SLOT(dismiss()));
 
216
    }
 
217
 
 
218
    QStringList fileList() const { return m_fileList; }
 
219
    bool allowMultipleFiles() const { return m_allowMultiple;}
 
220
 
 
221
public Q_SLOTS:
 
222
    void reject() { emit rejected();}
 
223
    void accept(const QVariant& path)
 
224
    {
 
225
        QStringList filesPath = path.toStringList();
 
226
 
 
227
        if (filesPath.isEmpty()) {
 
228
            emit rejected();
 
229
            return;
 
230
        }
 
231
 
 
232
        // For single file upload, send only the first element if there are more than one file paths
 
233
        if (!m_allowMultiple && filesPath.count() > 1)
 
234
            filesPath = QStringList(filesPath.at(0));
 
235
        emit fileSelected(filesPath);
 
236
    }
 
237
 
 
238
Q_SIGNALS:
 
239
    void rejected();
 
240
    void fileSelected(const QStringList&);
 
241
 
 
242
private:
 
243
    bool m_allowMultiple;
 
244
    QStringList m_fileList;
 
245
};
 
246
 
 
247
class DatabaseQuotaDialogContextObject : public DialogContextBase {
 
248
    Q_OBJECT
 
249
    Q_PROPERTY(QString databaseName READ databaseName CONSTANT)
 
250
    Q_PROPERTY(QString displayName READ displayName CONSTANT)
 
251
    Q_PROPERTY(quint64 currentQuota READ currentQuota CONSTANT)
 
252
    Q_PROPERTY(quint64 currentOriginUsage READ currentOriginUsage CONSTANT)
 
253
    Q_PROPERTY(quint64 currentDatabaseUsage READ currentDatabaseUsage CONSTANT)
 
254
    Q_PROPERTY(quint64 expectedUsage READ expectedUsage CONSTANT)
 
255
    Q_PROPERTY(QtWebSecurityOrigin* origin READ securityOrigin CONSTANT)
 
256
 
 
257
public:
 
258
    DatabaseQuotaDialogContextObject(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage)
 
259
        : DialogContextBase()
 
260
        , m_databaseName(databaseName)
 
261
        , m_displayName(displayName)
 
262
        , m_currentQuota(currentQuota)
 
263
        , m_currentOriginUsage(currentOriginUsage)
 
264
        , m_currentDatabaseUsage(currentDatabaseUsage)
 
265
        , m_expectedUsage(expectedUsage)
 
266
    {
 
267
        WKRetainPtr<WKStringRef> scheme = adoptWK(WKSecurityOriginCopyProtocol(securityOrigin));
 
268
        WKRetainPtr<WKStringRef> host = adoptWK(WKSecurityOriginCopyHost(securityOrigin));
 
269
 
 
270
        m_securityOrigin.setScheme(WKStringCopyQString(scheme.get()));
 
271
        m_securityOrigin.setHost(WKStringCopyQString(host.get()));
 
272
        m_securityOrigin.setPort(static_cast<int>(WKSecurityOriginGetPort(securityOrigin)));
 
273
 
 
274
        connect(this, SIGNAL(accepted(quint64)), SLOT(dismiss()));
 
275
        connect(this, SIGNAL(rejected()), SLOT(dismiss()));
 
276
    }
 
277
 
 
278
    QString databaseName() const { return m_databaseName; }
 
279
    QString displayName() const { return m_displayName; }
 
280
    quint64 currentQuota() const { return m_currentQuota; }
 
281
    quint64 currentOriginUsage() const { return m_currentOriginUsage; }
 
282
    quint64 currentDatabaseUsage() const { return m_currentDatabaseUsage; }
 
283
    quint64 expectedUsage() const { return m_expectedUsage; }
 
284
    QtWebSecurityOrigin* securityOrigin() { return &m_securityOrigin; }
 
285
 
 
286
public Q_SLOTS:
 
287
    void accept(quint64 size) { emit accepted(size); }
 
288
    void reject() { emit rejected(); }
 
289
 
 
290
Q_SIGNALS:
 
291
    void accepted(quint64 size);
 
292
    void rejected();
 
293
 
 
294
private:
 
295
    QString m_databaseName;
 
296
    QString m_displayName;
 
297
    quint64 m_currentQuota;
 
298
    quint64 m_currentOriginUsage;
 
299
    quint64 m_currentDatabaseUsage;
 
300
    quint64 m_expectedUsage;
 
301
    QtWebSecurityOrigin m_securityOrigin;
 
302
};
 
303
 
 
304
void QtDialogRunner::run()
 
305
{
 
306
    DialogContextBase* context = static_cast<DialogContextBase*>(m_dialogContext->contextObject());
 
307
 
 
308
    // We may have already been dismissed as part of Component.onCompleted()
 
309
    if (context->m_dismissed)
 
310
        return;
 
311
 
 
312
    connect(context, SIGNAL(dismissed()), SLOT(quit()));
 
313
    exec(); // Spin the event loop
 
314
}
 
315
 
 
316
bool QtDialogRunner::initForAlert(const QString& message)
 
317
{
 
318
    QQmlComponent* component = m_webView->experimental()->alertDialog();
 
319
    if (!component)
 
320
        return false;
 
321
 
 
322
    DialogContextObject* contextObject = new DialogContextObject(message);
 
323
 
 
324
    return createDialog(component, contextObject);
 
325
}
 
326
 
 
327
bool QtDialogRunner::initForConfirm(const QString& message)
 
328
{
 
329
    QQmlComponent* component = m_webView->experimental()->confirmDialog();
 
330
    if (!component)
 
331
        return false;
 
332
 
 
333
    DialogContextObject* contextObject = new DialogContextObject(message);
 
334
    connect(contextObject, SIGNAL(accepted(QString)), SLOT(onAccepted()));
 
335
 
 
336
    return createDialog(component, contextObject);
 
337
}
 
338
 
 
339
bool QtDialogRunner::initForPrompt(const QString& message, const QString& defaultValue)
 
340
{
 
341
    QQmlComponent* component = m_webView->experimental()->promptDialog();
 
342
    if (!component)
 
343
        return false;
 
344
 
 
345
    DialogContextObject* contextObject = new DialogContextObject(message, defaultValue);
 
346
    connect(contextObject, SIGNAL(accepted(QString)), SLOT(onAccepted(QString)));
 
347
 
 
348
    return createDialog(component, contextObject);
 
349
}
 
350
 
 
351
bool QtDialogRunner::initForAuthentication(const QString& hostname, const QString& realm, const QString& prefilledUsername)
 
352
{
 
353
    QQmlComponent* component = m_webView->experimental()->authenticationDialog();
 
354
    if (!component)
 
355
        return false;
 
356
 
 
357
    HttpAuthenticationDialogContextObject* contextObject = new HttpAuthenticationDialogContextObject(hostname, realm, prefilledUsername);
 
358
    connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(onAuthenticationAccepted(QString, QString)));
 
359
 
 
360
    return createDialog(component, contextObject);
 
361
}
 
362
 
 
363
bool QtDialogRunner::initForProxyAuthentication(const QString& hostname, uint16_t port, const QString& prefilledUsername)
 
364
{
 
365
    QQmlComponent* component = m_webView->experimental()->proxyAuthenticationDialog();
 
366
    if (!component)
 
367
        return false;
 
368
 
 
369
    ProxyAuthenticationDialogContextObject* contextObject = new ProxyAuthenticationDialogContextObject(hostname, port, prefilledUsername);
 
370
    connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(onAuthenticationAccepted(QString, QString)));
 
371
 
 
372
    return createDialog(component, contextObject);
 
373
}
 
374
 
 
375
bool QtDialogRunner::initForCertificateVerification(const QString& hostname)
 
376
{
 
377
    QQmlComponent* component = m_webView->experimental()->certificateVerificationDialog();
 
378
    if (!component)
 
379
        return false;
 
380
 
 
381
    CertificateVerificationDialogContextObject* contextObject = new CertificateVerificationDialogContextObject(hostname);
 
382
    connect(contextObject, SIGNAL(accepted()), SLOT(onAccepted()));
 
383
 
 
384
    return createDialog(component, contextObject);
 
385
}
 
386
 
 
387
bool QtDialogRunner::initForFilePicker(const QStringList& selectedFiles, bool allowMultiple)
 
388
{
 
389
    QQmlComponent* component = m_webView->experimental()->filePicker();
 
390
    if (!component)
 
391
        return false;
 
392
 
 
393
    FilePickerContextObject* contextObject = new FilePickerContextObject(selectedFiles, allowMultiple);
 
394
    connect(contextObject, SIGNAL(fileSelected(QStringList)), SLOT(onFileSelected(QStringList)));
 
395
 
 
396
    return createDialog(component, contextObject);
 
397
}
 
398
 
 
399
bool QtDialogRunner::initForDatabaseQuotaDialog(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage)
 
400
{
 
401
    QQmlComponent* component = m_webView->experimental()->databaseQuotaDialog();
 
402
    if (!component)
 
403
        return false;
 
404
 
 
405
    DatabaseQuotaDialogContextObject* contextObject = new DatabaseQuotaDialogContextObject(databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage);
 
406
    connect(contextObject, SIGNAL(accepted(quint64)), SLOT(onDatabaseQuotaAccepted(quint64)));
 
407
 
 
408
    return createDialog(component, contextObject);
 
409
}
 
410
 
 
411
bool QtDialogRunner::createDialog(QQmlComponent* component, QObject* contextObject)
 
412
{
 
413
    QQmlContext* baseContext = component->creationContext();
 
414
    if (!baseContext)
 
415
        baseContext = QQmlEngine::contextForObject(m_webView);
 
416
    m_dialogContext = adoptPtr(new QQmlContext(baseContext));
 
417
 
 
418
    // This makes both "message" and "model.message" work for the dialog,
 
419
    // just like QtQuick's ListView delegates.
 
420
    contextObject->setParent(m_dialogContext.get());
 
421
    m_dialogContext->setContextProperty(QLatin1String("model"), contextObject);
 
422
    m_dialogContext->setContextObject(contextObject);
 
423
 
 
424
    QObject* object = component->beginCreate(m_dialogContext.get());
 
425
    if (!object) {
 
426
        m_dialogContext.clear();
 
427
        return false;
 
428
    }
 
429
 
 
430
    m_dialog = adoptPtr(qobject_cast<QQuickItem*>(object));
 
431
    if (!m_dialog) {
 
432
        m_dialogContext.clear();
 
433
        m_dialog.clear();
 
434
        return false;
 
435
    }
 
436
 
 
437
    QQuickWebViewPrivate::get(m_webView)->addAttachedPropertyTo(m_dialog.get());
 
438
    m_dialog->setParentItem(m_webView);
 
439
 
 
440
    // Only fully create the component once we've set both a parent
 
441
    // and the needed context and attached properties, so that dialogs
 
442
    // can do useful stuff in their Component.onCompleted() method.
 
443
    component->completeCreate();
 
444
 
 
445
    // FIXME: As part of completeCreate, the bindings of the item will be
 
446
    // evaluated, but for some reason doing mapToItem/mapFromItem in a
 
447
    // binding will not work as expected, even if we at binding evaluation
 
448
    // time have the parent and all the way up to the root QML item.
 
449
    // As a workaround you can set whichever property you need in
 
450
    // Component.onCompleted, even to a binding using Qt.bind().
 
451
 
 
452
    return true;
 
453
}
 
454
 
 
455
void QtDialogRunner::onAccepted(const QString& result)
 
456
{
 
457
    m_wasAccepted = true;
 
458
    m_result = result;
 
459
}
 
460
 
 
461
void QtDialogRunner::onAuthenticationAccepted(const QString& username, const QString& password)
 
462
{
 
463
    m_username = username;
 
464
    m_password = password;
 
465
}
 
466
 
 
467
void QtDialogRunner::onFileSelected(const QStringList& filePaths)
 
468
{
 
469
    m_wasAccepted = true;
 
470
    m_filepaths = filePaths;
 
471
}
 
472
 
 
473
void QtDialogRunner::onDatabaseQuotaAccepted(quint64 quota)
 
474
{
 
475
    m_wasAccepted = true;
 
476
    m_databaseQuota = quota;
 
477
}
 
478
 
 
479
} // namespace WebKit
 
480
 
 
481
#include "QtDialogRunner.moc"
 
482
#include "moc_QtDialogRunner.cpp"
 
483