From e67c21a033121618bfe4cf62686d009d0bacd8c3 Mon Sep 17 00:00:00 2001
From: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Date: Tue, 11 Jun 2013 15:40:30 +0200
Subject: [PATCH] Get rid of BlinqApplication.

Rename the class to WebEngineContext and keep it as a ref-counted member
of pages instead. Also:
- Change the user-agent product to QtWebEngine
- Don't pass actual command line arguments to Chromium anymore
- Allow attaching to the event loop through Before/AfterRun instead of blocking
---
 example/main.cpp                              |  9 +-
 lib/lib.pro                                   | 10 +--
 lib/qquickwebcontentsview.cpp                 | 10 +++
 lib/qquickwebcontentsview.h                   |  2 +
 lib/qwebcontentsview.cpp                      |  4 +
 ...application.cpp => web_engine_context.cpp} | 83 +++++++++++--------
 ...linqapplication.h => web_engine_context.h} | 23 +++--
 patches/0001-My-local-fixes.patch             | 12 +--
 ...ebEngineContext-to-RunLoop-s-friends.patch | 33 ++++++++
 patches/patch-chromium.sh                     |  2 +-
 10 files changed, 131 insertions(+), 57 deletions(-)
 rename lib/{blinqapplication.cpp => web_engine_context.cpp} (80%)
 rename lib/{blinqapplication.h => web_engine_context.h} (81%)
 create mode 100644 patches/0002-Add-WebEngineContext-to-RunLoop-s-friends.patch

diff --git a/example/main.cpp b/example/main.cpp
index edd75f3ec..01850b879 100644
--- a/example/main.cpp
+++ b/example/main.cpp
@@ -39,13 +39,14 @@
 **
 ****************************************************************************/
 
-#include <blinqapplication.h>
 #include "quickwindow.h"
 #include "widgetwindow.h"
 
