diff --git a/example/main.cpp b/example/main.cpp index bae44ab1c4a430c3e07ed7ff6b2353f1a2200196..1b2c658c410a31a1399446af3a2beb6b11ae3249 100644 --- a/example/main.cpp +++ b/example/main.cpp @@ -1,14 +1,15 @@ #include <QtGui> #include <QtWidgets> +#include <blinqapplication.h> #include <blinqpage.h> int main(int argc, char **argv) { printf("main called\n"); - QApplication app(argc, argv); + BlinqApplication app(argc, argv); - BlinqPage page(argc, argv); + BlinqPage page; // page.window()->show(); return app.exec(); diff --git a/lib/blinqapplication.cpp b/lib/blinqapplication.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2fb42e186d19455c37d7e2747fee2693bb899db7 --- /dev/null +++ b/lib/blinqapplication.cpp @@ -0,0 +1,233 @@ +#include "blinqapplication.h" + +#include <math.h> + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/message_loop.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/threading/thread_restrictions.h" +#include "content/public/app/content_main_delegate.h" +#include "content/public/app/content_main_runner.h" +#include "content/public/browser/browser_main_runner.h" +#include "content/public/common/content_paths.h" +#include "content/public/common/main_function_params.h" +#include "content/shell/shell_browser_context.h" +#include "content/shell/shell_content_browser_client.h" +#include "webkit/common/user_agent/user_agent_util.h" + +#include "web_contents_view_qt.h" + +namespace { + +static inline base::FilePath::StringType qStringToStringType(const QString &str) +{ +#if defined(OS_POSIX) + return str.toStdString(); +#elif defined(OS_WIN) + return str.toStdWString(); +#endif +} + +static QByteArray blinqProcessPath() { + static bool initialized = false; +#ifdef BLINQ_PROCESS_PATH + static QByteArray processPath(BLINQ_PROCESS_PATH); +#else + static QByteArray processPath; +#endif + if (initialized) + return processPath; + // Allow overriding at runtime for the time being. + const QByteArray fromEnv = qgetenv("BLINQ_PROCESS_PATH"); + if (!fromEnv.isEmpty()) + processPath = fromEnv; + if (processPath.isEmpty()) + qFatal("BLINQ_PROCESS_PATH environment variable not set or empty."); + initialized = true; + return processPath; +} + +static void initializeBlinkPaths() +{ + static bool initialized = false; + if (initialized) + return; + + PathService::Override(content::CHILD_PROCESS_EXE, base::FilePath(qStringToStringType(QString(blinqProcessPath())))); +} + +// Return a timeout suitable for the glib loop, -1 to block forever, +// 0 to return right away, or a timeout in milliseconds from now. +int GetTimeIntervalMilliseconds(const base::TimeTicks& from) { + if (from.is_null()) + return -1; + + // Be careful here. TimeDelta has a precision of microseconds, but we want a + // value in milliseconds. If there are 5.5ms left, should the delay be 5 or + // 6? It should be 6 to avoid executing delayed work too early. + int delay = static_cast<int>( + ceil((from - base::TimeTicks::Now()).InMillisecondsF())); + + // If this value is negative, then we need to run delayed work soon. + return delay < 0 ? 0 : delay; +} + +class MessagePump : public QObject, + public base::MessagePump +{ +public: + MessagePump() + : m_delegate(0) + { + } + + 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; + } + + virtual void Quit() + { + QCoreApplication::instance()->quit(); + } + + virtual void ScheduleWork() + { + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + } + + virtual void ScheduleDelayedWork(const base::TimeTicks &delayed_work_time) + { + startTimer(GetTimeIntervalMilliseconds(delayed_work_time)); + } + +protected: + virtual void customEvent(QEvent *ev) + { + if (handleScheduledWork()) + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + } + + virtual void timerEvent(QTimerEvent *ev) + { + killTimer(ev->timerId()); + + base::TimeTicks next_delayed_work_time; + m_delegate->DoDelayedWork(&next_delayed_work_time); + + if (!next_delayed_work_time.is_null()) + startTimer(GetTimeIntervalMilliseconds(next_delayed_work_time)); + } + +private: + bool handleScheduledWork() { + bool more_work_is_plausible = m_delegate->DoWork(); + + base::TimeTicks delayed_work_time; + more_work_is_plausible |= m_delegate->DoDelayedWork(&delayed_work_time); + + if (more_work_is_plausible) + return true; + + more_work_is_plausible |= m_delegate->DoIdleWork(); + if (!more_work_is_plausible && !delayed_work_time.is_null()) + startTimer(GetTimeIntervalMilliseconds(delayed_work_time)); + + return more_work_is_plausible; + } + + Delegate *m_delegate; +}; + +base::MessagePump* messagePumpFactory() +{ + return new MessagePump; +} + +class ContentBrowserClientQt : public content::ShellContentBrowserClient +{ +public: + virtual content::WebContentsViewPort* OverrideCreateWebContentsView(content::WebContents* web_contents, content::RenderViewHostDelegateView** render_view_host_delegate_view) + { + fprintf(stderr, "OverrideCreateWebContentsView\n"); + WebContentsViewQt* rv = new WebContentsViewQt(web_contents); + *render_view_host_delegate_view = rv; + return rv; + } +}; + +class ContentMainDelegateQt : public content::ContentMainDelegate +{ +public: + content::ContentBrowserClient* CreateContentBrowserClient() + { + m_browserClient.reset(new ContentBrowserClientQt); + return m_browserClient.get(); + } + +private: + scoped_ptr<ContentBrowserClientQt> m_browserClient; +}; + +} + +BlinqApplication::BlinqApplication(int &argc, char **argv) + : QApplication(argc, argv) +{ + { + int myArgc = argc + 3; + const char **myArgv = new const char *[myArgc]; + + 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"; + + std::string ua = webkit_glue::BuildUserAgentFromProduct("Qrome/0.1"); + + QByteArray userAgentParameter("--user-agent="); + userAgentParameter.append(QString::fromStdString(ua).toUtf8()); + myArgv[argc + 2] = userAgentParameter.constData(); + + CommandLine::Init(myArgc, myArgv); + + delete [] myArgv; + } + + base::MessageLoop::InitMessagePumpForUIFactory(::messagePumpFactory); + + static content::ContentMainRunner *runner = 0; + if (!runner) { + runner = content::ContentMainRunner::Create(); + runner->Initialize(0, 0, new ContentMainDelegateQt); + } + + initializeBlinkPaths(); + + static content::BrowserMainRunner *browserRunner = 0; + if (!browserRunner) { + //CommandLine::Init(0, 0); + + browserRunner = content::BrowserMainRunner::Create(); + + browserRunner->Initialize(content::MainFunctionParams(*CommandLine::ForCurrentProcess())); + } + + base::ThreadRestrictions::SetIOAllowed(true); +} + +int BlinqApplication::exec() +{ + base::RunLoop runLoop; + runLoop.Run(); +} diff --git a/lib/blinqapplication.h b/lib/blinqapplication.h new file mode 100644 index 0000000000000000000000000000000000000000..7b8c837708d01e658d510cd5e725a00ab0a13d31 --- /dev/null +++ b/lib/blinqapplication.h @@ -0,0 +1,12 @@ +#ifndef BLINQAPPLICATION_H +#define BLINQAPPLICATION_H + +#include <QApplication> + +class Q_DECL_EXPORT BlinqApplication : public QApplication { +public: + BlinqApplication(int &argc, char **argv); + static int exec(); +}; + +#endif \ No newline at end of file diff --git a/lib/blinqpage.cpp b/lib/blinqpage.cpp index a178566be1102bbde550f2544ca82cfc16fa1b6e..8a68ea79f3e90d1eb276692bee3561c2e29e0a9c 100644 --- a/lib/blinqpage.cpp +++ b/lib/blinqpage.cpp @@ -9,39 +9,25 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/web_contents_view.h" -#include "content/public/browser/browser_main_runner.h" -#include "content/public/app/content_main_runner.h" -#include "content/public/app/content_main_delegate.h" -#include "content/public/common/content_paths.h" -#include "content/public/common/main_function_params.h" #include "net/url_request/url_request_context_getter.h" #include "base/files/scoped_temp_dir.h" -#include "base/path_service.h" -#include "base/files/file_path.h" #include "base/event_types.h" -#include "base/command_line.h" #include "ui/gfx/insets.h" -#include "base/message_loop.h" #include "ui/gfx/screen.h" #include "ui/gfx/rect.h" #include "ui/gfx/rect_conversions.h" #include "ui/surface/transport_dib.h" -#include "base/threading/thread_restrictions.h" #include "content/common/view_messages.h" -#include "content/shell/shell_browser_context.h" -#include "content/shell/app/shell_main_delegate.h" -#include "content/shell/shell_content_browser_client.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/renderer_host/render_view_host_factory.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/backing_store.h" -#include "webkit/common/user_agent/user_agent_util.h" +#include "content/shell/shell_browser_context.h" +#include "content/shell/shell_content_browser_client.h" #include "skia/ext/platform_canvas.h" #include "backing_store_qt.h" -#include "raster_window.h" #include "render_widget_host_view_qt.h" -#include "web_contents_view_qt.h" #include <QByteArray> #include <QWindow> @@ -71,68 +57,6 @@ private: Context *context; }; -class ContentBrowserClientQt : public content::ShellContentBrowserClient -{ -public: - virtual content::WebContentsViewPort* OverrideCreateWebContentsView(content::WebContents* web_contents, content::RenderViewHostDelegateView** render_view_host_delegate_view) - { - fprintf(stderr, "OverrideCreateWebContentsView\n"); - WebContentsViewQt* rv = new WebContentsViewQt(web_contents); - *render_view_host_delegate_view = rv; - return rv; - } -}; - -class ContentMainDelegateQt : public content::ContentMainDelegate -{ -public: - content::ContentBrowserClient* CreateContentBrowserClient() - { - m_browserClient.reset(new ContentBrowserClientQt); - return m_browserClient.get(); - } - -private: - scoped_ptr<ContentBrowserClientQt> m_browserClient; -}; - -static inline base::FilePath::StringType qStringToStringType(const QString &str) -{ -#if defined(OS_POSIX) - return str.toStdString(); -#elif defined(OS_WIN) - return str.toStdWString(); -#endif -} - -static QByteArray blinqProcessPath() { - static bool initialized = false; -#ifdef BLINQ_PROCESS_PATH - static QByteArray processPath(BLINQ_PROCESS_PATH); -#else - static QByteArray processPath; -#endif - if (initialized) - return processPath; - // Allow overriding at runtime for the time being. - const QByteArray fromEnv = qgetenv("BLINQ_PROCESS_PATH"); - if (!fromEnv.isEmpty()) - processPath = fromEnv; - if (processPath.isEmpty()) - qFatal("BLINQ_PROCESS_PATH environment variable not set or empty."); - initialized = true; - return processPath; -} - -static void initializeBlinkPaths() -{ - static bool initialized = false; - if (initialized) - return; - - PathService::Override(content::CHILD_PROCESS_EXE, base::FilePath(qStringToStringType(QString(blinqProcessPath())))); -} - class Context : public content::BrowserContext { public: @@ -201,108 +125,6 @@ public: } }; -// Return a timeout suitable for the glib loop, -1 to block forever, -// 0 to return right away, or a timeout in milliseconds from now. -int GetTimeIntervalMilliseconds(const base::TimeTicks& from) { - if (from.is_null()) - return -1; - - // Be careful here. TimeDelta has a precision of microseconds, but we want a - // value in milliseconds. If there are 5.5ms left, should the delay be 5 or - // 6? It should be 6 to avoid executing delayed work too early. - int delay = static_cast<int>( - ceil((from - base::TimeTicks::Now()).InMillisecondsF())); - - // If this value is negative, then we need to run delayed work soon. - return delay < 0 ? 0 : delay; -} - -#if 0 -class MessagePump : public QObject, - public base::MessagePump -{ -public: - struct DelayedWorkEvent : public QEvent - { - public: - DelayedWorkEvent(int msecs) - : QEvent(static_cast<QEvent::Type>(QEvent::User + 1)) - , m_secs(msecs) - {} - - int m_secs; - }; - - MessagePump() - : m_delegate(0) - { - } - - virtual void Run(Delegate *delegate) - { - m_delegate = delegate; - printf("RUN\n"); - } - - virtual void Quit() - { - printf("QUIT?!\n"); - } - - virtual void ScheduleWork() - { - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); - printf("ScheduleWork\n"); - } - - virtual void ScheduleDelayedWork(const base::TimeTicks &delayed_work_time) - { - printf("Schedule Delayed Work %d\n", GetTimeIntervalMilliseconds(delayed_work_time)); -// QCoreApplication::postEvent(this, new DelayedWorkEvent(GetTimeIntervalMilliseconds(delayed_work_time))); - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); - } - -protected: - virtual void customEvent(QEvent *ev) - { - if (ev->type() == QEvent::User + 1) { - startTimer(static_cast<DelayedWorkEvent*>(ev)->m_secs); - return; - } - printf("customEvent\n"); - if (!m_delegate) - return; - if (m_delegate->DoWork()) - return; - m_delegate->DoIdleWork(); - } - - virtual void timerEvent(QTimerEvent *ev) - { - printf("timerEvent\n"); - killTimer(ev->timerId()); - if (!m_delegate) - return; - base::TimeTicks next_delayed_work_time; - if (!m_delegate->DoDelayedWork(&next_delayed_work_time)) - m_delegate->DoIdleWork(); - - if (!next_delayed_work_time.is_null()) { - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); -// startTimer(GetTimeIntervalMilliseconds(next_delayed_work_time)); - } - } - -private: - Delegate *m_delegate; -}; - -base::MessagePump* messagePumpFactory() -{ - return new MessagePump; -} -#endif - } class BlinqPagePrivate @@ -312,51 +134,8 @@ public: scoped_ptr<content::WebContents> contents; }; -BlinqPage::BlinqPage(int argc, char **argv) +BlinqPage::BlinqPage() { - { - int myArgc = argc + 3; - const char **myArgv = new const char *[myArgc]; - - 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"; - - std::string ua = webkit_glue::BuildUserAgentFromProduct("Qrome/0.1"); - - QByteArray userAgentParameter("--user-agent="); - userAgentParameter.append(QString::fromStdString(ua).toUtf8()); - myArgv[argc + 2] = userAgentParameter.constData(); - - CommandLine::Init(myArgc, myArgv); - - delete [] myArgv; - -// base::MessageLoop::InitMessagePumpForUIFactory(::messagePumpFactory); - } - - static content::ContentMainRunner *runner = 0; - if (!runner) { - runner = content::ContentMainRunner::Create(); - runner->Initialize(0, 0, new ContentMainDelegateQt); - } - - initializeBlinkPaths(); - - static content::BrowserMainRunner *browserRunner = 0; - if (!browserRunner) { - //CommandLine::Init(0, 0); - - browserRunner = content::BrowserMainRunner::Create(); - - browserRunner->Initialize(content::MainFunctionParams(*CommandLine::ForCurrentProcess())); - } - - base::ThreadRestrictions::SetIOAllowed(true); - d.reset(new BlinqPagePrivate); d->context.reset(static_cast<content::ShellContentBrowserClient*>(content::GetContentClient()->browser())->browser_context()); @@ -367,8 +146,6 @@ BlinqPage::BlinqPage(int argc, char **argv) // content::Referrer(), // content::PAGE_TRANSITION_TYPED, // std::string()); - - MessageLoopForUI::current()->Run(); } BlinqPage::~BlinqPage() diff --git a/lib/blinqpage.h b/lib/blinqpage.h index 6c3933b83d51de045cda2c1b9f1cfbb3b3439bf2..c07619d8cb3dd7b771faee3cbf103c4b82724210 100644 --- a/lib/blinqpage.h +++ b/lib/blinqpage.h @@ -11,7 +11,7 @@ class BlinqPagePrivate; class Q_DECL_EXPORT BlinqPage { public: - BlinqPage(int argc, char **argv); + BlinqPage(); ~BlinqPage(); QWindow *window(); diff --git a/lib/lib.pro b/lib/lib.pro index 59c55779231fdf59dee8b47b2c6bac1e82ce0419..cb766577e2f906d09f12648a7db1fbd7ffaae5af 100644 --- a/lib/lib.pro +++ b/lib/lib.pro @@ -20,6 +20,7 @@ QT += gui-private widgets SOURCES = \ backing_store_qt.cpp \ + blinqapplication.cpp \ blinqpage.cpp \ raster_window.cpp \ render_widget_host_view_qt.cpp \ @@ -29,6 +30,7 @@ SOURCES = \ HEADERS = \ backing_store_qt.h \ + blinqapplication.h \ blinqpage.h \ raster_window.h \ render_widget_host_view_qt.h \ diff --git a/lib/web_contents_view_qt.h b/lib/web_contents_view_qt.h index 068df4e7dda480a19754e5252a22d42281b4fafe..c5d38a0ef1508bab3a46031a49107a830b2c031c 100644 --- a/lib/web_contents_view_qt.h +++ b/lib/web_contents_view_qt.h @@ -7,6 +7,7 @@ #include "content/port/browser/render_view_host_delegate_view.h" #include "content/port/browser/web_contents_view_port.h" #include "render_widget_host_view_qt.h" +#include "raster_window.h" class WebContentsViewQt : public content::WebContentsViewPort