KDEWebKit
kwebpage.cpp
Go to the documentation of this file.
00001 /* 00002 * This file is part of the KDE project. 00003 * 00004 * Copyright (C) 2008 Dirk Mueller <mueller@kde.org> 00005 * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> 00006 * Copyright (C) 2008 Michael Howell <mhowell123@gmail.com> 00007 * Copyright (C) 2009,2010 Dawit Alemayehu <adawit@kde.org> 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Library General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Library General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Library General Public License 00020 * along with this library; see the file COPYING.LIB. If not, write to 00021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00022 * Boston, MA 02110-1301, USA. 00023 * 00024 */ 00025 00026 // Own 00027 #include "kwebpage.h" 00028 #include "kwebwallet.h" 00029 00030 // Local 00031 #include "kwebpluginfactory.h" 00032 00033 // KDE 00034 #include <kaction.h> 00035 #include <kfiledialog.h> 00036 #include <kprotocolmanager.h> 00037 #include <kjobuidelegate.h> 00038 #include <krun.h> 00039 #include <kstandarddirs.h> 00040 #include <kstandardshortcut.h> 00041 #include <kurl.h> 00042 #include <kdebug.h> 00043 #include <kshell.h> 00044 #include <kmimetypetrader.h> 00045 #include <klocalizedstring.h> 00046 #include <ktemporaryfile.h> 00047 #include <kio/accessmanager.h> 00048 #include <kio/job.h> 00049 #include <kio/copyjob.h> 00050 #include <kio/jobuidelegate.h> 00051 #include <kio/renamedialog.h> 00052 #include <kio/scheduler.h> 00053 #include <kparts/browseropenorsavequestion.h> 00054 00055 // Qt 00056 #include <QtCore/QPointer> 00057 #include <QtCore/QFileInfo> 00058 #include <QtCore/QCoreApplication> 00059 #include <QtWebKit/QWebFrame> 00060 #include <QtNetwork/QNetworkReply> 00061 00062 00063 #define QL1S(x) QLatin1String(x) 00064 #define QL1C(x) QLatin1Char(x) 00065 00066 static void reloadRequestWithoutDisposition (QNetworkReply* reply) 00067 { 00068 QNetworkRequest req (reply->request()); 00069 req.setRawHeader("x-kdewebkit-ignore-disposition", "true"); 00070 00071 QWebFrame* frame = qobject_cast<QWebFrame*> (req.originatingObject()); 00072 if (!frame) 00073 return; 00074 00075 frame->load(req); 00076 } 00077 00078 static bool isMimeTypeAssociatedWithSelf(const KService::Ptr &offer) 00079 { 00080 if (!offer) 00081 return false; 00082 00083 kDebug(800) << offer->desktopEntryName(); 00084 00085 const QString& appName = QCoreApplication::applicationName(); 00086 00087 if (appName == offer->desktopEntryName() || offer->exec().trimmed().startsWith(appName)) 00088 return true; 00089 00090 // konqueror exception since it uses kfmclient to open html content... 00091 if (appName == QL1S("konqueror") && offer->exec().trimmed().startsWith(QL1S("kfmclient"))) 00092 return true; 00093 00094 return false; 00095 } 00096 00097 static void extractMimeType(const QNetworkReply* reply, QString& mimeType) 00098 { 00099 mimeType.clear(); 00100 const KIO::MetaData& metaData = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap(); 00101 if (metaData.contains(QL1S("content-type"))) 00102 mimeType = metaData.value(QL1S("content-type")); 00103 00104 if (!mimeType.isEmpty()) 00105 return; 00106 00107 if (!reply->hasRawHeader("Content-Type")) 00108 return; 00109 00110 const QString value (QL1S(reply->rawHeader("Content-Type").simplified().constData())); 00111 const int index = value.indexOf(QL1C(';')); 00112 mimeType = ((index == -1) ? value : value.left(index)); 00113 } 00114 00115 static bool downloadResource (const KUrl& srcUrl, const QString& suggestedName = QString(), 00116 QWidget* parent = 0, const KIO::MetaData& metaData = KIO::MetaData()) 00117 { 00118 const QString fileName = suggestedName.isEmpty() ? srcUrl.fileName() : suggestedName; 00119 // convert filename to URL using fromPath to avoid trouble with ':' in filenames (#184202) 00120 KUrl destUrl = KFileDialog::getSaveFileName(KUrl::fromPath(fileName), QString(), parent); 00121 if (!destUrl.isValid()) 00122 return false; 00123 00124 // Using KIO::copy rather than file_copy, to benefit from "dest already exists" dialogs. 00125 KIO::Job *job = KIO::copy(srcUrl, destUrl); 00126 00127 if (!metaData.isEmpty()) 00128 job->setMetaData(metaData); 00129 00130 job->addMetaData(QL1S("MaxCacheSize"), QL1S("0")); // Don't store in http cache. 00131 job->addMetaData(QL1S("cache"), QL1S("cache")); // Use entry from cache if available. 00132 job->ui()->setWindow((parent ? parent->window() : 0)); 00133 job->ui()->setAutoErrorHandlingEnabled(true); 00134 return true; 00135 } 00136 00137 static bool isReplyStatusOk(const QNetworkReply* reply) 00138 { 00139 if (!reply || reply->error() != QNetworkReply::NoError) 00140 return false; 00141 00142 // Check HTTP status code only for http and webdav protocols... 00143 const QString scheme = reply->url().scheme(); 00144 if (scheme.startsWith(QLatin1String("http"), Qt::CaseInsensitive) || 00145 scheme.startsWith(QLatin1String("webdav"), Qt::CaseInsensitive)) { 00146 bool ok = false; 00147 const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok); 00148 if (!ok || statusCode < 200 || statusCode > 299) 00149 return false; 00150 } 00151 00152 return true; 00153 } 00154 00155 class KWebPage::KWebPagePrivate 00156 { 00157 public: 00158 KWebPagePrivate(KWebPage* page) 00159 : q(page) 00160 , inPrivateBrowsingMode(false) 00161 { 00162 } 00163 00164 QWidget* windowWidget() 00165 { 00166 return (window ? window.data() : q->view()); 00167 } 00168 00169 void _k_copyResultToTempFile(KJob* job) 00170 { 00171 KIO::FileCopyJob* cJob = qobject_cast<KIO::FileCopyJob *>(job); 00172 if (cJob && !cJob->error() ) { 00173 // Same as KRun::foundMimeType but with a different URL 00174 (void)KRun::runUrl(cJob->destUrl(), mimeType, window); 00175 } 00176 } 00177 00178 void _k_receivedContentType(KIO::Job* job, const QString& mimetype) 00179 { 00180 KIO::TransferJob* tJob = qobject_cast<KIO::TransferJob*>(job); 00181 if (tJob && !tJob->error()) { 00182 tJob->putOnHold(); 00183 KIO::Scheduler::publishSlaveOnHold(); 00184 // Get suggested file name... 00185 mimeType = mimetype; 00186 const QString suggestedFileName (tJob->queryMetaData(QL1S("content-disposition-filename"))); 00187 // kDebug(800) << "suggested filename:" << suggestedFileName << ", mimetype:" << mimetype; 00188 (void) downloadResource(tJob->url(), suggestedFileName, window, tJob->metaData()); 00189 } 00190 } 00191 00192 void _k_contentTypeCheckFailed(KJob* job) 00193 { 00194 KIO::TransferJob* tJob = qobject_cast<KIO::TransferJob*>(job); 00195 // On error simply call downloadResource which will probably fail as well. 00196 if (tJob && tJob->error()) { 00197 (void)downloadResource(tJob->url(), QString(), window, tJob->metaData()); 00198 } 00199 } 00200 00201 KWebPage* q; 00202 QPointer<QWidget> window; 00203 QString mimeType; 00204 QPointer<KWebWallet> wallet; 00205 bool inPrivateBrowsingMode; 00206 }; 00207 00208 static void setActionIcon(QAction* action, const QIcon& icon) 00209 { 00210 if (action) { 00211 action->setIcon(icon); 00212 } 00213 } 00214 00215 static void setActionShortcut(QAction* action, const KShortcut& shortcut) 00216 { 00217 if (action) { 00218 action->setShortcuts(shortcut.toList()); 00219 } 00220 } 00221 00222 KWebPage::KWebPage(QObject *parent, Integration flags) 00223 :QWebPage(parent), d(new KWebPagePrivate(this)) 00224 { 00225 // KDE KParts integration for <embed> tag... 00226 if (!flags || (flags & KPartsIntegration)) 00227 setPluginFactory(new KWebPluginFactory(this)); 00228 00229 QWidget *parentWidget = qobject_cast<QWidget*>(parent); 00230 d->window = (parentWidget ? parentWidget->window() : 0); 00231 00232 // KDE IO (KIO) integration... 00233 if (!flags || (flags & KIOIntegration)) { 00234 KIO::Integration::AccessManager *manager = new KIO::Integration::AccessManager(this); 00235 // Disable QtWebKit's internal cache to avoid duplication with the one in KIO... 00236 manager->setCache(0); 00237 manager->setWindow(d->window); 00238 manager->setEmitReadyReadOnMetaDataChange(true); 00239 setNetworkAccessManager(manager); 00240 } 00241 00242 // KWallet integration... 00243 if (!flags || (flags & KWalletIntegration)) { 00244 setWallet(new KWebWallet(0, (d->window ? d->window->winId() : 0) )); 00245 } 00246 00247 setActionIcon(action(Back), KIcon("go-previous")); 00248 setActionIcon(action(Forward), KIcon("go-next")); 00249 setActionIcon(action(Reload), KIcon("view-refresh")); 00250 setActionIcon(action(Stop), KIcon("process-stop")); 00251 setActionIcon(action(Cut), KIcon("edit-cut")); 00252 setActionIcon(action(Copy), KIcon("edit-copy")); 00253 setActionIcon(action(Paste), KIcon("edit-paste")); 00254 setActionIcon(action(Undo), KIcon("edit-undo")); 00255 setActionIcon(action(Redo), KIcon("edit-redo")); 00256 setActionIcon(action(InspectElement), KIcon("view-process-all")); 00257 setActionIcon(action(OpenLinkInNewWindow), KIcon("window-new")); 00258 setActionIcon(action(OpenFrameInNewWindow), KIcon("window-new")); 00259 setActionIcon(action(OpenImageInNewWindow), KIcon("window-new")); 00260 setActionIcon(action(CopyLinkToClipboard), KIcon("edit-copy")); 00261 setActionIcon(action(CopyImageToClipboard), KIcon("edit-copy")); 00262 setActionIcon(action(ToggleBold), KIcon("format-text-bold")); 00263 setActionIcon(action(ToggleItalic), KIcon("format-text-italic")); 00264 setActionIcon(action(ToggleUnderline), KIcon("format-text-underline")); 00265 setActionIcon(action(DownloadLinkToDisk), KIcon("document-save")); 00266 setActionIcon(action(DownloadImageToDisk), KIcon("document-save")); 00267 00268 settings()->setWebGraphic(QWebSettings::MissingPluginGraphic, KIcon("preferences-plugin").pixmap(32, 32)); 00269 settings()->setWebGraphic(QWebSettings::MissingImageGraphic, KIcon("image-missing").pixmap(32, 32)); 00270 settings()->setWebGraphic(QWebSettings::DefaultFrameIconGraphic, KIcon("applications-internet").pixmap(32, 32)); 00271 00272 setActionShortcut(action(Back), KStandardShortcut::back()); 00273 setActionShortcut(action(Forward), KStandardShortcut::forward()); 00274 setActionShortcut(action(Reload), KStandardShortcut::reload()); 00275 setActionShortcut(action(Stop), KShortcut(QKeySequence(Qt::Key_Escape))); 00276 setActionShortcut(action(Cut), KStandardShortcut::cut()); 00277 setActionShortcut(action(Copy), KStandardShortcut::copy()); 00278 setActionShortcut(action(Paste), KStandardShortcut::paste()); 00279 setActionShortcut(action(Undo), KStandardShortcut::undo()); 00280 setActionShortcut(action(Redo), KStandardShortcut::redo()); 00281 setActionShortcut(action(SelectAll), KStandardShortcut::selectAll()); 00282 } 00283 00284 KWebPage::~KWebPage() 00285 { 00286 delete d; 00287 } 00288 00289 bool KWebPage::isExternalContentAllowed() const 00290 { 00291 KIO::AccessManager *manager = qobject_cast<KIO::AccessManager*>(networkAccessManager()); 00292 if (manager) 00293 return manager->isExternalContentAllowed(); 00294 return true; 00295 } 00296 00297 KWebWallet *KWebPage::wallet() const 00298 { 00299 return d->wallet; 00300 } 00301 00302 void KWebPage::setAllowExternalContent(bool allow) 00303 { 00304 KIO::AccessManager *manager = qobject_cast<KIO::AccessManager*>(networkAccessManager()); 00305 if (manager) 00306 manager->setExternalContentAllowed(allow); 00307 } 00308 00309 void KWebPage::setWallet(KWebWallet* wallet) 00310 { 00311 // Delete the current wallet if this object is its parent... 00312 if (d->wallet && this == d->wallet->parent()) 00313 delete d->wallet; 00314 00315 d->wallet = wallet; 00316 00317 if (d->wallet) 00318 d->wallet->setParent(this); 00319 } 00320 00321 00322 void KWebPage::downloadRequest(const QNetworkRequest& request) 00323 { 00324 KIO::TransferJob* job = KIO::get(request.url()); 00325 connect(job, SIGNAL(mimetype(KIO::Job*,QString)), 00326 this, SLOT(_k_receivedContentType(KIO::Job*,QString))); 00327 connect(job, SIGNAL(result(KJob*)), 00328 this, SLOT(_k_receivedContentTypeResult(KJob*))); 00329 00330 job->setMetaData(request.attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap()); 00331 job->addMetaData(QL1S("MaxCacheSize"), QL1S("0")); // Don't store in http cache. 00332 job->addMetaData(QL1S("cache"), QL1S("cache")); // Use entry from cache if available. 00333 job->ui()->setWindow(d->windowWidget()); 00334 } 00335 00336 void KWebPage::downloadUrl(const KUrl &url) 00337 { 00338 downloadRequest(QNetworkRequest(url)); 00339 } 00340 00341 void KWebPage::downloadResponse(QNetworkReply *reply) 00342 { 00343 Q_ASSERT(reply); 00344 00345 if (!reply) 00346 return; 00347 00348 // Put the job on hold only for the protocols we know about (read: http). 00349 KIO::Integration::AccessManager::putReplyOnHold(reply); 00350 00351 QString mimeType; 00352 KIO::MetaData metaData; 00353 00354 if (handleReply(reply, &mimeType, &metaData)) { 00355 return; 00356 } 00357 00358 const KUrl replyUrl (reply->url()); 00359 00360 // Ask KRun to handle the response when mimetype is unknown 00361 if (mimeType.isEmpty()) { 00362 (void)new KRun(replyUrl, d->windowWidget(), 0 , replyUrl.isLocalFile()); 00363 return; 00364 } 00365 00366 // Ask KRun::runUrl to handle the response when mimetype is inode/* 00367 if (mimeType.startsWith(QL1S("inode/"), Qt::CaseInsensitive) && 00368 KRun::runUrl(replyUrl, mimeType, d->windowWidget(), false, false, 00369 metaData.value(QL1S("content-disposition-filename")))) { 00370 return; 00371 } 00372 } 00373 00374 QString KWebPage::sessionMetaData(const QString &key) const 00375 { 00376 QString value; 00377 00378 KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager()); 00379 if (manager) 00380 value = manager->sessionMetaData().value(key); 00381 00382 return value; 00383 } 00384 00385 QString KWebPage::requestMetaData(const QString &key) const 00386 { 00387 QString value; 00388 00389 KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager()); 00390 if (manager) 00391 value = manager->requestMetaData().value(key); 00392 00393 return value; 00394 } 00395 00396 void KWebPage::setSessionMetaData(const QString &key, const QString &value) 00397 { 00398 KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager()); 00399 if (manager) 00400 manager->sessionMetaData()[key] = value; 00401 } 00402 00403 void KWebPage::setRequestMetaData(const QString &key, const QString &value) 00404 { 00405 KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager()); 00406 if (manager) 00407 manager->requestMetaData()[key] = value; 00408 } 00409 00410 void KWebPage::removeSessionMetaData(const QString &key) 00411 { 00412 KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager()); 00413 if (manager) 00414 manager->sessionMetaData().remove(key); 00415 } 00416 00417 void KWebPage::removeRequestMetaData(const QString &key) 00418 { 00419 KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager()); 00420 if (manager) 00421 manager->requestMetaData().remove(key); 00422 } 00423 00424 QString KWebPage::userAgentForUrl(const QUrl& _url) const 00425 { 00426 const KUrl url(_url); 00427 const QString userAgent = KProtocolManager::userAgentForHost((url.isLocalFile() ? QL1S("localhost") : url.host())); 00428 00429 if (userAgent == KProtocolManager::defaultUserAgent()) 00430 return QWebPage::userAgentForUrl(_url); 00431 00432 return userAgent; 00433 } 00434 00435 static void setDisableCookieJarStorage(QNetworkAccessManager* manager, bool status) 00436 { 00437 if (manager) { 00438 KIO::Integration::CookieJar *cookieJar = manager ? qobject_cast<KIO::Integration::CookieJar*>(manager->cookieJar()) : 0; 00439 if (cookieJar) { 00440 //kDebug(800) << "Store cookies ?" << !status; 00441 cookieJar->setDisableCookieStorage(status); 00442 } 00443 } 00444 } 00445 00446 bool KWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type) 00447 { 00448 kDebug(800) << "url:" << request.url() << ", type:" << type << ", frame:" << frame; 00449 00450 if (frame && d->wallet && type == QWebPage::NavigationTypeFormSubmitted) 00451 d->wallet->saveFormData(frame); 00452 00453 // Make sure nothing is cached when private browsing mode is enabled... 00454 if (settings()->testAttribute(QWebSettings::PrivateBrowsingEnabled)) { 00455 if (!d->inPrivateBrowsingMode) { 00456 setDisableCookieJarStorage(networkAccessManager(), true); 00457 setSessionMetaData(QL1S("no-cache"), QL1S("true")); 00458 d->inPrivateBrowsingMode = true; 00459 } 00460 } else { 00461 if (d->inPrivateBrowsingMode) { 00462 setDisableCookieJarStorage(networkAccessManager(), false); 00463 removeSessionMetaData(QL1S("no-cache")); 00464 d->inPrivateBrowsingMode = false; 00465 } 00466 } 00467 00468 /* 00469 If the navigation request is from the main frame, set the cross-domain 00470 meta-data value to the current url for proper integration with KCookieJar... 00471 */ 00472 if (frame == mainFrame() && type != QWebPage::NavigationTypeReload) 00473 setSessionMetaData(QL1S("cross-domain"), request.url().toString()); 00474 00475 return QWebPage::acceptNavigationRequest(frame, request, type); 00476 } 00477 00478 bool KWebPage::handleReply(QNetworkReply* reply, QString* contentType, KIO::MetaData* metaData) 00479 { 00480 // Reply url... 00481 const KUrl replyUrl (reply->url()); 00482 00483 // Get suggested file name... 00484 const KIO::MetaData& data = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap(); 00485 const QString suggestedFileName = data.value(QL1S("content-disposition-filename")); 00486 if (metaData) { 00487 *metaData = data; 00488 } 00489 00490 // Get the mime-type... 00491 QString mimeType; 00492 extractMimeType(reply, mimeType); 00493 if (contentType) { 00494 *contentType = mimeType; 00495 } 00496 00497 // Let the calling function deal with handling empty or inode/* mimetypes... 00498 if (mimeType.isEmpty() || mimeType.startsWith(QL1S("inode/"), Qt::CaseInsensitive)) { 00499 return false; 00500 } 00501 00502 // Convert executable text files to plain text... 00503 if (KParts::BrowserRun::isTextExecutable(mimeType)) 00504 mimeType = QL1S("text/plain"); 00505 00506 //kDebug(800) << "Content-disposition:" << suggestedFileName; 00507 //kDebug(800) << "Got unsupported content of type:" << mimeType << "URL:" << replyUrl; 00508 //kDebug(800) << "Error code:" << reply->error() << reply->errorString(); 00509 00510 if (isReplyStatusOk(reply)) { 00511 while (true) { 00512 KParts::BrowserOpenOrSaveQuestion::Result result; 00513 KParts::BrowserOpenOrSaveQuestion dlg(d->windowWidget(), replyUrl, mimeType); 00514 dlg.setSuggestedFileName(suggestedFileName); 00515 dlg.setFeatures(KParts::BrowserOpenOrSaveQuestion::ServiceSelection); 00516 result = dlg.askOpenOrSave(); 00517 00518 switch (result) { 00519 case KParts::BrowserOpenOrSaveQuestion::Open: 00520 // Handle Post operations that return content... 00521 if (reply->operation() == QNetworkAccessManager::PostOperation) { 00522 d->mimeType = mimeType; 00523 QFileInfo finfo (suggestedFileName.isEmpty() ? replyUrl.fileName() : suggestedFileName); 00524 KTemporaryFile tempFile; 00525 tempFile.setSuffix(QL1C('.') + finfo.suffix()); 00526 tempFile.setAutoRemove(false); 00527 tempFile.open(); 00528 KUrl destUrl; 00529 destUrl.setPath(tempFile.fileName()); 00530 KIO::Job *job = KIO::file_copy(replyUrl, destUrl, 0600, KIO::Overwrite); 00531 job->ui()->setWindow(d->windowWidget()); 00532 job->ui()->setAutoErrorHandlingEnabled(true); 00533 connect(job, SIGNAL(result(KJob*)), 00534 this, SLOT(_k_copyResultToTempFile(KJob*))); 00535 return true; 00536 } 00537 00538 // Ask before running any executables... 00539 if (KParts::BrowserRun::allowExecution(mimeType, replyUrl)) { 00540 KService::Ptr offer = dlg.selectedService(); 00541 // HACK: The check below is necessary to break an infinite 00542 // recursion that occurs whenever this function is called as a result 00543 // of receiving content that can be rendered by the app using this engine. 00544 // For example a text/html header that containing a content-disposition 00545 // header is received by the app using this class. 00546 if (isMimeTypeAssociatedWithSelf(offer)) { 00547 reloadRequestWithoutDisposition(reply); 00548 } else { 00549 KUrl::List list; 00550 list.append(replyUrl); 00551 bool success = false; 00552 // kDebug(800) << "Suggested file name:" << suggestedFileName; 00553 if (offer) { 00554 success = KRun::run(*offer, list, d->windowWidget() , false, suggestedFileName); 00555 } else { 00556 success = KRun::displayOpenWithDialog(list, d->windowWidget(), false, suggestedFileName); 00557 if (!success) 00558 break; 00559 } 00560 // For non KIO apps and cancelled Open With dialog, remove slave on hold. 00561 if (!success || (offer && !offer->categories().contains(QL1S("KDE")))) { 00562 KIO::SimpleJob::removeOnHold(); // Remove any slave-on-hold... 00563 } 00564 } 00565 return true; 00566 } 00567 // TODO: Instead of silently failing when allowExecution fails, notify 00568 // the user why the requested action cannot be fulfilled... 00569 return false; 00570 case KParts::BrowserOpenOrSaveQuestion::Save: 00571 // Do not download local files... 00572 if (!replyUrl.isLocalFile()) { 00573 QString downloadCmd (reply->property("DownloadManagerExe").toString()); 00574 if (!downloadCmd.isEmpty()) { 00575 downloadCmd += QLatin1Char(' '); 00576 downloadCmd += KShell::quoteArg(replyUrl.url()); 00577 if (!suggestedFileName.isEmpty()) { 00578 downloadCmd += QLatin1Char(' '); 00579 downloadCmd += KShell::quoteArg(suggestedFileName); 00580 } 00581 // kDebug(800) << "download command:" << downloadCmd; 00582 if (KRun::runCommand(downloadCmd, view())) 00583 return true; 00584 } 00585 if (!downloadResource(replyUrl, suggestedFileName, d->windowWidget())) 00586 break; 00587 } 00588 return true; 00589 case KParts::BrowserOpenOrSaveQuestion::Cancel: 00590 default: 00591 KIO::SimpleJob::removeOnHold(); // Remove any slave-on-hold... 00592 return true; 00593 } 00594 } 00595 } else { 00596 KService::Ptr offer = KMimeTypeTrader::self()->preferredService(mimeType); 00597 if (isMimeTypeAssociatedWithSelf(offer)) { 00598 reloadRequestWithoutDisposition(reply); 00599 return true; 00600 } 00601 } 00602 00603 return false; 00604 } 00605 00606 #include "kwebpage.moc" 00607
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:37:47 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:37:47 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.