From ef6cb53a1d49de616067126c8f49d2406c9a7f43 Mon Sep 17 00:00:00 2001
From: Arvid Nilsson <anilsson@blackberry.com>
Date: Thu, 3 Oct 2013 12:33:54 +0200
Subject: [PATCH] Quick: Add Favicon API

Adds a favicon API modelled after the WebKit2 QQuickWebView API, but
using an http(s) URL instead of a custom protocol, because there's no
icondatabase yet.

The icon URL lingers even when a new load is committed, until the load
finishes. It might be more prudent to clear the icon when committing a
new load, but I opted to let the app take care of that detail if
desired. Many browsers show a spinner instead of the favicon while
loading, for example.

There's no widget API implementation for favicons yet, because that API
only makes sense if we have a full-fledged icon database (case in
point: QWebEngineSettings::iconForUrl()).

Change-Id: I1e7b85104c80de2ae46a5fe9a273104d43a5c71f
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
---
 examples/quick/quicknanobrowser/quickwindow.qml |  5 +++++
 lib/quick/qquickwebengineview.cpp               | 13 +++++++++++++
 lib/quick/qquickwebengineview_p.h               |  3 +++
 lib/quick/qquickwebengineview_p_p.h             |  2 ++
 lib/web_contents_adapter_client.h               |  1 +
 lib/web_contents_delegate_qt.cpp                | 12 ++++++++++++
 lib/web_contents_delegate_qt.h                  |  1 +
 lib/widgets/Api/qwebenginepage.cpp              |  5 +++++
 lib/widgets/Api/qwebenginepage_p.h              |  1 +
 9 files changed, 43 insertions(+)

diff --git a/examples/quick/quicknanobrowser/quickwindow.qml b/examples/quick/quicknanobrowser/quickwindow.qml
index bec301e6d..7ec4fc021 100644
--- a/examples/quick/quicknanobrowser/quickwindow.qml
+++ b/examples/quick/quicknanobrowser/quickwindow.qml
@@ -82,6 +82,10 @@ ApplicationWindow {
                 iconSource: webEngineView.loading ? "icons/process-stop.png" : "icons/view-refresh.png"
                 onClicked: webEngineView.reload()
             }
+            Image {
+                id: faviconImage
+                width: 16; height: 16
+            }
             TextField {
                 id: addressBar
                 focus: true
@@ -99,5 +103,6 @@ ApplicationWindow {
         url: utils.initialUrl()
 
         onUrlChanged: addressBar.text = url
+        onIconChanged: faviconImage.source = url
     }
 }
diff --git a/lib/quick/qquickwebengineview.cpp b/lib/quick/qquickwebengineview.cpp
index 708a7ecb6..aa942c017 100644
--- a/lib/quick/qquickwebengineview.cpp
+++ b/lib/quick/qquickwebengineview.cpp
@@ -74,6 +74,13 @@ void QQuickWebEngineViewPrivate::urlChanged(const QUrl &url)
     Q_EMIT q->urlChanged();
 }
 
+void QQuickWebEngineViewPrivate::iconChanged(const QUrl &url)
+{
+    Q_Q(QQuickWebEngineView);
+    icon = url;
+    Q_EMIT q->iconChanged();
+}
+
 void QQuickWebEngineViewPrivate::loadingStateChanged()
 {
     Q_Q(QQuickWebEngineView);
@@ -127,6 +134,12 @@ void QQuickWebEngineView::setUrl(const QUrl& url)
     d->adapter->load(url);
 }
 
+QUrl QQuickWebEngineView::icon() const
+{
+    Q_D(const QQuickWebEngineView);
+    return d->icon;
+}
+
 void QQuickWebEngineView::goBack()
 {
     Q_D(QQuickWebEngineView);
diff --git a/lib/quick/qquickwebengineview_p.h b/lib/quick/qquickwebengineview_p.h
index faeb234a1..1c3e27732 100644
--- a/lib/quick/qquickwebengineview_p.h
+++ b/lib/quick/qquickwebengineview_p.h
@@ -51,6 +51,7 @@ class QQuickWebEngineViewPrivate;
 class QQuickWebEngineView : public QQuickItem {
     Q_OBJECT
     Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
+    Q_PROPERTY(QUrl icon READ icon NOTIFY iconChanged)
     Q_PROPERTY(bool loading READ isLoading NOTIFY loadingStateChanged)
     Q_PROPERTY(QString title READ title NOTIFY titleChanged)
     Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY loadingStateChanged)
@@ -62,6 +63,7 @@ public:
 
     QUrl url() const;
     void setUrl(const QUrl&);
+    QUrl icon() const;
     bool isLoading() const;
     QString title() const;
     bool canGoBack() const;
@@ -76,6 +78,7 @@ public Q_SLOTS:
 Q_SIGNALS:
     void titleChanged();
     void urlChanged();
+    void iconChanged();
     void loadingStateChanged();
 
 protected:
diff --git a/lib/quick/qquickwebengineview_p_p.h b/lib/quick/qquickwebengineview_p_p.h
index 9831fa0f3..38621b44d 100644
--- a/lib/quick/qquickwebengineview_p_p.h
+++ b/lib/quick/qquickwebengineview_p_p.h
@@ -61,6 +61,7 @@ public:
     virtual RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(CompositingMode mode) Q_DECL_OVERRIDE;
     virtual void titleChanged(const QString&) Q_DECL_OVERRIDE;
     virtual void urlChanged(const QUrl&) Q_DECL_OVERRIDE;
+    virtual void iconChanged(const QUrl&) Q_DECL_OVERRIDE;
     virtual void loadingStateChanged() Q_DECL_OVERRIDE;
     virtual QRectF viewportRect() const Q_DECL_OVERRIDE;
     virtual void loadFinished(bool success) Q_DECL_OVERRIDE;
@@ -68,6 +69,7 @@ public:
     virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition) Q_DECL_OVERRIDE;
 
     QExplicitlySharedDataPointer<WebContentsAdapter> adapter;
