File indexing completed on 2024-04-21 05:50:21
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 "toplevel.h" 0025 0026 #include "keditbookmarks_debug.h" 0027 #include <KLocalizedString> 0028 0029 #include <KIO/FavIconRequestJob> 0030 #include <KIO/SimpleJob> 0031 #include <KIO/TransferJob> 0032 #include <KParts/NavigationExtension> 0033 #include <KParts/PartLoader> 0034 0035 FavIconUpdater::FavIconUpdater(QObject *parent) 0036 : QObject(parent) 0037 { 0038 m_part = nullptr; 0039 m_webGrabber = nullptr; 0040 } 0041 0042 void FavIconUpdater::downloadIcon(const KBookmark &bk) 0043 { 0044 m_bk = bk; 0045 const QUrl url = bk.url(); 0046 const QString favicon = KIO::favIconForUrl(url); 0047 if (!favicon.isEmpty()) { 0048 // qCDebug(KEDITBOOKMARKS_LOG) << "got favicon" << favicon; 0049 m_bk.setIcon(favicon); 0050 KEBApp::self()->notifyCommandExecuted(); 0051 // //qCDebug(KEDITBOOKMARKS_LOG) << "emit done(true)"; 0052 Q_EMIT done(true, QString()); 0053 0054 } else { 0055 // qCDebug(KEDITBOOKMARKS_LOG) << "no favicon found"; 0056 webupdate = false; 0057 KIO::FavIconRequestJob *job = new KIO::FavIconRequestJob(url, KIO::Reload); 0058 connect(job, &KIO::FavIconRequestJob::result, this, &FavIconUpdater::slotResult); 0059 } 0060 } 0061 0062 FavIconUpdater::~FavIconUpdater() 0063 { 0064 delete m_webGrabber; 0065 delete m_part; 0066 } 0067 0068 void FavIconUpdater::downloadIconUsingWebBrowser(const KBookmark &bk, const QString ¤tError) 0069 { 0070 // qCDebug(KEDITBOOKMARKS_LOG); 0071 m_bk = bk; 0072 webupdate = true; 0073 0074 if (!m_part) { 0075 auto partResult = KParts::PartLoader::instantiatePartForMimeType<KParts::ReadOnlyPart>(QStringLiteral("text/html"), nullptr, this); 0076 if (!partResult) { 0077 Q_EMIT done(false, i18n("%1; no HTML component found (%2)", currentError, partResult.errorString)); 0078 return; 0079 } 0080 0081 auto part = partResult.plugin; 0082 part->setProperty("pluginsEnabled", QVariant(false)); 0083 part->setProperty("javaScriptEnabled", QVariant(false)); 0084 part->setProperty("javaEnabled", QVariant(false)); 0085 part->setProperty("autoloadImages", QVariant(false)); 0086 KParts::NavigationExtension *ext = KParts::NavigationExtension::childObject(part); 0087 Q_ASSERT(ext); 0088 0089 connect(ext, &KParts::NavigationExtension::setIconUrl, this, &FavIconUpdater::setIconUrl); 0090 m_part = part; 0091 } 0092 0093 // The part isn't created by the webgrabber so that we can create the part 0094 // only once. 0095 delete m_webGrabber; 0096 m_webGrabber = new FavIconWebGrabber(m_part, bk.url()); 0097 connect(m_webGrabber, &FavIconWebGrabber::done, this, &FavIconUpdater::done); 0098 } 0099 0100 // khtml callback 0101 void FavIconUpdater::setIconUrl(const QUrl &iconURL) 0102 { 0103 KIO::FavIconRequestJob *job = new KIO::FavIconRequestJob(m_bk.url()); 0104 job->setIconUrl(iconURL); 0105 connect(job, &KIO::FavIconRequestJob::result, this, &FavIconUpdater::slotResult); 0106 0107 delete m_webGrabber; 0108 m_webGrabber = nullptr; 0109 } 0110 0111 void FavIconUpdater::slotResult(KJob *job) 0112 { 0113 KIO::FavIconRequestJob *requestJob = static_cast<KIO::FavIconRequestJob *>(job); 0114 if (job->error()) { 0115 if (!webupdate) { 0116 qCDebug(KEDITBOOKMARKS_LOG) << "favicon job failed, going to downloadIconUsingWebBrowser"; 0117 // no icon found, try webupdater 0118 downloadIconUsingWebBrowser(m_bk, job->errorString()); 0119 } else { 0120 qCDebug(KEDITBOOKMARKS_LOG) << "favicon job failed, emit done"; 0121 // already tried webupdater 0122 Q_EMIT done(false, job->errorString()); 0123 } 0124 return; 0125 } 0126 m_bk.setIcon(requestJob->iconFile()); 0127 Q_EMIT done(true, QString()); 0128 } 0129 0130 /* -------------------------- */ 0131 0132 FavIconWebGrabber::FavIconWebGrabber(KParts::ReadOnlyPart *part, const QUrl &url) 0133 : m_part(part) 0134 , m_url(url) 0135 { 0136 // FIXME only connect to result? 0137 // connect(part, SIGNAL(result(KIO::Job*job)), 0138 // this, SLOT(slotCompleted())); 0139 connect(part, &KParts::ReadOnlyPart::canceled, this, &FavIconWebGrabber::slotCanceled); 0140 // clang-format off 0141 connect(part, SIGNAL(completed(bool)), this, SLOT(slotCompleted())); 0142 // clang-format on 0143 0144 // the use of KIO rather than directly using KHTML is to allow silently abort on error 0145 // TODO: an alternative would be to derive from KHTMLPart and reimplement showError(KJob*). 0146 0147 // qCDebug(KEDITBOOKMARKS_LOG) << "starting KIO::get() on" << m_url; 0148 KIO::Job *job = KIO::get(m_url, KIO::NoReload, KIO::HideProgressInfo); 0149 job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none")); 0150 job->addMetaData(QStringLiteral("errorPage"), QStringLiteral("false")); 0151 connect(job, &KJob::result, this, &FavIconWebGrabber::slotFinished); 0152 // clang-format off 0153 connect(job, SIGNAL(mimetype(KIO::Job*,QString)), this, SLOT(slotMimetype(KIO::Job*,QString))); 0154 // clang-format on 0155 } 0156 0157 void FavIconWebGrabber::slotMimetype(KIO::Job *job, const QString &type) 0158 { 0159 Q_ASSERT(!job->error()); // can't be set already, surely? 0160 0161 KIO::SimpleJob *sjob = static_cast<KIO::SimpleJob *>(job); 0162 m_url = sjob->url(); // allow for redirection 0163 sjob->putOnHold(); 0164 0165 // QString typeLocal = typeUncopied; // local copy 0166 qCDebug(KEDITBOOKMARKS_LOG) << "slotMimetype " << type << "calling openUrl on" << m_url; 0167 // TODO - what to do if typeLocal is not text/html ?? 0168 0169 m_part->openUrl(m_url); 0170 } 0171 0172 void FavIconWebGrabber::slotFinished(KJob *job) 0173 { 0174 if (job->error()) { 0175 qCDebug(KEDITBOOKMARKS_LOG) << job->errorString(); 0176 Q_EMIT done(false, job->errorString()); 0177 return; 0178 } 0179 // On success mimetype was emitted, so no need to do anything. 0180 } 0181 0182 void FavIconWebGrabber::slotCompleted() 0183 { 0184 qCDebug(KEDITBOOKMARKS_LOG); 0185 Q_EMIT done(true, QString()); 0186 } 0187 0188 void FavIconWebGrabber::slotCanceled(const QString &errorString) 0189 { 0190 // qCDebug(KEDITBOOKMARKS_LOG) << errorString; 0191 Q_EMIT done(false, errorString); 0192 } 0193 0194 #include "moc_faviconupdater.cpp"