~ubuntu-branches/ubuntu/utopic/kde4libs/utopic

« back to all changes in this revision

Viewing changes to kdewebkit/kwebpage.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2012-10-02 15:22:43 UTC
  • mfrom: (1.14.22) (0.1.28 sid)
  • Revision ID: package-import@ubuntu.com-20121002152243-k5qvzmkyuioevedo
Tags: 4:4.9.2-0ubuntu1
* New upstream bugfix release
* New files in kdelibs5-dev.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
#include <kio/copyjob.h>
50
50
#include <kio/jobuidelegate.h>
51
51
#include <kio/renamedialog.h>
 
52
#include <kio/scheduler.h>
52
53
#include <kparts/browseropenorsavequestion.h>
53
54
 
54
55
// Qt
154
155
class KWebPage::KWebPagePrivate
155
156
{
156
157
public:
157
 
    KWebPagePrivate() : inPrivateBrowsingMode(false) {}
158
 
    void _k_copyResultToTempFile(KJob * job)
159
 
    {
160
 
        if ( job->error() ) {
161
 
            job->uiDelegate()->showErrorMessage();
162
 
            return;
163
 
        }
164
 
        // Same as KRun::foundMimeType but with a different URL
165
 
        (void)KRun::runUrl(static_cast<KIO::FileCopyJob *>(job)->destUrl(), mimeType, window);
166
 
    }
167
 
 
 
158
    KWebPagePrivate(KWebPage* page)
 
159
        : q(page)
 
160
          , inPrivateBrowsingMode(false)
 
161
    {
 
162
    }
 
163
 
 
164
    QWidget* windowWidget()
 
165
    {
 
166
        return (window ? window.data() : q->view());
 
167
    }
 
168
 
 
169
    void _k_copyResultToTempFile(KJob* job)
 
170
    {
 
171
        KIO::FileCopyJob* cJob = qobject_cast<KIO::FileCopyJob *>(job);
 
172
        if (cJob && !cJob->error() ) {
 
173
            // Same as KRun::foundMimeType but with a different URL
 
174
            (void)KRun::runUrl(cJob->destUrl(), mimeType, window);
 
175
        }
 
176
    }
 
177
 
 
178
    void _k_receivedContentType(KIO::Job* job, const QString& mimetype)
 
179
    {
 
180
        KIO::TransferJob* tJob = qobject_cast<KIO::TransferJob*>(job);
 
181
        if (tJob && !tJob->error()) {
 
182
            tJob->putOnHold();
 
183
            KIO::Scheduler::publishSlaveOnHold();
 
184
            // Get suggested file name...
 
185
            mimeType = mimetype;
 
186
            const QString suggestedFileName (tJob->queryMetaData(QL1S("content-disposition-filename")));
 
187
            // kDebug(800) << "suggested filename:" << suggestedFileName << ", mimetype:" << mimetype;
 
188
            (void) downloadResource(tJob->url(), suggestedFileName, window, tJob->metaData());
 
189
        }
 
190
    }
 
191
 
 
192
    void _k_contentTypeCheckFailed(KJob* job)
 
193
    {
 
194
        KIO::TransferJob* tJob = qobject_cast<KIO::TransferJob*>(job);
 
195
        // On error simply call downloadResource which will probably fail as well.
 
196
        if (tJob && tJob->error()) {
 
197
            (void)downloadResource(tJob->url(), QString(), window, tJob->metaData());
 
198
        }
 
199
    }
 
200
 
 
201
    KWebPage* q;
168
202
    QPointer<QWidget> window;
169
203
    QString mimeType;
170
204
    QPointer<KWebWallet> wallet;
186
220
}
187
221
 
188
222
KWebPage::KWebPage(QObject *parent, Integration flags)
189
 
         :QWebPage(parent), d(new KWebPagePrivate)
 
223
         :QWebPage(parent), d(new KWebPagePrivate(this))
190
224
191
225
    // KDE KParts integration for <embed> tag...
192
226
    if (!flags || (flags & KPartsIntegration))
193
227
        setPluginFactory(new KWebPluginFactory(this));
194
228
 
195
229
    QWidget *parentWidget = qobject_cast<QWidget*>(parent);
196
 
    QWidget *window = parentWidget ? parentWidget->window() : 0;
 
230
    d->window = (parentWidget ? parentWidget->window() : 0);
197
231
 
198
232
    // KDE IO (KIO) integration...