+#include "qquickwebcontentsview.h"
+
 int mainWidget(int argc, char **argv)
 {
-    BlinqApplication app(argc, argv);
+    QApplication app(argc, argv);
 
     WidgetWindow window;
     window.show();
@@ -55,7 +56,9 @@ int mainWidget(int argc, char **argv)
 
 int mainQuick(int argc, char **argv)
 {
-    BlinqApplication app(argc, argv);
+    QGuiApplication app(argc, argv);
+
+    QQuickWebContentsView::registerType();
 
     QuickWindow window;
     window.show();
diff --git a/lib/lib.pro b/lib/lib.pro
index d8c47ef88..4db81a6f8 100644
--- a/lib/lib.pro
+++ b/lib/lib.pro
@@ -20,23 +20,21 @@ CONFIG(release, debug|release): DEFINES += NDEBUG
 QT += widgets quick
 
 SOURCES = \
-        blinqapplication.cpp \
         content_browser_client_qt.cpp \
         qquickwebcontentsview.cpp \
         qwebcontentsview.cpp \
         resource_context_qt.cpp \
         url_request_context_getter_qt.cpp \
-        web_contents_delegate_qt.cpp
-        web_event_factory.cpp
+        web_contents_delegate_qt.cpp \
+        web_engine_context.cpp
 
 HEADERS = \
-        blinqapplication.h \
         browser_context_qt.h \
         content_browser_client_qt.h \
         qquickwebcontentsview.h \
         qwebcontentsview.h \
         resource_context_qt.h \
         url_request_context_getter_qt.h \
-        web_contents_delegate_qt.h
-        web_event_factory.h
+        web_contents_delegate_qt.h \
+        web_engine_context.h
 
diff --git a/lib/qquickwebcontentsview.cpp b/lib/qquickwebcontentsview.cpp
index 469b030fd..06ba95b79 100644
--- a/lib/qquickwebcontentsview.cpp
+++ b/lib/qquickwebcontentsview.cpp
@@ -51,19 +51,29 @@
 #include "browser_context_qt.h"
 #include "content_browser_client_qt.h"
 #include "web_contents_delegate_qt.h"
+#include "web_engine_context.h"
 
 #include <QWidget>
 #include <QUrl>
 
+void QQuickWebContentsView::registerType()
+{
+    // FIXME: Do a proper plugin.
+    qmlRegisterType<QQuickWebContentsView>("QtWebEngine", 1, 0, "WebContentsView");
+}
+
 class QQuickWebContentsViewPrivate
 {
 public:
+    scoped_refptr<WebEngineContext> context;
     scoped_ptr<WebContentsDelegateQt> webContentsDelegate;
 };
 
 QQuickWebContentsView::QQuickWebContentsView()
 {
     d.reset(new QQuickWebContentsViewPrivate);
+    // This has to be the first thing we do.
+    d->context = WebEngineContext::current();
 
     content::BrowserContext* browser_context = static_cast<ContentBrowserClientQt*>(content::GetContentClient()->browser())->browser_context();
     d->webContentsDelegate.reset(WebContentsDelegateQt::CreateNewWindow(browser_context, GURL(std::string("http://qt-project.org/")), NULL, MSG_ROUTING_NONE, gfx::Size(), this));
diff --git a/lib/qquickwebcontentsview.h b/lib/qquickwebcontentsview.h
index 809bbf25e..9e9979b0a 100644
--- a/lib/qquickwebcontentsview.h
+++ b/lib/qquickwebcontentsview.h
@@ -51,6 +51,8 @@ class Q_DECL_EXPORT QQuickWebContentsView : public QQuickItem {
     Q_OBJECT
     Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
 public:
+    static void registerType();
+
     QQuickWebContentsView();
     ~QQuickWebContentsView();
 
diff --git a/lib/qwebcontentsview.cpp b/lib/qwebcontentsview.cpp
index 64bdb9c36..1f23fb0d1 100644
--- a/lib/qwebcontentsview.cpp
+++ b/lib/qwebcontentsview.cpp
@@ -51,6 +51,7 @@
 #include "browser_context_qt.h"
 #include "content_browser_client_qt.h"
 #include "web_contents_delegate_qt.h"
+#include "web_engine_context.h"
 
 #include <QWidget>
 #include <QUrl>
@@ -58,12 +59,15 @@
 class QWebContentsViewPrivate
 {
 public:
+    scoped_refptr<WebEngineContext> context;
     scoped_ptr<WebContentsDelegateQt> webContentsDelegate;
 };
 
 QWebContentsView::QWebContentsView()
 {
     d.reset(new QWebContentsViewPrivate);
+    // This has to be the first thing we do.
+    d->context = WebEngineContext::current();
 
     content::BrowserContext* browser_context = static_cast<ContentBrowserClientQt*>(content::GetContentClient()->browser())->browser_context();
     d->webContentsDelegate.reset(WebContentsDelegateQt::CreateNewWindow(browser_context, GURL(std::string("http://qt-project.org/")), NULL, MSG_ROUTING_NONE, gfx::Size(), this));
diff --git a/lib/blinqapplication.cpp b/lib/web_engine_context.cpp
similarity index 80%
rename from lib/blinqapplication.cpp
rename to lib/web_engine_context.cpp
index 732b7d1c7..5b9855a27 100644
--- a/lib/blinqapplication.cpp
+++ b/lib/web_engine_context.cpp
@@ -39,7 +39,7 @@
 **
 ****************************************************************************/
 
-#include "blinqapplication.h"
+#include "web_engine_context.h"
 
 #include <math.h>
 
@@ -57,10 +57,13 @@
 #include "webkit/common/user_agent/user_agent_util.h"
 
 #include "content_browser_client_qt.h"
-#include "qquickwebcontentsview.h"
+#include <QCoreApplication>
+#include <QStringList>
 
 namespace {
 
+static WebEngineContext* sContext = 0;
+
 static inline base::FilePath::StringType qStringToStringType(const QString &str)
 {
 #if defined(OS_POSIX)
@@ -70,7 +73,7 @@ static inline base::FilePath::StringType qStringToStringType(const QString &str)
 #endif
 }
 
-static QByteArray blinqProcessPath() {
+static QByteArray subProcessPath() {
     static bool initialized = false;
 #ifdef BLINQ_PROCESS_PATH
     static QByteArray processPath(BLINQ_PROCESS_PATH);
@@ -95,7 +98,7 @@ static void initializeBlinkPaths()
     if (initialized)
         return;
 
-    PathService::Override(content::CHILD_PROCESS_EXE, base::FilePath(qStringToStringType(QString(blinqProcessPath()))));
+    PathService::Override(content::CHILD_PROCESS_EXE, base::FilePath(qStringToStringType(QString(subProcessPath()))));
 }
 
 // Return a timeout suitable for the glib loop, -1 to block forever,
@@ -114,29 +117,27 @@ int GetTimeIntervalMilliseconds(const base::TimeTicks& from) {
   return delay < 0 ? 0 : delay;
 }
 
-class MessagePump : public QObject,
+class MessagePumpForUIQt : public QObject,
                     public base::MessagePump
 {
 public:
-    MessagePump()
-        : m_delegate(0)
+    MessagePumpForUIQt()
+        // Usually this gets passed through Run, but since we have
+        // our own event loop, attach it explicitely ourselves.
+        : m_delegate(base::MessageLoopForUI::current())
     {
     }
 
     virtual void Run(Delegate *delegate)
     {
-        // It would be possible to do like the Android message loop and use
-        // Start(Delegate*) instead of Run to avoid blocking, but we still
-        // need to grab the command line arguments, so keep it simple for now
-        // by forcing the use of BlinqApplication.
-        m_delegate = delegate;
-        QApplication::exec();
-        m_delegate = 0;
+        // FIXME: This could be needed if we want to run Chromium tests.
+        // We could run a QEventLoop here.
+        Q_ASSERT(false);
     }
 
     virtual void Quit()
     {
-        QCoreApplication::instance()->quit();
+        Q_ASSERT(false);
     }
 
     virtual void ScheduleWork()
@@ -189,7 +190,7 @@ private:
 
 base::MessagePump* messagePumpFactory()
 {
-    return new MessagePump;
+    return new MessagePumpForUIQt;
 }
 
 class ContentMainDelegateQt : public content::ContentMainDelegate
@@ -207,31 +208,31 @@ private:
 
 }
 
-BlinqApplication::BlinqApplication(int &argc, char **argv)
-    : QApplication(argc, argv)
+WebEngineContext::WebEngineContext()
 {
-    {
-        int myArgc = argc + 3;
-        const char **myArgv = new const char *[myArgc];
+    Q_ASSERT(!sContext);
+    sContext = this;
 
-        for (int i = 0; i < argc; ++i)
-            myArgv[i] = argv[i];
+    {
         QByteArray subProcessPathOption("--browser-subprocess-path=");
-        subProcessPathOption.append(blinqProcessPath());
-        myArgv[argc] = subProcessPathOption.constData();
-        myArgv[argc + 1] = "--no-sandbox";
+        subProcessPathOption.append(subProcessPath());
 
-        std::string ua = webkit_glue::BuildUserAgentFromProduct("Qrome/0.1");
+        std::string ua = webkit_glue::BuildUserAgentFromProduct("QtWebEngine/0.1");
 
         QByteArray userAgentParameter("--user-agent=");
         userAgentParameter.append(QString::fromStdString(ua).toUtf8());
-        myArgv[argc + 2] = userAgentParameter.constData();
 
-        CommandLine::Init(myArgc, myArgv);
+        const int argc = 4;
+        const char* argv[4];
+        argv[0] = QCoreApplication::arguments()[0].toLatin1().constData();
+        argv[1] = subProcessPathOption.constData();
+        argv[2] = "--no-sandbox";
+        argv[3] = userAgentParameter.constData();
 
-        delete [] myArgv;
+        CommandLine::Init(argc, argv);
     }
 
+    // This needs to be set before the MessageLoop is created by BrowserMainRunner.
     base::MessageLoop::InitMessagePumpForUIFactory(::messagePumpFactory);
 
     static content::ContentMainRunner *runner = 0;
@@ -253,12 +254,24 @@ BlinqApplication::BlinqApplication(int &argc, char **argv)
 
     base::ThreadRestrictions::SetIOAllowed(true);
 
-    // FIXME: Do a proper plugin.
-    qmlRegisterType<QQuickWebContentsView>("QtWebEngine", 1, 0, "WebContentsView");
+    // Once the MessageLoop has been created, attach a top-level RunLoop.
+    m_runLoop.reset(new base::RunLoop);
+    m_runLoop->BeforeRun();
+}
+
+WebEngineContext::~WebEngineContext()
+{
+    m_runLoop->AfterRun();
+
+    Q_ASSERT(sContext == this);
+    sContext = 0;
 }
 
-int BlinqApplication::exec()
+scoped_refptr<WebEngineContext> WebEngineContext::current()
 {
-    base::RunLoop runLoop;
-    runLoop.Run();
+    scoped_refptr<WebEngineContext> current = sContext;
+    if (!current)
+        current = new WebEngineContext;
+    Q_ASSERT(sContext == current);
+    return current;
 }
diff --git a/lib/blinqapplication.h b/lib/web_engine_context.h
similarity index 81%
rename from lib/blinqapplication.h
rename to lib/web_engine_context.h
index 68034e613..2bf20ac4b 100644
--- a/lib/blinqapplication.h
+++ b/lib/web_engine_context.h
@@ -39,15 +39,26 @@
 **
 ****************************************************************************/
 
-#ifndef BLINQAPPLICATION_H
-#define BLINQAPPLICATION_H
+#ifndef WEB_ENGINE_CONTEXT_H
+#define WEB_ENGINE_CONTEXT_H
 
-#include <QApplication>
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 
-class Q_DECL_EXPORT BlinqApplication : public QApplication {
+namespace base {
+class RunLoop;
+}
+
+class WebEngineContext : public base::RefCounted<WebEngineContext> {
 public:
-    BlinqApplication(int &argc, char **argv);
-	static int exec();
+    static scoped_refptr<WebEngineContext> current();
+
+private:
+    friend class base::RefCounted<WebEngineContext>;
+    WebEngineContext();
+    ~WebEngineContext();
+
+    scoped_ptr<base::RunLoop> m_runLoop;
 };
 
 #endif
diff --git a/patches/0001-My-local-fixes.patch b/patches/0001-My-local-fixes.patch
index ff5e1308c..87a08aab9 100644
--- a/patches/0001-My-local-fixes.patch
+++ b/patches/0001-My-local-fixes.patch
@@ -1,7 +1,7 @@
-From 4ce3baa412e9799684c0b7379814384489c2ae5a Mon Sep 17 00:00:00 2001
+From 0a3b4029af83089cb313b555a47c5c510dc94cc7 Mon Sep 17 00:00:00 2001
 From: Simon Hausmann <simon.hausmann@digia.com>
 Date: Mon, 29 Apr 2013 11:25:37 +0200
-Subject: [PATCH] My local fixes
+Subject: [PATCH 1/2] My local fixes
 
 ---
  content/browser/zygote_host/zygote_host_impl_linux.cc | 1 +
@@ -10,7 +10,7 @@ Subject: [PATCH] My local fixes
  3 files changed, 4 insertions(+), 2 deletions(-)
 
 diff --git a/content/browser/zygote_host/zygote_host_impl_linux.cc b/content/browser/zygote_host/zygote_host_impl_linux.cc
-index 4e28c55..ddd3513 100644
+index ba7884f8..50eacc8 100644
 --- a/content/browser/zygote_host/zygote_host_impl_linux.cc
 +++ b/content/browser/zygote_host/zygote_host_impl_linux.cc
 @@ -70,6 +70,7 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) {
@@ -43,10 +43,10 @@ index bed5ff2..992e0d0 100644
    virtual ~ContentMainRunner() {}
  
 diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h
-index 198ecad..778fcac 100644
+index 4c1d110..ddf6a32 100644
 --- a/content/public/common/content_client.h
 +++ b/content/public/common/content_client.h
-@@ -60,7 +60,7 @@ CONTENT_EXPORT void SetContentClient(ContentClient* client);
+@@ -63,7 +63,7 @@ CONTENT_EXPORT void SetContentClient(ContentClient* client);
  
  #if defined(CONTENT_IMPLEMENTATION)
  // Content's embedder API should only be used by content.
@@ -56,5 +56,5 @@ index 198ecad..778fcac 100644
  
  // Used for tests to override the relevant embedder interfaces. Each method
 -- 
-1.8.1.2
+1.8.3
 
diff --git a/patches/0002-Add-WebEngineContext-to-RunLoop-s-friends.patch b/patches/0002-Add-WebEngineContext-to-RunLoop-s-friends.patch
new file mode 100644
index 000000000..c822c0162
--- /dev/null
+++ b/patches/0002-Add-WebEngineContext-to-RunLoop-s-friends.patch
@@ -0,0 +1,33 @@
+From 1f686ea3aafa4d950d92a7f945cfec5b6fb02dfd Mon Sep 17 00:00:00 2001
+From: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
+Date: Tue, 11 Jun 2013 15:44:26 +0200
+Subject: [PATCH 2/2] Add WebEngineContext to RunLoop's friends.
+
+---
+ base/run_loop.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/base/run_loop.h b/base/run_loop.h
+index 380c8bf..12f810a 100644
+--- a/base/run_loop.h
++++ b/base/run_loop.h
+@@ -10,6 +10,8 @@
+ #include "base/memory/weak_ptr.h"
+ #include "base/message_loop.h"
+ 
++class WebEngineContext;
++
+ namespace base {
+ #if defined(OS_ANDROID)
+ class MessagePumpForUI;
+@@ -74,6 +76,7 @@ class BASE_EXPORT RunLoop {
+ 
+  private:
+   friend class MessageLoop;
++  friend class ::WebEngineContext;
+ #if defined(OS_ANDROID)
+   // Android doesn't support the blocking MessageLoop::Run, so it calls
+   // BeforeRun and AfterRun directly.
+-- 
+1.8.3
+
diff --git a/patches/patch-chromium.sh b/patches/patch-chromium.sh
index cb74fecc1..5abc44203 100755
--- a/patches/patch-chromium.sh
+++ b/patches/patch-chromium.sh
@@ -20,7 +20,7 @@ if [ "$2" = "--update" ]; then
 fi
 
 echo "Applying patches..."
-git am $PATCH_DIR/0001-My-local-fixes.patch
+git am $PATCH_DIR/0001-My-local-fixes.patch $PATCH_DIR/0002-Add-WebEngineContext-to-RunLoop-s-friends.patch
 
 cd tools/gyp
 echo "Entering $PWD"
-- 
GitLab