summaryrefslogtreecommitdiffstats
path: root/src/core/favicon_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/favicon_manager.cpp')
-rw-r--r--src/core/favicon_manager.cpp183
1 files changed, 66 insertions, 117 deletions
diff --git a/src/core/favicon_manager.cpp b/src/core/favicon_manager.cpp
index 6cbb8bc1c..8469f054e 100644
--- a/src/core/favicon_manager.cpp
+++ b/src/core/favicon_manager.cpp
@@ -44,6 +44,8 @@
#include "web_contents_adapter_client.h"
#include "base/bind.h"
+#include "content/public/browser/favicon_status.h"
+#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkPixelRef.h"
@@ -76,12 +78,12 @@ FaviconManagerPrivate::~FaviconManagerPrivate()
{
}
-int FaviconManagerPrivate::downloadIcon(const QUrl &url, bool candidate)
+int FaviconManagerPrivate::downloadIcon(const QUrl &url)
{
static int fakeId = 0;
int id;
- bool cached = candidate && m_icons.contains(url);
+ bool cached = m_icons.contains(url);
if (isResourceUrl(url) || cached) {
id = --fakeId;
m_pendingRequests.insert(id, url);
@@ -94,13 +96,8 @@ int FaviconManagerPrivate::downloadIcon(const QUrl &url, bool candidate)
base::Bind(&FaviconManagerPrivate::iconDownloadFinished, m_weakFactory.GetWeakPtr()));
}
- if (candidate) {
- Q_ASSERT(!m_inProgressCandidateRequests.contains(id));
- m_inProgressCandidateRequests.insert(id, url);
- } else {
- Q_ASSERT(!m_inProgressCustomRequests.contains(id));
- m_inProgressCustomRequests.insert(id, url);
- }
+ Q_ASSERT(!m_inProgressRequests.contains(id));
+ m_inProgressRequests.insert(id, url);
return id;
}
@@ -118,12 +115,10 @@ void FaviconManagerPrivate::iconDownloadFinished(int id,
storeIcon(id, toQIcon(bitmaps));
}
-/* Pending requests are used as a workaround for avoiding signal iconChanged when
- * accessing each cached icons or icons stored in qrc. They don't have to be downloaded
- * thus the m_inProgressCustomRequests maybe emptied right before the next icon is added to
- * in-progress-requests queue. The m_pendingRequests stores these requests until all
- * candidates are added to the queue then pending requests should be cleaned up by this
- * function.
+/* Pending requests are used to mark icons that are already downloaded (cached icons or icons
+ * stored in qrc). These requests are also stored in the m_inProgressRequests but the corresponding
+ * icons are stored in m_icons explicitly by this function. It is necessary to avoid
+ * m_inProgressRequests being emptied right before the next icon is added by a downloadIcon() call.
*/
void FaviconManagerPrivate::downloadPendingRequests()
{
@@ -143,10 +138,9 @@ void FaviconManagerPrivate::downloadPendingRequests()
void FaviconManagerPrivate::storeIcon(int id, const QIcon &icon)
{
Q_Q(FaviconManager);
+ Q_ASSERT(m_inProgressRequests.contains(id));
- bool candidate = m_inProgressCandidateRequests.contains(id);
-
- QUrl requestUrl = candidate ? m_inProgressCandidateRequests[id] : m_inProgressCustomRequests[id];
+ QUrl requestUrl = m_inProgressRequests[id];
FaviconInfo &faviconInfo = q->m_faviconInfoMap[requestUrl];
unsigned iconCount = 0;
@@ -168,29 +162,46 @@ void FaviconManagerPrivate::storeIcon(int id, const QIcon &icon)
}
}
}
-
- q->m_hasDownloadedIcon = true;
- } else if (id < 0) {
- // Icon is cached
- q->m_hasDownloadedIcon = true;
- } else {
+ } else if (id >= 0) {
// Reset size if icon cannot be downloaded
faviconInfo.size = QSize(0, 0);
}
- if (candidate) {
- m_inProgressCandidateRequests.remove(id);
- if (m_inProgressCandidateRequests.isEmpty())
- m_viewClient->iconChanged(q->getProposedFaviconInfo().url);
- } else {
- m_inProgressCustomRequests.remove(id);
+ m_inProgressRequests.remove(id);
+ if (m_inProgressRequests.isEmpty())
+ propagateIcon();
+}
+
+void FaviconManagerPrivate::propagateIcon() const
+{
+ Q_Q(const FaviconManager);
+
+ QUrl iconUrl;
+ const QList<FaviconInfo> &faviconInfoList = q->getFaviconInfoList(true /* candidates only */);
+
+ unsigned bestArea = 0;
+ for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
+ if (it->type != FaviconInfo::Favicon)
+ continue;
+
+ if (it->isValid() && bestArea < area(it->size)) {
+ iconUrl = it->url;
+ bestArea = area(it->size);
+ }
}
- Q_EMIT q->iconDownloaded(requestUrl);
+ content::NavigationEntry *entry = m_webContents->GetController().GetVisibleEntry();
+ if (entry) {
+ content::FaviconStatus &favicon = entry->GetFavicon();
+ favicon.url = toGurl(iconUrl);
+ favicon.valid = true;
+ }
+
+ m_viewClient->iconChanged(iconUrl);
}
FaviconManager::FaviconManager(FaviconManagerPrivate *d)
- : m_hasDownloadedIcon(false)
+ : m_hasCandidate(false)
{
Q_ASSERT(d);
d_ptr.reset(d);
@@ -228,121 +239,59 @@ QList<FaviconInfo> FaviconManager::getFaviconInfoList(bool candidatesOnly) const
return faviconInfoList;
}
-
-void FaviconManager::downloadIcon(const QUrl &url, FaviconInfo::FaviconType iconType)
-{
- Q_D(FaviconManager);
-
- // If the favicon cannot be found in the list that means that it is not a candidate
- // for any visited page (including the current one). In this case the type of the icon
- // is unknown: it has to be specified explicitly.
- if (!m_faviconInfoMap.contains(url)) {
- FaviconInfo newFaviconInfo(url, iconType);
- m_faviconInfoMap.insert(url, newFaviconInfo);
- }
-
- d->downloadIcon(url, false);
- d->downloadPendingRequests();
-}
-
-void FaviconManager::removeIcon(const QUrl &url)
-{
- Q_D(FaviconManager);
- int removed = d->m_icons.remove(url);
-
- if (removed) {
- Q_ASSERT(removed == 1);
- Q_ASSERT(m_faviconInfoMap.contains(url));
- m_faviconInfoMap[url].size = QSize(0, 0);
- }
-}
-
-bool FaviconManager::hasAvailableCandidateIcon() const
-{
- Q_D(const FaviconManager);
- return m_hasDownloadedIcon || !d->m_inProgressCandidateRequests.isEmpty();
-}
-
void FaviconManager::update(const QList<FaviconInfo> &candidates)
{
Q_D(FaviconManager);
updateCandidates(candidates);
- for (auto it = m_faviconInfoMap.cbegin(), end = m_faviconInfoMap.cend(); it != end; ++it) {
- const FaviconInfo &faviconInfo = it.value();
- if (!faviconInfo.candidate || faviconInfo.type != FaviconInfo::Favicon)
+ const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
+ for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
+ if (it->type != FaviconInfo::Favicon)
continue;
- if (faviconInfo.isValid())
- d->downloadIcon(faviconInfo.url, true);
+ if (it->isValid())
+ d->downloadIcon(it->url);
}
d->downloadPendingRequests();
+
+ // Reset icon if nothing was downloaded
+ if (d->m_inProgressRequests.isEmpty()) {
+ content::NavigationEntry *entry = d->m_webContents->GetController().GetVisibleEntry();
+ if (entry && !entry->GetFavicon().valid)
+ d->m_viewClient->iconChanged(QUrl());
+ }
}
void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates)
{
+ m_hasCandidate = candidates.count();
for (FaviconInfo candidateFaviconInfo : candidates) {
- QUrl candidateUrl = candidateFaviconInfo.url;
- if (m_faviconInfoMap.contains(candidateUrl)) {
- m_faviconInfoMap[candidateUrl].candidate = true;
- // Update type in case of the icon was downloaded manually
+ const QUrl &candidateUrl = candidateFaviconInfo.url;
+
+ if (!m_faviconInfoMap.contains(candidateUrl))
+ m_faviconInfoMap.insert(candidateUrl, candidateFaviconInfo);
+ else {
+ // The same icon can be used for more than one page with different types.
m_faviconInfoMap[candidateUrl].type = candidateFaviconInfo.type;
- continue;
}
- candidateFaviconInfo.candidate = true;
- m_faviconInfoMap.insert(candidateUrl, candidateFaviconInfo);
+ m_faviconInfoMap[candidateUrl].candidate = true;
}
}
void FaviconManager::resetCandidates()
{
- m_hasDownloadedIcon = false;
+ m_hasCandidate = false;
for (auto it = m_faviconInfoMap.begin(), end = m_faviconInfoMap.end(); it != end; ++it)
it->candidate = false;
}
-
-FaviconInfo FaviconManager::getProposedFaviconInfo() const
+bool FaviconManager::hasCandidate() const
{
- FaviconInfo proposedFaviconInfo = getFirstFaviconInfo();
-
- // If nothing has been downloaded yet return the first favicon
- // if there is available for dev-tools
- if (!m_hasDownloadedIcon)
- return proposedFaviconInfo;
-
- unsigned bestArea = area(proposedFaviconInfo.size);
- for (auto it = m_faviconInfoMap.cbegin(), end = m_faviconInfoMap.cend(); it != end; ++it) {
- const FaviconInfo &faviconInfo = it.value();
- if (!faviconInfo.candidate || faviconInfo.type != FaviconInfo::Favicon)
- continue;
-
- if (faviconInfo.isValid() && bestArea < area(faviconInfo.size)) {
- proposedFaviconInfo = faviconInfo;
- bestArea = area(proposedFaviconInfo.size);
- }
- }
-
- return proposedFaviconInfo;
+ return m_hasCandidate;
}
-FaviconInfo FaviconManager::getFirstFaviconInfo() const
-{
- for (auto it = m_faviconInfoMap.cbegin(), end = m_faviconInfoMap.cend(); it != end; ++it) {
- const FaviconInfo &faviconInfo = it.value();
- if (!faviconInfo.candidate || faviconInfo.type != FaviconInfo::Favicon)
- continue;
-
- if (faviconInfo.isValid())
- return faviconInfo;
- }
-
- return FaviconInfo();
-}
-
-
FaviconInfo::FaviconInfo()
: url(QUrl())