199
233
    if (!flags || (flags & KIOIntegration)) {
200
234
        KIO::Integration::AccessManager *manager = new KIO::Integration::AccessManager(this);
201
235
        // Disable QtWebKit's internal cache to avoid duplication with the one in KIO...
202
236
        manager->setCache(0);
203
 
        manager->setWindow(window);
 
237
        manager->setWindow(d->window);
204
238
        manager->setEmitReadyReadOnMetaDataChange(true);
205
239
        setNetworkAccessManager(manager);
206
240
    }
207
241
 
208
242
    // KWallet integration...
209
243
    if (!flags || (flags & KWalletIntegration)) {
210
 
        setWallet(new KWebWallet(0, (window ? window->winId() : 0) ));
 
244
        setWallet(new KWebWallet(0, (d->window ? d->window->winId() : 0) ));
211
245
    }
212
246
 
213
247
    setActionIcon(action(Back), KIcon("go-previous"));
284
318
        d->wallet->setParent(this);
285
319
}
286
320
 
287
 
void KWebPage::downloadRequest(const QNetworkRequest &request)
 
321
 
 
322
void KWebPage::downloadRequest(const QNetworkRequest& request)
288
323
{
289
 
    downloadResource(request.url(), QString(), view(),
290
 
                     request.attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap());
 
324
    KIO::TransferJob* job = KIO::get(request.url());
 
325
    connect(job, SIGNAL(mimetype(KIO::Job*,QString)),
 
326
            this, SLOT(_k_receivedContentType(KIO::Job*,QString)));
 
327
    connect(job, SIGNAL(result(KJob*)),
 
328
            this, SLOT(_k_receivedContentTypeResult(KJob*)));
 
329
 
 
330
    job->setMetaData(request.attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap());
 
331
    job->addMetaData(QL1S("MaxCacheSize"), QL1S("0")); // Don't store in http cache.
 
332
    job->addMetaData(QL1S("cache"), QL1S("cache")); // Use entry from cache if available.
 
333
    job->ui()->setWindow(d->windowWidget());
291
334
}
292
335
 
293
336
void KWebPage::downloadUrl(const KUrl &url)
294
337
{
295
 
    downloadResource(url, QString(), view());
 
338
    downloadRequest(QNetworkRequest(url));
296
339
}
297
340
 
298
341
void KWebPage::downloadResponse(QNetworkReply *reply)
313
356
    }
314
357
 
315
358
    const KUrl replyUrl (reply->url());
316
 
    QWidget* topLevelWindow = view() ? view()->window() : 0;
317
359
 
318
360
    // Ask KRun to handle the response when mimetype is unknown
319
361
    if (mimeType.isEmpty()) {
320
 
        (void)new KRun(replyUrl, topLevelWindow, 0 , replyUrl.isLocalFile());
 
362
        (void)new KRun(replyUrl, d->windowWidget(), 0 , replyUrl.isLocalFile());
321
363
        return;
322
364
    }
323
365
 
324
366
    // Ask KRun::runUrl to handle the response when mimetype is inode/*
