Warning, file /utilities/keditbookmarks/src/faviconupdater.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // -*- indent-tabs-mode:nil -*-
0002 // vim: set ts=4 sts=4 sw=4 et:
0003 /* This file is part of the KDE project
0004    Copyright (C) 2003 Alexander Kellett <lypanov@kde.org>
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU General Public
0008    License version 2 or at your option version 3 as published by
0009    the Free Software Foundation.
0010 
0011    This program is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    General Public License for more details.
0015 
0016    You should have received a copy of the GNU General Public License
0017    along with this program; see the file COPYING.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019    Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "faviconupdater.h"
0023 
0024 #include "bookmarkiterator.h"
0025 #include "toplevel.h"
0026 
0027 #include "keditbookmarks_debug.h"
0028 #include <KLocalizedString>
0029 
0030 #include <KIO/FavIconRequestJob>
0031 #include <kio/job.h>
0032 
0033 #include <KParts/BrowserExtension>
0034 #include <KParts/PartLoader>
0035 
0036 FavIconUpdater::FavIconUpdater(QObject *parent)
0037     : QObject(parent)
0038 {
0039     m_part = nullptr;
0040     m_webGrabber = nullptr;
0041 }
0042 
0043 void FavIconUpdater::downloadIcon(const KBookmark &bk)
0044 {
0045     m_bk = bk;
0046     const QUrl url = bk.url();
0047     const QString favicon = KIO::favIconForUrl(url);
0048     if (!favicon.isEmpty()) {
0049         // qCDebug(KEDITBOOKMARKS_LOG) << "got favicon" << favicon;
0050         m_bk.setIcon(favicon);
0051         KEBApp::self()->notifyCommandExecuted();
0052         // //qCDebug(KEDITBOOKMARKS_LOG) << "emit done(true)";
0053         Q_EMIT done(true, QString());
0054 
0055     } else {
0056         // qCDebug(KEDITBOOKMARKS_LOG) << "no favicon found";
0057         webupdate = false;
0058         KIO::FavIconRequestJob *job = new KIO::FavIconRequestJob(url, KIO::Reload);
0059         connect(job, &KIO::FavIconRequestJob::result, this, &FavIconUpdater::slotResult);
0060     }
0061 }
0062 
0063 FavIconUpdater::~FavIconUpdater()
0064 {
0065     delete m_webGrabber;
0066     delete m_part;
0067 }
0068 
0069 void FavIconUpdater::downloadIconUsingWebBrowser(const KBookmark &bk, const QString &currentError)
0070 {
0071     // qCDebug(KEDITBOOKMARKS_LOG);
0072     m_bk = bk;
0073     webupdate = true;
0074 
0075     if (!m_part) {
0076         QString partLoadingError;
0077         KParts::ReadOnlyPart *part =
0078             KParts::PartLoader::createPartInstanceForMimeType<KParts::ReadOnlyPart>(QStringLiteral("text/html"), nullptr, this, &partLoadingError);
0079         if (!part) {
0080             Q_EMIT done(false, i18n("%1; no HTML component found (%2)", currentError, partLoadingError));
0081             return;
0082         }
0083 
0084         part->setProperty("pluginsEnabled", QVariant(false));
0085         part->setProperty("javaScriptEnabled", QVariant(false));
0086         part->setProperty("javaEnabled", QVariant(false));
0087         part->setProperty("autoloadImages", QVariant(false));
0088 
0089         KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(part);
0090         Q_ASSERT(ext);
0091 
0092         connect(ext, &KParts::BrowserExtension::setIconUrl, this, &FavIconUpdater::setIconUrl);
0093 
0094         m_part = part;
0095     }
0096 
0097     // The part isn't created by the webgrabber so that we can create the part
0098     // only once.
0099     delete m_webGrabber;
0100     m_webGrabber = new FavIconWebGrabber(m_part, bk.url());
0101     connect(m_webGrabber, &FavIconWebGrabber::done, this, &FavIconUpdater::done);
0102 }
0103 
0104 // khtml callback
0105 void FavIconUpdater::setIconUrl(const QUrl &iconURL)
0106 {
0107     KIO::FavIconRequestJob *job = new KIO::FavIconRequestJob(m_bk.url());
0108     job->setIconUrl(iconURL);
0109     connect(job, &KIO::FavIconRequestJob::result, this, &FavIconUpdater::slotResult);
0110 
0111     delete m_webGrabber;
0112     m_webGrabber = nullptr;
0113 }
0114 
0115 void FavIconUpdater::slotResult(KJob *job)
0116 {
0117     KIO::FavIconRequestJob *requestJob = static_cast<KIO::FavIconRequestJob *>(job);
0118     if (job->error()) {
0119         if (!webupdate) {
0120             qCDebug(KEDITBOOKMARKS_LOG) << "favicon job failed, going to downloadIconUsingWebBrowser";
0121             // no icon found, try webupdater
0122             downloadIconUsingWebBrowser(m_bk, job->errorString());
0123         } else {
0124             qCDebug(KEDITBOOKMARKS_LOG) << "favicon job failed, emit done";
0125             // already tried webupdater
0126             Q_EMIT done(false, job->errorString());
0127         }
0128         return;
0129     }
0130     m_bk.setIcon(requestJob->iconFile());
0131     Q_EMIT done(true, QString());
0132 }
0133 
0134 /* -------------------------- */
0135 
0136 FavIconWebGrabber::FavIconWebGrabber(KParts::ReadOnlyPart *part, const QUrl &url)
0137     : m_part(part)
0138     , m_url(url)
0139 {
0140     // FIXME only connect to result?
0141     //  connect(part, SIGNAL(result(KIO::Job*job)),
0142     //          this, SLOT(slotCompleted()));
0143     connect(part, &KParts::ReadOnlyPart::canceled, this, &FavIconWebGrabber::slotCanceled);
0144     // clang-format off
0145     connect(part, SIGNAL(completed(bool)), this, SLOT(slotCompleted()));
0146     // clang-format on
0147 
0148     // the use of KIO rather than directly using KHTML is to allow silently abort on error
0149     // TODO: an alternative would be to derive from KHTMLPart and reimplement showError(KJob*).
0150 
0151     // qCDebug(KEDITBOOKMARKS_LOG) << "starting KIO::get() on" << m_url;
0152     KIO::Job *job = KIO::get(m_url, KIO::NoReload, KIO::HideProgressInfo);
0153     job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
0154     job->addMetaData(QStringLiteral("errorPage"), QStringLiteral("false"));
0155     connect(job, &KJob::result, this, &FavIconWebGrabber::slotFinished);
0156     // clang-format off
0157     connect(job, SIGNAL(mimetype(KIO::Job*,QString)), this, SLOT(slotMimetype(KIO::Job*,QString)));
0158     // clang-format on
0159 }
0160 
0161 void FavIconWebGrabber::slotMimetype(KIO::Job *job, const QString &type)
0162 {
0163     Q_ASSERT(!job->error()); // can't be set already, surely?
0164 
0165     KIO::SimpleJob *sjob = static_cast<KIO::SimpleJob *>(job);
0166     m_url = sjob->url(); // allow for redirection
0167     sjob->putOnHold();
0168 
0169     // QString typeLocal = typeUncopied; // local copy
0170     qCDebug(KEDITBOOKMARKS_LOG) << "slotMimetype " << type << "calling openUrl on" << m_url;
0171     // TODO - what to do if typeLocal is not text/html ??
0172 
0173     m_part->openUrl(m_url);
0174 }
0175 
0176 void FavIconWebGrabber::slotFinished(KJob *job)
0177 {
0178     if (job->error()) {
0179         qCDebug(KEDITBOOKMARKS_LOG) << job->errorString();
0180         Q_EMIT done(false, job->errorString());
0181         return;
0182     }
0183     // On success mimetype was emitted, so no need to do anything.
0184 }
0185 
0186 void FavIconWebGrabber::slotCompleted()
0187 {
0188     qCDebug(KEDITBOOKMARKS_LOG);
0189     Q_EMIT done(true, QString());
0190 }
0191 
0192 void FavIconWebGrabber::slotCanceled(const QString &errorString)
0193 {
0194     // qCDebug(KEDITBOOKMARKS_LOG) << errorString;
0195     Q_EMIT done(false, errorString);
0196 }