+    QUrl icon;
 };
 
 QT_END_NAMESPACE
diff --git a/lib/web_contents_adapter_client.h b/lib/web_contents_adapter_client.h
index b0ab502c8..ea6e5a666 100644
--- a/lib/web_contents_adapter_client.h
+++ b/lib/web_contents_adapter_client.h
@@ -80,6 +80,7 @@ public:
     virtual RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(CompositingMode mode) = 0;
     virtual void titleChanged(const QString&) = 0;
     virtual void urlChanged(const QUrl&) = 0;
+    virtual void iconChanged(const QUrl&) = 0;
     virtual void loadingStateChanged() = 0;
     virtual QRectF viewportRect() const = 0;
     virtual void loadFinished(bool success) = 0;
diff --git a/lib/web_contents_delegate_qt.cpp b/lib/web_contents_delegate_qt.cpp
index e64649aea..12a00481c 100644
--- a/lib/web_contents_delegate_qt.cpp
+++ b/lib/web_contents_delegate_qt.cpp
@@ -48,6 +48,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/invalidate_type.h"
+#include "content/public/common/favicon_url.h"
 
 WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, WebContentsAdapterClient *adapterClient)
     : m_viewClient(adapterClient)
@@ -96,3 +97,14 @@ void WebContentsDelegateQt::DidFinishLoad(int64 frame_id, const GURL &validated_
     if (is_main_frame)
         m_viewClient->loadFinished(true);
 }
+
+void WebContentsDelegateQt::DidUpdateFaviconURL(int32 page_id, const std::vector<content::FaviconURL>& candidates)
+{
+    Q_UNUSED(page_id)
+    Q_FOREACH (content::FaviconURL candidate, candidates) {
+        if (candidate.icon_type == content::FaviconURL::FAVICON && !candidate.icon_url.is_empty()) {
+            m_viewClient->iconChanged(toQt(candidate.icon_url));
+            break;
+        }
+    }
+}
diff --git a/lib/web_contents_delegate_qt.h b/lib/web_contents_delegate_qt.h
index e56800571..629fd5c6c 100644
--- a/lib/web_contents_delegate_qt.h
+++ b/lib/web_contents_delegate_qt.h
@@ -64,6 +64,7 @@ public:
     virtual void LoadingStateChanged(content::WebContents* source);
     virtual void DidFailLoad(int64 frame_id, const GURL &validated_url, bool is_main_frame, int error_code, const string16 &error_description, content::RenderViewHost *render_view_host);
     virtual void DidFinishLoad(int64 frame_id, const GURL &validated_url, bool is_main_frame, content::RenderViewHost *render_view_host);
+    virtual void DidUpdateFaviconURL(int32 page_id, const std::vector<content::FaviconURL>& candidates);
 
 private:
     WebContentsAdapterClient *m_viewClient;
diff --git a/lib/widgets/Api/qwebenginepage.cpp b/lib/widgets/Api/qwebenginepage.cpp
index ee0238368..ab3b1e675 100644
--- a/lib/widgets/Api/qwebenginepage.cpp
+++ b/lib/widgets/Api/qwebenginepage.cpp
@@ -69,6 +69,11 @@ void QWebEnginePagePrivate::urlChanged(const QUrl &url)
     Q_EMIT q->urlChanged(url);
 }
 
+void QWebEnginePagePrivate::iconChanged(const QUrl &url)
+{
+    Q_UNUSED(url)
+}
+
 void QWebEnginePagePrivate::loadingStateChanged()
 {
     Q_Q(QWebEnginePage);
diff --git a/lib/widgets/Api/qwebenginepage_p.h b/lib/widgets/Api/qwebenginepage_p.h
index 22066b5bc..ad1de0047 100644
--- a/lib/widgets/Api/qwebenginepage_p.h
+++ b/lib/widgets/Api/qwebenginepage_p.h
@@ -67,6 +67,7 @@ public:
     virtual RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(CompositingMode mode) Q_DECL_OVERRIDE;
     virtual void titleChanged(const QString&) Q_DECL_OVERRIDE;
     virtual void urlChanged(const QUrl&) Q_DECL_OVERRIDE;
+    virtual void iconChanged(const QUrl&) Q_DECL_OVERRIDE;
     virtual void loadingStateChanged() Q_DECL_OVERRIDE;
     virtual QRectF viewportRect() const Q_DECL_OVERRIDE;
     virtual void loadFinished(bool success) Q_DECL_OVERRIDE;
-- 
GitLab