325
367
    if (mimeType.startsWith(QL1S("inode/"), Qt::CaseInsensitive) &&
326
 
        KRun::runUrl(replyUrl, mimeType, topLevelWindow, false, false,
 
368
        KRun::runUrl(replyUrl, mimeType, d->windowWidget(), false, false,
327
369
                     metaData.value(QL1S("content-disposition-filename")))) {
328
370
        return;
329
371
    }
438
480
    // Reply url...
439
481
    const KUrl replyUrl (reply->url());
440
482
 
441
 
    // Get the top level window...
442
 
    QWidget* topLevelWindow = view() ? view()->window() : 0;
443
 
 
444
483
    // Get suggested file name...
445
484
    const KIO::MetaData& data = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap();
446
485
    const QString suggestedFileName = data.value(QL1S("content-disposition-filename"));
469
508
    //kDebug(800) << "Error code:" << reply->error() << reply->errorString();
470
509
 
471
510
    if (isReplyStatusOk(reply)) {
472
 
        KParts::BrowserOpenOrSaveQuestion::Result result;
473
 
        KParts::BrowserOpenOrSaveQuestion dlg(topLevelWindow, replyUrl, mimeType);
474
 
        dlg.setSuggestedFileName(suggestedFileName);
475
 
        dlg.setFeatures(KParts::BrowserOpenOrSaveQuestion::ServiceSelection);
476
 
        result = dlg.askOpenOrSave();
477
 
 
478
 
        switch (result) {
479
 
        case KParts::BrowserOpenOrSaveQuestion::Open:
480
 
            // Handle Post operations that return content...
481
 
            if (reply->operation() == QNetworkAccessManager::PostOperation) {
482
 
                d->mimeType = mimeType;
483
 
                d->window = topLevelWindow;
484
 
                QFileInfo finfo (suggestedFileName.isEmpty() ? replyUrl.fileName() : suggestedFileName);
485
 
                KTemporaryFile tempFile;
486
 
                tempFile.setSuffix(QL1C('.') + finfo.suffix());
487
 
                tempFile.setAutoRemove(false);
488
 
                tempFile.open();
489
 
                KUrl destUrl;
490
 
                destUrl.setPath(tempFile.fileName());
491
 
                KIO::Job *job = KIO::file_copy(replyUrl, destUrl, 0600, KIO::Overwrite);
492
 
                job->ui()->setWindow(topLevelWindow);
493
 
                job->ui()->setAutoErrorHandlingEnabled(true);
494
 
                connect(job, SIGNAL(result(KJob*)),
495
 
                        this, SLOT(_k_copyResultToTempFile(KJob*)));
496
 
                return true;
497
 
            }
498
 
 
499
 
            // Ask before running any executables...
500
 
            if (KParts::BrowserRun::allowExecution(mimeType, replyUrl)) {
501
 
                KService::Ptr offer = dlg.selectedService();
502
 
                // HACK: The check below is necessary to break an infinite
503
 
                // recursion that occurs whenever this function is called as a result
504
 
                // of receiving content that can be rendered by the app using this engine.
505
 
                // For example a text/html header that containing a content-disposition
506
 
                // header is received by the app using this class.
507
 
                if (isMimeTypeAssociatedWithSelf(offer)) {
508
 
                    reloadRequestWithoutDisposition(reply);
509
 
                } else {
510
 
                    KUrl::List list;
511
 
                    list.append(replyUrl);
512
 
                    bool success = false;
513
 
                    // kDebug(800) << "Suggested file name:" << suggestedFileName;
514
 
                    if (offer) {
515
 
                        success = KRun::run(*offer, list, topLevelWindow , false, suggestedFileName);
 
511
        while (true) {
 
512
            KParts::BrowserOpenOrSaveQuestion::Result result;
 
513
            KParts::BrowserOpenOrSaveQuestion dlg(d->windowWidget(), replyUrl, mimeType);
 
514
            dlg.setSuggestedFileName(suggestedFileName);
 
515
            dlg.setFeatures(KParts::BrowserOpenOrSaveQuestion::ServiceSelection);
 
516
            result = dlg.askOpenOrSave();
 
517
 
 
518
            switch (result) {
 
519
            case KParts::BrowserOpenOrSaveQuestion::Open:
 
520
                // Handle Post operations that return content...
 
521
                if (reply->operation() == QNetworkAccessManager::PostOperation) {
 
522
                    d->mimeType = mimeType;
 
523
                    QFileInfo finfo (suggestedFileName.isEmpty() ? replyUrl.fileName() : suggestedFileName);
 
524
                    KTemporaryFile tempFile;
 
525
                    tempFile.setSuffix(QL1C('.') + finfo.suffix());
 
526
                    tempFile.setAutoRemove(false);
 
527
                    tempFile.open();
 
528
                    KUrl destUrl;
 
529
                    destUrl.setPath(tempFile.fileName());
 
530
                    KIO::Job *job = KIO::file_copy(replyUrl, destUrl, 0600, KIO::Overwrite);
 
531
                    job->ui()->setWindow(d->windowWidget());
 
532
                    job->ui()->setAutoErrorHandlingEnabled(true);
 
533
                    connect(job, SIGNAL(result(KJob*)),
 
534
                            this, SLOT(_k_copyResultToTempFile(KJob*)));
 
535
                    return true;
 
536
                }
 
537
 
 
538
                // Ask before running any executables...
 
539
                if (KParts::BrowserRun::allowExecution(mimeType, replyUrl)) {
 
540
                    KService::Ptr offer = dlg.selectedService();
 
541
                    // HACK: The check below is necessary to break an infinite
 
542
                    // recursion that occurs whenever this function is called as a result
 
543
                    // of receiving content that can be rendered by the app using this engine.
 
544
                    // For example a text/html header that containing a content-disposition
 
545
                    // header is received by the app using this class.
 
546
                    if (isMimeTypeAssociatedWithSelf(offer)) {
 
547
                        reloadRequestWithoutDisposition(reply);
516
548
                    } else {
517
 
                        success = KRun::displayOpenWithDialog(list, topLevelWindow, false, suggestedFileName);
518
 
                    }
519
 
                    // For non KIO apps and cancelled Open With dialog, remove slave on hold.
520
 
                    if (!success || (offer && !offer->categories().contains(QL1S("KDE")))) {
521
 
                        KIO::SimpleJob::removeOnHold(); // Remove any slave-on-hold...
522
 
                    }
 
549
                        KUrl::List list;
 
550
                        list.append(replyUrl);
 
551
                        bool success = false;
 
552
                        // kDebug(800) << "Suggested file name:" << suggestedFileName;
 
553
                        if (offer) {
 
554
                            success = KRun::run(*offer, list, d->windowWidget() , false, suggestedFileName);
 
555
                        } else {
 
556
                            success = KRun::displayOpenWithDialog(list, d->windowWidget(), false, suggestedFileName);
 
557
                            if (!success)
 
558
                                break;
 
559
                        }
 
560
                        // For non KIO apps and cancelled Open With dialog, remove slave on hold.
 
561
                        if (!success || (offer && !offer->categories().contains(QL1S("KDE")))) {
 
562
                            KIO::SimpleJob::removeOnHold(); // Remove any slave-on-hold...
 
563
                        }
 
564
                    }
 
565
                    return true;
523
566
                }
524
 
                return true;
525
 
            }
526
 
            // TODO: Instead of silently failing when allowExecution fails, notify
527
 
            // the user why the requested action cannot be fulfilled...
528
 
            break;
529
 
        case KParts::BrowserOpenOrSaveQuestion::Save:
530
 
            // Do not download local files...
531
 
            if (!replyUrl.isLocalFile()) {
532
 
                QString downloadCmd (reply->property("DownloadManagerExe").toString());
533
 
                if (!downloadCmd.isEmpty()) {
534
 
                    downloadCmd += QLatin1Char(' ');
535
 
                    downloadCmd += KShell::quoteArg(replyUrl.url());
536
 
                    if (!suggestedFileName.isEmpty()) {
 
567
                // TODO: Instead of silently failing when allowExecution fails, notify
 
568
                // the user why the requested action cannot be fulfilled...
 
569
                return false;
 
570
            case KParts::BrowserOpenOrSaveQuestion::Save:
 
571
                // Do not download local files...
 
572
                if (!replyUrl.isLocalFile()) {
 
573
                    QString downloadCmd (reply->property("DownloadManagerExe").toString());
 
574
                    if (!downloadCmd.isEmpty()) {
537
575
                        downloadCmd += QLatin1Char(' ');
538
 
                        downloadCmd += KShell::quoteArg(suggestedFileName);
 
576
                        downloadCmd += KShell::quoteArg(replyUrl.url());
 
577
                        if (!suggestedFileName.isEmpty()) {
 
578
                            downloadCmd += QLatin1Char(' ');
 
579
                            downloadCmd += KShell::quoteArg(suggestedFileName);
 
580
                        }
 
581
                        // kDebug(800) << "download command:" << downloadCmd;
 
582
                        if (KRun::runCommand(downloadCmd, view()))
 
583
                            return true;
539
584
                    }
540
 
                    // kDebug(800) << "download command:" << downloadCmd;
541
 
                    if (KRun::runCommand(downloadCmd, view()))
542
 
                        return true;
 
585
                    if (!downloadResource(replyUrl, suggestedFileName, d->windowWidget()))
 
586
                        break;
543
587
                }
544
 
                return downloadResource(replyUrl, suggestedFileName, topLevelWindow);
 
588
                return true;
 
589
            case KParts::BrowserOpenOrSaveQuestion::Cancel:
 
590
            default:
 
591
                KIO::SimpleJob::removeOnHold(); // Remove any slave-on-hold...
 
592
                return true;
545
593
            }
546
 
            return true;
547
 
        case KParts::BrowserOpenOrSaveQuestion::Cancel:
548
 
        default:
549
 
            return true;
550
594
        }
551
595
    } else {
552
596
        KService::Ptr offer = KMimeTypeTrader::self()->preferredService(mimeType);