diff options
Diffstat (limited to 'src/core')
56 files changed, 7564 insertions, 0 deletions
diff --git a/src/core/backing_store_qt.cpp b/src/core/backing_store_qt.cpp new file mode 100644 index 000000000..b12f09f18 --- /dev/null +++ b/src/core/backing_store_qt.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "backing_store_qt.h" + +#include "type_conversion.h" + +#include "content/public/browser/render_process_host.h" +#include "ui/gfx/rect.h" +#include "ui/gfx/rect_conversions.h" +#include "ui/gfx/vector2d_conversions.h" +#include "skia/ext/platform_canvas.h" + +#include <QPainter> +#include <QScreen> +#include <QSizeF> +#include <QWindow> + +QT_BEGIN_NAMESPACE +// from qbackingstore.cpp +extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); +QT_END_NAMESPACE + +BackingStoreQt::BackingStoreQt(content::RenderWidgetHost *host, const gfx::Size &size, QWindow* parent) + : content::BackingStore(host, size) + , m_deviceScaleFactor((parent && parent->screen()) ? parent->screen()->devicePixelRatio() : 1) + , m_pixelBuffer(size.width() * m_deviceScaleFactor, size.height() * m_deviceScaleFactor, QImage::Format_ARGB32_Premultiplied) +{ +} + +BackingStoreQt::~BackingStoreQt() +{ +} + +void BackingStoreQt::paintToTarget(QPainter* painter, const QRectF& rect) +{ + if (m_pixelBuffer.isNull()) + return; + + qreal x = rect.x() * m_deviceScaleFactor; + qreal y = rect.y() * m_deviceScaleFactor; + qreal w = rect.width() * m_deviceScaleFactor; + qreal h = rect.height() * m_deviceScaleFactor; + + QRectF source(x, y, w, h); + painter->drawImage(rect, m_pixelBuffer, source); +} + +void BackingStoreQt::PaintToBackingStore(content::RenderProcessHost *process, + TransportDIB::Id bitmap, + const gfx::Rect &bitmap_rect, + const std::vector<gfx::Rect> ©_rects, + float scale_factor, + const base::Closure &completion_callback, + bool *scheduled_completion_callback) +{ + if (bitmap_rect.IsEmpty()) + return; + + *scheduled_completion_callback = false; + TransportDIB* dib = process->GetTransportDIB(bitmap); + if (!dib) + return; + + gfx::Rect pixel_bitmap_rect = gfx::ToEnclosingRect(gfx::ScaleRect(bitmap_rect, scale_factor)); + + uint8_t* bitmapData = static_cast<uint8_t*>(dib->memory()); + const QImage img(bitmapData, pixel_bitmap_rect.width(), pixel_bitmap_rect.height(), QImage::Format_ARGB32); + + QPainter painter(&m_pixelBuffer); + for (size_t i = 0; i < copy_rects.size(); ++i) { + gfx::Rect copy_rect = gfx::ToEnclosingRect(gfx::ScaleRect(copy_rects[i], scale_factor)); + + QRect source = QRect( copy_rect.x() - pixel_bitmap_rect.x() + , copy_rect.y() - pixel_bitmap_rect.y() + , copy_rect.width() + , copy_rect.height()); + + gfx::Rect copy_rect_dst = gfx::ToEnclosingRect(gfx::ScaleRect(copy_rects[i], m_deviceScaleFactor)); + + QRect destination = QRect( copy_rect_dst.x() + , copy_rect_dst.y() + , copy_rect_dst.width() + , copy_rect_dst.height()); + + painter.drawImage(destination, img, source); + } +} + +void BackingStoreQt::ScrollBackingStore(const gfx::Vector2d &delta, const gfx::Rect &clip_rect, const gfx::Size &view_size) +{ + DCHECK(delta.x() == 0 || delta.y() == 0); + + gfx::Rect pixel_rect = gfx::ToEnclosingRect(gfx::ScaleRect(clip_rect, m_deviceScaleFactor)); + gfx::Vector2d pixel_delta = gfx::ToFlooredVector2d(gfx::ScaleVector2d(delta, m_deviceScaleFactor)); + + // Logic borrowed from QPixmap::scroll and QRasterPlatformPixmap::scroll. + QRect dest = toQt(pixel_rect) & m_pixelBuffer.rect(); + QRect src = dest.translated(-pixel_delta.x(), -pixel_delta.y()) & dest; + qt_scrollRectInImage(m_pixelBuffer, src, QPoint(pixel_delta.x(), pixel_delta.y())); +} + +bool BackingStoreQt::CopyFromBackingStore(const gfx::Rect &rect, skia::PlatformBitmap *output) +{ + const int width = std::min(m_pixelBuffer.width(), rect.width()); + const int height = std::min(m_pixelBuffer.height(), rect.height()); + + if (!output->Allocate(width, height, true)) + return false; + + // This code assumes a visual mode where a pixel is + // represented using a 32-bit unsigned int, with a byte per component. + const SkBitmap& bitmap = output->GetBitmap(); + if (bitmap.rowBytes() != 4) + return false; + + SkAutoLockPixels alp(bitmap); + + QImage cpy = m_pixelBuffer.copy(rect.x(), rect.y(), rect.width(), rect.height()); + + // Convert the format and remove transparency. + if (cpy.format() != QImage::Format_RGB32) + cpy = cpy.convertToFormat(QImage::Format_RGB32); + + const uint8_t* src = cpy.bits(); + uint8_t* dst = reinterpret_cast<uint8_t*>(bitmap.getAddr32(0,0)); + + int bytesPerLine = cpy.bytesPerLine(); + int bytesPerPixel = bytesPerLine / cpy.width(); + int copyLineLength = width * bytesPerPixel; + int lineOffset = rect.y() * cpy.width(); + int rowOffset = rect.x() * bytesPerPixel; + + const uint8_t* copyLineBegin = src + rowOffset + lineOffset; + + for (int lineNumber = 0; lineNumber < height; ++lineNumber) { + memcpy(dst, copyLineBegin, copyLineLength); + dst += copyLineLength; + copyLineBegin += cpy.width(); + } + + return true; +} + diff --git a/src/core/backing_store_qt.h b/src/core/backing_store_qt.h new file mode 100644 index 000000000..24f232a02 --- /dev/null +++ b/src/core/backing_store_qt.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BACKING_STORE_QT_H +#define BACKING_STORE_QT_H + +#include "content/browser/renderer_host/backing_store.h" + +#include <QPainter> +#include <QImage> + +class BackingStoreQt : public content::BackingStore +{ +public: + BackingStoreQt(content::RenderWidgetHost *host, const gfx::Size &size, QWindow* parent); + ~BackingStoreQt(); + + void paintToTarget(QPainter*, const QRectF& rect); + + virtual void PaintToBackingStore(content::RenderProcessHost *process, TransportDIB::Id bitmap, const gfx::Rect &bitmap_rect, + const std::vector<gfx::Rect> ©_rects, float scale_factor, const base::Closure &completion_callback, + bool *scheduled_completion_callback) Q_DECL_OVERRIDE; + + virtual void ScrollBackingStore(const gfx::Vector2d &delta, const gfx::Rect &clip_rect, const gfx::Size &view_size) Q_DECL_OVERRIDE; + virtual bool CopyFromBackingStore(const gfx::Rect &rect, skia::PlatformBitmap *output) Q_DECL_OVERRIDE; + +private: + // Number of physical pixels per view unit. This is 1 or 2 in practice. + float m_deviceScaleFactor; + + QImage m_pixelBuffer; +}; + +#endif // BACKING_STORE_QT_H diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h new file mode 100644 index 000000000..382b08ff3 --- /dev/null +++ b/src/core/browser_context_qt.h @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BROWSER_CONTEXT_QT_H +#define BROWSER_CONTEXT_QT_H + +#include "content/public/browser/browser_context.h" + +#include "base/files/scoped_temp_dir.h" + +#include "base/time/time.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/resource_context.h" +#include "content/public/browser/storage_partition.h" +#include "net/url_request/url_request_context.h" +#include "net/proxy/proxy_config_service.h" + +#include <qglobal.h> +#include <QByteArray> +#include <QCoreApplication> +#include <QDir> +#include <QStandardPaths> +#include <QString> +#include <QStringBuilder> + +#include "download_manager_delegate_qt.h" +#include "qtwebenginecoreglobal.h" +#include "resource_context_qt.h" +#include "type_conversion.h" +#include "url_request_context_getter_qt.h" + +class BrowserContextQt : public content::BrowserContext +{ +public: + explicit BrowserContextQt() + { + resourceContext.reset(new ResourceContextQt(this)); + downloadManagerDelegate.reset(new DownloadManagerDelegateQt); + } + + virtual ~BrowserContextQt() Q_DECL_OVERRIDE + { + if (resourceContext) + content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, resourceContext.release()); + } + + virtual base::FilePath GetPath() const Q_DECL_OVERRIDE + { + QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + if (dataLocation.isEmpty()) + dataLocation = QDir::homePath() % QDir::separator() % QChar::fromLatin1('.') % QCoreApplication::applicationName(); + + dataLocation.append(QDir::separator() % QStringLiteral("QtWebEngine")); + return base::FilePath(toFilePathString(dataLocation)); + } + + virtual bool IsOffTheRecord() const Q_DECL_OVERRIDE + { + return false; + } + + virtual net::URLRequestContextGetter* GetRequestContext() Q_DECL_OVERRIDE + { + return GetDefaultStoragePartition(this)->GetURLRequestContext(); + } + virtual net::URLRequestContextGetter* GetRequestContextForRenderProcess(int) Q_DECL_OVERRIDE { return GetRequestContext(); } + virtual net::URLRequestContextGetter* GetMediaRequestContext() Q_DECL_OVERRIDE { return GetRequestContext(); } + virtual net::URLRequestContextGetter* GetMediaRequestContextForRenderProcess(int) Q_DECL_OVERRIDE { return GetRequestContext(); } + virtual net::URLRequestContextGetter* GetMediaRequestContextForStoragePartition(const base::FilePath&, bool) Q_DECL_OVERRIDE { return GetRequestContext(); } + + virtual void RequestMIDISysExPermission(int render_process_id, int render_view_id, const GURL& requesting_frame, const MIDISysExPermissionCallback& callback) Q_DECL_OVERRIDE + { + // Always reject requests for testing. + callback.Run(false); + } + + virtual content::ResourceContext* GetResourceContext() Q_DECL_OVERRIDE + { + return resourceContext.get(); + } + + virtual content::DownloadManagerDelegate* GetDownloadManagerDelegate() Q_DECL_OVERRIDE + { + return downloadManagerDelegate.get(); + } + virtual content::GeolocationPermissionContext* GetGeolocationPermissionContext() Q_DECL_OVERRIDE + { + QT_NOT_YET_IMPLEMENTED + return 0; + } + virtual quota::SpecialStoragePolicy* GetSpecialStoragePolicy() Q_DECL_OVERRIDE + { + QT_NOT_YET_IMPLEMENTED + return 0; + } + + net::URLRequestContextGetter *CreateRequestContext(content::ProtocolHandlerMap* protocol_handlers) + { + url_request_getter_ = new URLRequestContextGetterQt(GetPath()); + static_cast<ResourceContextQt*>(resourceContext.get())->set_url_request_context_getter(url_request_getter_.get()); + return url_request_getter_.get(); + } + +private: + scoped_ptr<content::ResourceContext> resourceContext; + scoped_refptr<net::URLRequestContextGetter> url_request_getter_; + scoped_ptr<DownloadManagerDelegateQt> downloadManagerDelegate; + + DISALLOW_COPY_AND_ASSIGN(BrowserContextQt); +}; + +#endif // BROWSER_CONTEXT_QT_H diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp new file mode 100644 index 000000000..3d393c25d --- /dev/null +++ b/src/core/chromium_gpu_helper.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "chromium_gpu_helper.h" + +#include "content/common/gpu/gpu_channel_manager.h" +#include "content/common/gpu/sync_point_manager.h" +#include "content/gpu/gpu_child_thread.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/texture_manager.h" + +static void addSyncPointCallbackDelegate(content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback) +{ + syncPointManager->AddSyncPointCallback(sync_point, callback); +} + +base::MessageLoop *gpu_message_loop() +{ + return content::GpuChildThread::instance()->message_loop(); +} + +content::SyncPointManager *sync_point_manager() +{ + content::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager(); + return gpuChannelManager->sync_point_manager(); +} + +void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback) +{ + // We need to set our callback from the GPU thread, where the SyncPointManager lives. + gpuMessageLoop->PostTask(FROM_HERE, base::Bind(&addSyncPointCallbackDelegate, make_scoped_refptr(syncPointManager), sync_point, callback)); +} + +gpu::gles2::MailboxManager *mailbox_manager() +{ + content::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager(); + return gpuChannelManager->mailbox_manager(); +} + +gpu::gles2::Texture* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::gles2::MailboxName& name) +{ + return mailboxManager->ConsumeTexture(target, name); +} + +unsigned int service_id(gpu::gles2::Texture *tex) +{ + return tex->service_id(); +} diff --git a/src/core/chromium_gpu_helper.h b/src/core/chromium_gpu_helper.h new file mode 100644 index 000000000..e0ac8e2a3 --- /dev/null +++ b/src/core/chromium_gpu_helper.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CHROMIUM_GPU_HELPER_H +#define CHROMIUM_GPU_HELPER_H + +#include "base/callback.h" + +namespace base { +class MessageLoop; +} + +namespace content { +class SyncPointManager; +} + +namespace gpu { +namespace gles2 { +class MailboxManager; +class MailboxName; +class Texture; +} +} + +// These functions wrap code that needs to include headers that are +// incompatible with Qt GL headers. +// From the outside, types from incompatible headers referenced in these +// functions should only be forward-declared and considered as opaque types. + +base::MessageLoop *gpu_message_loop(); +content::SyncPointManager *sync_point_manager(); +gpu::gles2::MailboxManager *mailbox_manager(); + +void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback); +gpu::gles2::Texture* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::gles2::MailboxName& name); +unsigned int service_id(gpu::gles2::Texture *tex); + +#endif // CHROMIUM_GPU_HELPER_H diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp new file mode 100644 index 000000000..383fc6587 --- /dev/null +++ b/src/core/chromium_overrides.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "chromium_overrides.h" + +#include "base/message_loop/message_pump_gtk.h" +#include "content/browser/renderer_host/render_widget_host_view_base.h" + +#include <QGuiApplication> +#include <QScreen> +#include <QWindow> +#include <qpa/qplatformnativeinterface.h> + +#if defined(USE_X11) +#include <X11/Xlib.h> +#endif + +void GetScreenInfoFromNativeWindow(QWindow* window, WebKit::WebScreenInfo* results) +{ + QScreen* screen = window->screen(); + + WebKit::WebScreenInfo r; + r.deviceScaleFactor = screen->devicePixelRatio(); + r.depthPerComponent = 8; + r.depth = screen->depth(); + r.isMonochrome = (r.depth == 1); + + QRect screenGeometry = screen->geometry(); + r.rect = WebKit::WebRect(screenGeometry.x(), screenGeometry.y(), screenGeometry.width(), screenGeometry.height()); + QRect available = screen->availableGeometry(); + r.availableRect = WebKit::WebRect(available.x(), available.y(), available.width(), available.height()); + *results = r; +} + +namespace base { + +#if defined(USE_X11) +Display* MessagePumpGtk::GetDefaultXDisplay() { + static void *display = qApp->platformNativeInterface()->nativeResourceForScreen(QByteArrayLiteral("display"), qApp->primaryScreen()); + if (!display) { + // XLib isn't available or has not been initialized, which is a decision we wish to + // support, for example for the GPU process. + static Display* xdisplay = XOpenDisplay(NULL); + return xdisplay; + } + return static_cast<Display*>(display); +} +#endif + +} + +namespace content { +class WebContentsImpl; +class WebContentsViewPort; +class WebContentsViewDelegate; +class RenderViewHostDelegateView; + +WebContentsViewPort* CreateWebContentsView(WebContentsImpl*, + WebContentsViewDelegate*, + RenderViewHostDelegateView**) +{ + return 0; +} + +RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(RenderWidgetHost*) { + // WebContentsViewQt should take care of this directly. + Q_UNREACHABLE(); + return NULL; +} + +// static +void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebKit::WebScreenInfo* results) { + QWindow dummy; + GetScreenInfoFromNativeWindow(&dummy, results); +} + +} diff --git a/src/core/chromium_overrides.h b/src/core/chromium_overrides.h new file mode 100644 index 000000000..cda4d7e66 --- /dev/null +++ b/src/core/chromium_overrides.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CHROMIUM_OVERRIDES_H +#define CHROMIUM_OVERRIDES_H + +#include "third_party/WebKit/public/platform/WebScreenInfo.h" +#include <QtGlobal> + +QT_BEGIN_NAMESPACE +class QWindow; +QT_END_NAMESPACE + +void GetScreenInfoFromNativeWindow(QWindow* window, WebKit::WebScreenInfo* results); + +#endif diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp new file mode 100644 index 000000000..9bc9bfe5e --- /dev/null +++ b/src/core/content_browser_client_qt.cpp @@ -0,0 +1,330 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "content_browser_client_qt.h" + +#include "base/message_loop/message_loop.h" +#include "base/threading/thread_restrictions.h" +#include "content/public/browser/browser_main_parts.h" +#include "content/public/common/main_function_params.h" +#include "content/public/browser/child_process_security_policy.h" +#include "content/public/common/url_constants.h" +#include "grit/net_resources.h" +#include "net/base/net_module.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_share_group.h" + +#include "browser_context_qt.h" +#include "dev_tools_http_handler_delegate_qt.h" +#include "web_contents_view_qt.h" + +#include <QGuiApplication> +#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)) +#include <QtQuick/private/qsgcontext_p.h> +#endif +#include <qpa/qplatformnativeinterface.h> + +namespace { + +ContentBrowserClientQt* gBrowserClient = 0; // Owned by ContentMainDelegateQt. + +// 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 MessagePumpForUIQt : public QObject, + public base::MessagePump +{ +public: + MessagePumpForUIQt() + // Usually this gets passed through Run, but since we have + // our own event loop, attach it explicitly ourselves. + : m_delegate(base::MessageLoopForUI::current()) + { + } + + virtual void Run(Delegate *delegate) Q_DECL_OVERRIDE + { + // FIXME: This could be needed if we want to run Chromium tests. + // We could run a QEventLoop here. + } + + virtual void Quit() Q_DECL_OVERRIDE + { + Q_UNREACHABLE(); + } + + virtual void ScheduleWork() Q_DECL_OVERRIDE + { + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + } + + virtual void ScheduleDelayedWork(const base::TimeTicks &delayed_work_time) Q_DECL_OVERRIDE + { + startTimer(GetTimeIntervalMilliseconds(delayed_work_time)); + } + +protected: + virtual void customEvent(QEvent *ev) Q_DECL_OVERRIDE + { + if (handleScheduledWork()) + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + } + + virtual void timerEvent(QTimerEvent *ev) Q_DECL_OVERRIDE + { + 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 MessagePumpForUIQt; +} + +} // namespace + +static base::StringPiece PlatformResourceProvider(int key) { + if (key == IDR_DIR_HEADER_HTML) { + base::StringPiece html_data = ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_DIR_HEADER_HTML); + return html_data; + } + return base::StringPiece(); +} + +class BrowserMainPartsQt : public content::BrowserMainParts +{ +public: + BrowserMainPartsQt() + : content::BrowserMainParts() + { } + + void PreMainMessageLoopStart() Q_DECL_OVERRIDE + { + net::NetModule::SetResourceProvider(PlatformResourceProvider); + ui::ResourceBundle::InitSharedInstanceWithLocale("en-US", NULL); + base::MessageLoop::InitMessagePumpForUIFactory(::messagePumpFactory); + } + + void PreMainMessageLoopRun() Q_DECL_OVERRIDE + { + m_browserContext.reset(new BrowserContextQt()); + } + + void PostMainMessageLoopRun() + { + m_browserContext.reset(); + } + + int PreCreateThreads() Q_DECL_OVERRIDE + { + base::ThreadRestrictions::SetIOAllowed(true); + return 0; + } + + BrowserContextQt* browser_context() const { + return m_browserContext.get(); + } + +private: + scoped_ptr<BrowserContextQt> m_browserContext; + + DISALLOW_COPY_AND_ASSIGN(BrowserMainPartsQt); +}; + +class QtShareGLContext : public gfx::GLContext { +public: + QtShareGLContext(QOpenGLContext *qtContext) + : gfx::GLContext(0) + , m_handle(0) + { + QString platform = qApp->platformName().toLower(); + QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface(); + if (platform == QStringLiteral("xcb")) { + if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); + else + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("glxcontext"), qtContext); + } else if (platform == QStringLiteral("cocoa")) + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("cglcontextobj"), qtContext); + else if (platform == QStringLiteral("qnx")) + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); + else + // Add missing platforms once they work. + Q_UNREACHABLE(); + } + + virtual void* GetHandle() Q_DECL_OVERRIDE { return m_handle; } + + // We don't care about the rest, this context shouldn't be used except for its handle. + virtual bool Initialize(gfx::GLSurface *, gfx::GpuPreference) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; } + virtual void Destroy() Q_DECL_OVERRIDE { Q_UNREACHABLE(); } + virtual bool MakeCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; } + virtual void ReleaseCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); } + virtual bool IsCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; } + virtual void SetSwapInterval(int) Q_DECL_OVERRIDE { Q_UNREACHABLE(); } + +private: + void *m_handle; +}; + +class ShareGroupQtQuick : public gfx::GLShareGroup { +public: + virtual gfx::GLContext* GetContext() Q_DECL_OVERRIDE { return m_shareContextQtQuick.get(); } + virtual void AboutToAddFirstContext() Q_DECL_OVERRIDE; + +private: + scoped_refptr<QtShareGLContext> m_shareContextQtQuick; +}; + +void ShareGroupQtQuick::AboutToAddFirstContext() +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)) + // This currently has to be setup by ::main in all applications using QQuickWebEngineView with delegated rendering. + QOpenGLContext *shareContext = QSGContext::sharedOpenGLContext(); + Q_ASSERT(shareContext); + m_shareContextQtQuick = make_scoped_refptr(new QtShareGLContext(shareContext)); +#endif +} + +content::WebContentsViewPort* ContentBrowserClientQt::OverrideCreateWebContentsView(content::WebContents* web_contents, + content::RenderViewHostDelegateView** render_view_host_delegate_view) +{ + WebContentsViewQt* rv = new WebContentsViewQt(web_contents); + *render_view_host_delegate_view = rv; + return rv; +} + +ContentBrowserClientQt::ContentBrowserClientQt() + : m_browserMainParts(0) +{ + Q_ASSERT(!gBrowserClient); + gBrowserClient = this; +} + +ContentBrowserClientQt::~ContentBrowserClientQt() +{ + gBrowserClient = 0; +} + +ContentBrowserClientQt *ContentBrowserClientQt::Get() +{ + return gBrowserClient; +} + +content::BrowserMainParts *ContentBrowserClientQt::CreateBrowserMainParts(const content::MainFunctionParams&) +{ + m_browserMainParts = new BrowserMainPartsQt; + return m_browserMainParts; +} + +void ContentBrowserClientQt::RenderProcessHostCreated(content::RenderProcessHost* host) +{ + // FIXME: Add a settings variable to enable/disable the file scheme. + content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(host->GetID(), chrome::kFileScheme); +} + +gfx::GLShareGroup *ContentBrowserClientQt::GetInProcessGpuShareGroup() +{ + if (!m_shareGroupQtQuick) + m_shareGroupQtQuick = new ShareGroupQtQuick; + return m_shareGroupQtQuick.get(); +} + +BrowserContextQt* ContentBrowserClientQt::browser_context() { + Q_ASSERT(m_browserMainParts); + return static_cast<BrowserMainPartsQt*>(m_browserMainParts)->browser_context(); +} + +net::URLRequestContextGetter* ContentBrowserClientQt::CreateRequestContext(content::BrowserContext* content_browser_context, content::ProtocolHandlerMap* protocol_handlers) +{ + if (content_browser_context != browser_context()) + fprintf(stderr, "Warning: off the record browser context not implemented !\n"); + return static_cast<BrowserContextQt*>(browser_context())->CreateRequestContext(protocol_handlers); +} + +void ContentBrowserClientQt::enableInspector(bool enable) +{ + if (enable && !m_devtools) { + m_devtools.reset(new DevToolsHttpHandlerDelegateQt(browser_context())); + } else if (!enable && m_devtools) { + m_devtools.reset(); + } +} diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h new file mode 100644 index 000000000..b97eaa5e1 --- /dev/null +++ b/src/core/content_browser_client_qt.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CONTENT_BROWSER_CLIENT_QT_H +#define CONTENT_BROWSER_CLIENT_QT_H + +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/content_browser_client.h" + +#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE + +namespace net { +class URLRequestContextGetter; +} + +namespace content { +class BrowserContext; +class BrowserMainParts; +class RenderProcessHost; +class RenderViewHostDelegateView; +class WebContentsViewPort; +class WebContents; +struct MainFunctionParams; +} + +namespace gfx { +class GLShareGroup; +} + +class BrowserContextQt; +class BrowserMainPartsQt; +class DevToolsHttpHandlerDelegateQt; +class ShareGroupQtQuick; + +class ContentBrowserClientQt : public content::ContentBrowserClient { + +public: + ContentBrowserClientQt(); + ~ContentBrowserClientQt(); + static ContentBrowserClientQt* Get(); + virtual content::WebContentsViewPort* OverrideCreateWebContentsView(content::WebContents* , content::RenderViewHostDelegateView**) Q_DECL_OVERRIDE; + virtual content::BrowserMainParts* CreateBrowserMainParts(const content::MainFunctionParams&) Q_DECL_OVERRIDE; + virtual void RenderProcessHostCreated(content::RenderProcessHost* host) Q_DECL_OVERRIDE; + virtual gfx::GLShareGroup* GetInProcessGpuShareGroup() Q_DECL_OVERRIDE; + + BrowserContextQt* browser_context(); + + net::URLRequestContextGetter *CreateRequestContext(content::BrowserContext *content_browser_context, content::ProtocolHandlerMap *protocol_handlers); + + void enableInspector(bool); + +private: + BrowserMainPartsQt* m_browserMainParts; + scoped_ptr<DevToolsHttpHandlerDelegateQt> m_devtools; + scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick; +}; + +#endif // CONTENT_BROWSER_CLIENT_QT_H diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp new file mode 100644 index 000000000..46a3e9870 --- /dev/null +++ b/src/core/content_client_qt.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "content_client_qt.h" + +#include "base/strings/string_piece.h" +#include "ui/base/layout.h" +#include "ui/base/resource/resource_bundle.h" + +base::StringPiece ContentClientQt::GetDataResource(int resource_id, ui::ScaleFactor scale_factor) const { + return ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(resource_id, scale_factor); +} diff --git a/src/core/content_client_qt.h b/src/core/content_client_qt.h new file mode 100644 index 000000000..059e9423b --- /dev/null +++ b/src/core/content_client_qt.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CONTENT_CLIENT_QT_H +#define CONTENT_CLIENT_QT_H + +#include "base/strings/string_piece.h" +#include "content/public/common/content_client.h" +#include "ui/base/layout.h" +#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE + +class ContentClientQt : public content::ContentClient { +public: + virtual base::StringPiece GetDataResource(int, ui::ScaleFactor) const Q_DECL_OVERRIDE; +}; + +#endif // CONTENT_CLIENT_QT_H diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro new file mode 100644 index 000000000..76924ecd4 --- /dev/null +++ b/src/core/core_gyp_generator.pro @@ -0,0 +1,98 @@ +# This is a dummy .pro file used to extract some aspects of the used configuration and feed them to gyp +# We want the gyp generation step to happen after all the other config steps. For that we need to prepend +# our gyp_generator.prf feature to the CONFIG variable since it is processed backwards +CONFIG = gyp_generator $$CONFIG +GYPDEPENDENCIES += <(chromium_src_dir)/content/browser/devtools/devtools_resources.gyp:devtools_resources +GYPINCLUDES += ../qtwebengine.gypi + +TEMPLATE = lib + +TARGET = Qt5WebEngineCore + +# gyp sets the default install name to /usr/local/lib and we need the module libraries to +# know its install_name so that they can let the dynamic linker load the core library. +# FIXME: Remove this and put it in qtwebengine.gypi once we can use a relative path to @loader_path. +macx: GYP_DYLIB_INSTALL_NAME_BASE = $$getOutDir()/$$getConfigDir() + +QT += qml quick +QT_PRIVATE += qml-private quick-private gui-private core-private +qtHaveModule(v8): QT_PRIVATE += v8-private + +COPY_FILES = <(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak +COPY_DESTINATIONS = ../resources/ + +# Defining keywords such as 'signal' clashes with the chromium code base. +DEFINES += QT_NO_KEYWORDS \ + Q_FORWARD_DECLARE_OBJC_CLASS=QT_FORWARD_DECLARE_CLASS + +# We need a way to tap into gyp´s Debug vs. Release configuration +PER_CONFIG_DEFINES = QTWEBENGINEPROCESS_PATH=\\\"$$getOutDir()/%config/$$QTWEBENGINEPROCESS_NAME\\\" + +# Keep Skia happy +CONFIG(release, debug|release): DEFINES += NDEBUG + +RESOURCES += lib_resources.qrc devtools.qrc +# We need this to find the include files generated for the .pak resource files. +INCLUDEPATH += $$absolute_path(../resources, $$PWD) + +# something fishy with qmake in 5.2 ? +INCLUDEPATH += $$[QT_INSTALL_HEADERS] + +SOURCES = \ + backing_store_qt.cpp \ + chromium_overrides.cpp \ + content_client_qt.cpp \ + content_browser_client_qt.cpp \ + delegated_frame_node.cpp \ + dev_tools_http_handler_delegate_qt.cpp \ + download_manager_delegate_qt.cpp \ + chromium_gpu_helper.cpp \ + javascript_dialog_manager_qt.cpp \ + process_main.cpp \ + render_widget_host_view_qt.cpp \ + resource_bundle_qt.cpp \ + resource_context_qt.cpp \ + url_request_context_getter_qt.cpp \ + web_contents_adapter.cpp \ + web_contents_delegate_qt.cpp \ + web_contents_view_qt.cpp \ + web_engine_context.cpp \ + web_event_factory.cpp \ + yuv_video_node.cpp + +HEADERS = \ + backing_store_qt.h \ + browser_context_qt.h \ + chromium_overrides.h \ + content_client_qt.h \ + content_browser_client_qt.h \ + delegated_frame_node.h \ + dev_tools_http_handler_delegate_qt.h \ + download_manager_delegate_qt.h \ + chromium_gpu_helper.h \ + javascript_dialog_manager_qt.h \ + process_main.h \ + render_widget_host_view_qt.h \ + render_widget_host_view_qt_delegate.h \ + resource_context_qt.h \ + url_request_context_getter_qt.h \ + web_contents_adapter.h \ + web_contents_adapter_client.h \ + web_contents_delegate_qt.h \ + web_contents_view_qt.h \ + web_engine_context.h \ + web_event_factory.h \ + yuv_video_node.h + +# It's difficult to convince the gyp/ninja combination to install the +# output, so use qmake for that purpose. We need to use target.extra +# rather than target.files since qmake is not convinced this file will +# exist after the build completes. +# FIXME: Remove this once we get rid of libQt5WebEngineCore.so and fold +# the object files into libQt5WebEngine.so instead. +unix { + OUTPUT_DIR = $$getOutDir()/$$getConfigDir() + target.extra = $(INSTALL_FILE) $$OUTPUT_DIR/lib/lib$${TARGET}.so $$[QT_INSTALL_LIBS] + target.path = $$[QT_INSTALL_LIBS] + INSTALLS += target +} diff --git a/src/core/core_resources.qrc b/src/core/core_resources.qrc new file mode 100644 index 000000000..af8448d2b --- /dev/null +++ b/src/core/core_resources.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="data"> + <file alias="resources.pak">../resources/net_resources.pak</file> +</qresource> +</RCC> diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp new file mode 100644 index 000000000..c770f388d --- /dev/null +++ b/src/core/delegated_frame_node.cpp @@ -0,0 +1,519 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// On Mac we need to reset this define in order to prevent definition +// of "check" macros etc. The "check" macro collides with a member function name in QtQuick. +// See AssertMacros.h in the Mac SDK. +#include <QtGlobal> // We need this for the Q_OS_MAC define. +#if defined(Q_OS_MAC) +#undef __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES +#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +#include "delegated_frame_node.h" + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)) +#include "chromium_gpu_helper.h" +#include "type_conversion.h" +#include "yuv_video_node.h" + +#include "base/message_loop/message_loop.h" +#include "base/bind.h" +#include "cc/output/delegated_frame_data.h" +#include "cc/quads/draw_quad.h" +#include "cc/quads/render_pass_draw_quad.h" +#include "cc/quads/solid_color_draw_quad.h" +#include "cc/quads/texture_draw_quad.h" +#include "cc/quads/tile_draw_quad.h" +#include "cc/quads/yuv_video_draw_quad.h" +#include <QOpenGLFramebufferObject> +#include <QSGSimpleTextureNode> +#include <QSGTexture> +#include <QtQuick/private/qquickclipnode_p.h> +#include <QtQuick/private/qquickwindow_p.h> +#include <QtQuick/private/qsgadaptationlayer_p.h> +#include <QtQuick/private/qsgcontext_p.h> +#include <QtQuick/private/qsgrenderer_p.h> +#include <QtQuick/private/qsgtexture_p.h> + +class RenderPassTexture : public QSGTexture +{ +public: + RenderPassTexture(const cc::RenderPass::Id &id, QSGRenderContext *context); + + const cc::RenderPass::Id &id() const { return m_id; } + void bind(); + + int textureId() const { return m_fbo ? m_fbo->texture() : 0; } + QSize textureSize() const { return m_rect.size(); } + bool hasAlphaChannel() const { return m_format != GL_RGB; } + bool hasMipmaps() const { return false; } + + void setRect(const QRect &rect) { m_rect = rect; } + void setFormat(GLenum format) { m_format = format; } + void setDevicePixelRatio(qreal ratio) { m_device_pixel_ratio = ratio; } + QSGNode *rootNode() { return m_rootNode.data(); } + + void grab(); + +private: + cc::RenderPass::Id m_id; + QRect m_rect; + qreal m_device_pixel_ratio; + GLenum m_format; + + QScopedPointer<QSGRootNode> m_rootNode; + QScopedPointer<QSGRenderer> m_renderer; + QScopedPointer<QOpenGLFramebufferObject> m_fbo; + + QSGRenderContext *m_context; +}; + +class MailboxTexture : public QSGTexture { +public: + MailboxTexture(const cc::TransferableResource &resource); + virtual int textureId() const Q_DECL_OVERRIDE { return m_textureId; } + void setTextureSize(const QSize& size) { m_textureSize = size; } + virtual QSize textureSize() const Q_DECL_OVERRIDE { return m_textureSize; } + virtual bool hasAlphaChannel() const Q_DECL_OVERRIDE { return m_hasAlpha; } + void setHasAlphaChannel(bool hasAlpha) { m_hasAlpha = hasAlpha; } + virtual bool hasMipmaps() const Q_DECL_OVERRIDE { return false; } + virtual void bind() Q_DECL_OVERRIDE; + + bool needsToFetch() const { return !m_textureId; } + cc::TransferableResource &resource() { return m_resource; } + void fetchTexture(gpu::gles2::MailboxManager *mailboxManager); + +private: + cc::TransferableResource m_resource; + int m_textureId; + QSize m_textureSize; + bool m_hasAlpha; +}; + +static inline QSharedPointer<RenderPassTexture> findRenderPassTexture(const cc::RenderPass::Id &id, const QList<QSharedPointer<RenderPassTexture> > &list) +{ + Q_FOREACH (const QSharedPointer<RenderPassTexture> &texture, list) + if (texture->id() == id) + return texture; + return QSharedPointer<RenderPassTexture>(); +} + +static QSGNode *buildRenderPassChain(QSGNode *chainParent, const cc::RenderPass *renderPass) +{ + // Chromium already ordered the quads from back to front for us, however the + // Qt scene graph layers individual geometries in their own z-range and uses + // the depth buffer to visually stack nodes according to their item tree order. + // This finds the z-span of all layers so that we can z-compress them to fit + // them between 0.0 and 1.0 on the z axis. + double minZ = 0; + double maxZ = 1; + double src2[8]; + double dst4[16]; + // topleft.x, topleft.y, topRight.y and bottomLeft.x + src2[0] = src2[1] = src2[3] = src2[4] = 0; + + // Go through each layer in this pass and find out their transformed rect. + cc::SharedQuadStateList::const_iterator it = renderPass->shared_quad_state_list.begin(); + cc::SharedQuadStateList::const_iterator sharedStateEnd = renderPass->shared_quad_state_list.end(); + for (; it != sharedStateEnd; ++it) { + gfx::Size &layerSize = (*it)->content_bounds; + // topRight.x + src2[2] = layerSize.width(); + // bottomLeft.y + src2[5] = layerSize.height(); + // bottomRight + src2[6] = layerSize.width(); + src2[7] = layerSize.height(); + (*it)->content_to_target_transform.matrix().map2(src2, 4, dst4); + // Check the mapped corner's z value and track the boundaries. + minZ = std::min(std::min(std::min(std::min(minZ, dst4[2]), dst4[6]), dst4[10]), dst4[14]); + maxZ = std::max(std::max(std::max(std::max(maxZ, dst4[2]), dst4[6]), dst4[10]), dst4[14]); + } + + QSGTransformNode *zCompressNode = new QSGTransformNode; + QMatrix4x4 zCompressMatrix; + zCompressMatrix.scale(1, 1, 1 / (maxZ - minZ)); + zCompressMatrix.translate(0, 0, -minZ); + zCompressNode->setMatrix(zCompressMatrix); + chainParent->appendChildNode(zCompressNode); + return zCompressNode; +} + +static QSGNode *buildLayerChain(QSGNode *chainParent, const cc::SharedQuadState *layerState) +{ + QSGNode *layerChain = chainParent; + if (layerState->is_clipped) { + QQuickDefaultClipNode *clipNode = new QQuickDefaultClipNode(toQt(layerState->clip_rect)); + clipNode->update(); + layerChain->appendChildNode(clipNode); + layerChain = clipNode; + } + if (!layerState->content_to_target_transform.IsIdentity()) { + QSGTransformNode *transformNode = new QSGTransformNode; + transformNode->setMatrix(toQt(layerState->content_to_target_transform.matrix())); + layerChain->appendChildNode(transformNode); + layerChain = transformNode; + } + if (layerState->opacity < 1.0) { + QSGOpacityNode *opacityNode = new QSGOpacityNode; + opacityNode->setOpacity(layerState->opacity); + layerChain->appendChildNode(opacityNode); + layerChain = opacityNode; + } + return layerChain; +} + +RenderPassTexture::RenderPassTexture(const cc::RenderPass::Id &id, QSGRenderContext *context) + : QSGTexture() + , m_id(id) + , m_device_pixel_ratio(1) + , m_format(GL_RGBA) + , m_rootNode(new QSGRootNode) + , m_context(context) +{ +} + +void RenderPassTexture::bind() +{ + glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0); + updateBindOptions(); +} + +void RenderPassTexture::grab() +{ + if (!m_rootNode->firstChild()) { + m_renderer.reset(); + m_fbo.reset(); + return; + } + if (!m_renderer) { + m_renderer.reset(m_context->createRenderer()); + m_renderer->setRootNode(m_rootNode.data()); + } + m_renderer->setDevicePixelRatio(m_device_pixel_ratio); + + if (!m_fbo || m_fbo->size() != m_rect.size() || m_fbo->format().internalTextureFormat() != m_format) + { + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + format.setInternalTextureFormat(m_format); + + m_fbo.reset(new QOpenGLFramebufferObject(m_rect.size(), format)); + glBindTexture(GL_TEXTURE_2D, m_fbo->texture()); + updateBindOptions(true); + } + + m_rootNode->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update. + m_renderer->nodeChanged(m_rootNode.data(), QSGNode::DirtyForceUpdate); // Force render list update. + + m_renderer->setDeviceRect(m_rect.size()); + m_renderer->setViewportRect(m_rect.size()); + QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height()); + m_renderer->setProjectionMatrixToRect(mirrored); + m_renderer->setClearColor(Qt::transparent); + + m_context->renderNextFrame(m_renderer.data(), m_fbo->handle()); +} + +MailboxTexture::MailboxTexture(const cc::TransferableResource &resource) + : m_resource(resource) + , m_textureId(0) + , m_textureSize(toQt(resource.size)) + , m_hasAlpha(false) +{ +} + +void MailboxTexture::bind() +{ + glBindTexture(GL_TEXTURE_2D, m_textureId); +} + +void MailboxTexture::fetchTexture(gpu::gles2::MailboxManager *mailboxManager) +{ + gpu::gles2::Texture *tex = ConsumeTexture(mailboxManager, GL_TEXTURE_2D, *reinterpret_cast<const gpu::gles2::MailboxName*>(m_resource.mailbox.name)); + + // The texture might already have been deleted (e.g. when navigating away from a page). + if (tex) + m_textureId = service_id(tex); +} + +DelegatedFrameNode::DelegatedFrameNode(QQuickWindow *window) + : m_window(window) + , m_numPendingSyncPoints(0) +{ + setFlag(UsePreprocess); +} + +DelegatedFrameNode::~DelegatedFrameNode() +{ +} + +void DelegatedFrameNode::preprocess() +{ + // With the threaded render loop the GUI thread has been unlocked at this point. + // We can now wait for the Chromium GPU thread to produce textures that will be + // rendered on our quads and fetch the IDs from the mailboxes we were given. + QList<MailboxTexture *> mailboxesToFetch; + Q_FOREACH (const QSharedPointer<MailboxTexture> &mailboxTexture, m_mailboxTextures.values()) + if (mailboxTexture->needsToFetch()) + mailboxesToFetch.append(mailboxTexture.data()); + + if (!mailboxesToFetch.isEmpty()) { + QMutexLocker lock(&m_mutex); + base::MessageLoop *gpuMessageLoop = gpu_message_loop(); + content::SyncPointManager *syncPointManager = sync_point_manager(); + + Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) { + m_numPendingSyncPoints++; + AddSyncPointCallbackOnGpuThread(gpuMessageLoop, syncPointManager, mailboxTexture->resource().sync_point, base::Bind(&DelegatedFrameNode::syncPointRetired, this, &mailboxesToFetch)); + } + + m_mailboxesFetchedWaitCond.wait(&m_mutex); + } + + // Then render any intermediate RenderPass in order. + Q_FOREACH (const QSharedPointer<RenderPassTexture> &renderPass, m_renderPassTextures) + renderPass->grab(); +} + +void DelegatedFrameNode::commit(cc::DelegatedFrameData *frameData, cc::TransferableResourceArray *resourcesToRelease) +{ + // Keep the old texture lists around to find the ones we can re-use. + QList<QSharedPointer<RenderPassTexture> > oldRenderPassTextures; + m_renderPassTextures.swap(oldRenderPassTextures); + QMap<int, QSharedPointer<MailboxTexture> > mailboxTextureCandidates; + m_mailboxTextures.swap(mailboxTextureCandidates); + + // A frame's resource_list only contains the new resources to be added to the scene. Quads can + // still reference resources that were added in previous frames. Add them to the list of + // candidates to be picked up by quads, it's then our responsibility to return unused resources + // to the producing child compositor. + for (unsigned i = 0; i < frameData->resource_list.size(); ++i) { + const cc::TransferableResource &res = frameData->resource_list.at(i); + mailboxTextureCandidates[res.id] = QSharedPointer<MailboxTexture>(new MailboxTexture(res)); + } + + // The RenderPasses list is actually a tree where a parent RenderPass is connected + // to its dependencies through a RenderPass::Id reference in one or more RenderPassQuads. + // The list is already ordered with intermediate RenderPasses placed before their + // parent, with the last one in the list being the root RenderPass, the one + // that we displayed to the user. + // All RenderPasses except the last one are rendered to an FBO. + cc::RenderPass *rootRenderPass = frameData->render_pass_list.back(); + + for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) { + cc::RenderPass *pass = frameData->render_pass_list.at(i); + + QSGNode *renderPassParent = 0; + if (pass != rootRenderPass) { + QSharedPointer<RenderPassTexture> rpTexture = findRenderPassTexture(pass->id, oldRenderPassTextures); + if (!rpTexture) { + QSGRenderContext *sgrc = QQuickWindowPrivate::get(m_window)->context; + rpTexture = QSharedPointer<RenderPassTexture>(new RenderPassTexture(pass->id, sgrc)); + } + m_renderPassTextures.append(rpTexture); + rpTexture->setDevicePixelRatio(m_window->devicePixelRatio()); + rpTexture->setRect(toQt(pass->output_rect)); + rpTexture->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB); + renderPassParent = rpTexture->rootNode(); + } else + renderPassParent = this; + + // There is currently no way to know which and how quads changed since the last frame. + // We have to reconstruct the node chain with their geometries on every update. + while (QSGNode *oldChain = renderPassParent->firstChild()) + delete oldChain; + + QSGNode *renderPassChain = buildRenderPassChain(renderPassParent, pass); + const cc::SharedQuadState *currentLayerState = 0; + QSGNode *currentLayerChain = 0; + + cc::QuadList::ConstBackToFrontIterator it = pass->quad_list.BackToFrontBegin(); + cc::QuadList::ConstBackToFrontIterator end = pass->quad_list.BackToFrontEnd(); + for (; it != end; ++it) { + cc::DrawQuad *quad = *it; + + if (currentLayerState != quad->shared_quad_state) { + currentLayerState = quad->shared_quad_state; + currentLayerChain = buildLayerChain(renderPassChain, currentLayerState); + } + + switch (quad->material) { + case cc::DrawQuad::RENDER_PASS: { + const cc::RenderPassDrawQuad *renderPassQuad = cc::RenderPassDrawQuad::MaterialCast(quad); + QSGTexture *texture = findRenderPassTexture(renderPassQuad->render_pass_id, m_renderPassTextures).data(); + // cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes. + if (!texture) + continue; + + QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode; + textureNode->setRect(toQt(quad->rect)); + textureNode->setTexture(texture); + currentLayerChain->appendChildNode(textureNode); + break; + } case cc::DrawQuad::TEXTURE_CONTENT: { + const cc::TextureDrawQuad *tquad = cc::TextureDrawQuad::MaterialCast(quad); + QSharedPointer<MailboxTexture> &texture = m_mailboxTextures[tquad->resource_id] = mailboxTextureCandidates.take(tquad->resource_id); + Q_ASSERT(texture); + + // FIXME: TransferableResource::size isn't always set properly for TextureDrawQuads, use the size of its DrawQuad::rect instead. + texture->setTextureSize(toQt(quad->rect.size())); + + // TransferableResource::format seems to always be GL_BGRA even though it might not + // contain any pixel with alpha < 1.0. The information about if they need blending + // for the contents itself is actually stored in quads. + // Tell the scene graph to enable blending for a texture only when at least one quad asks for it. + // Do not rely on DrawQuad::ShouldDrawWithBlending() since the shared_quad_state->opacity + // case will be handled by QtQuick by fetching this information from QSGOpacityNodes. + if (!quad->visible_rect.IsEmpty() && !quad->opaque_rect.Contains(quad->visible_rect)) + texture->setHasAlphaChannel(true); + + QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode; + textureNode->setTextureCoordinatesTransform(tquad->flipped ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform); + textureNode->setRect(toQt(quad->rect)); + textureNode->setFiltering(texture->resource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); + textureNode->setTexture(texture.data()); + currentLayerChain->appendChildNode(textureNode); + break; + } case cc::DrawQuad::SOLID_COLOR: { + const cc::SolidColorDrawQuad *scquad = cc::SolidColorDrawQuad::MaterialCast(quad); + QSGRenderContext *sgrc = QQuickWindowPrivate::get(m_window)->context; + QSGRectangleNode *rectangleNode = sgrc->sceneGraphContext()->createRectangleNode(); + + // Qt only supports MSAA and this flag shouldn't be needed. + // If we ever want to use QSGRectangleNode::setAntialiasing for this we should + // try to see if we can do something similar for tile quads first. + Q_UNUSED(scquad->force_anti_aliasing_off); + + rectangleNode->setRect(toQt(quad->rect)); + rectangleNode->setColor(toQt(scquad->color)); + rectangleNode->update(); + currentLayerChain->appendChildNode(rectangleNode); + break; + } case cc::DrawQuad::TILED_CONTENT: { + const cc::TileDrawQuad *tquad = cc::TileDrawQuad::MaterialCast(quad); + QSharedPointer<MailboxTexture> &texture = m_mailboxTextures[tquad->resource_id] = mailboxTextureCandidates.take(tquad->resource_id); + Q_ASSERT(texture); + + if (!quad->visible_rect.IsEmpty() && !quad->opaque_rect.Contains(quad->visible_rect)) + texture->setHasAlphaChannel(true); + + QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode; + textureNode->setRect(toQt(quad->rect)); + textureNode->setFiltering(texture->resource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); + textureNode->setTexture(texture.data()); + + // FIXME: Find out if we can implement a QSGSimpleTextureNode::setSourceRect instead of this hack. + // This has to be done at the end since many QSGSimpleTextureNode methods would overwrite this. + QSGGeometry::updateTexturedRectGeometry(textureNode->geometry(), textureNode->rect(), textureNode->texture()->convertToNormalizedSourceRect(toQt(tquad->tex_coord_rect))); + currentLayerChain->appendChildNode(textureNode); + break; + } case cc::DrawQuad::YUV_VIDEO_CONTENT: { + const cc::YUVVideoDrawQuad *vquad = cc::YUVVideoDrawQuad::MaterialCast(quad); + QSharedPointer<MailboxTexture> &yTexture = m_mailboxTextures[vquad->y_plane_resource_id] = mailboxTextureCandidates.take(vquad->y_plane_resource_id); + QSharedPointer<MailboxTexture> &uTexture = m_mailboxTextures[vquad->u_plane_resource_id] = mailboxTextureCandidates.take(vquad->u_plane_resource_id); + QSharedPointer<MailboxTexture> &vTexture = m_mailboxTextures[vquad->v_plane_resource_id] = mailboxTextureCandidates.take(vquad->v_plane_resource_id); + Q_ASSERT(yTexture && uTexture && vTexture); + + // Do not use a reference for this one, it might be null. + QSharedPointer<MailboxTexture> aTexture; + // This currently requires --enable-vp8-alpha-playback and needs a video with alpha data to be triggered. + if (vquad->a_plane_resource_id) + aTexture = m_mailboxTextures[vquad->a_plane_resource_id] = mailboxTextureCandidates.take(vquad->a_plane_resource_id); + + YUVVideoNode *videoNode = new YUVVideoNode(yTexture.data(), uTexture.data(), vTexture.data(), aTexture.data(), toQt(vquad->tex_scale)); + videoNode->setRect(toQt(quad->rect)); + currentLayerChain->appendChildNode(videoNode); + break; + } default: + qWarning("Unimplemented quad material: %d", quad->material); + } + } + } + + // Send resources of remaining candidates back to the child compositors so that they can be freed or reused. + Q_FOREACH (const QSharedPointer<MailboxTexture> &mailboxTexture, mailboxTextureCandidates.values()) { + // The ResourceProvider ensures that the resource isn't used by the parent compositor's GL + // context in the GPU process by inserting a sync point to be waited for by the child + // compositor's GL context. We don't need this since we are triggering the delegated frame + // ack directly from our rendering thread. At this point (in updatePaintNode) we know that + // a frame that was compositing any of those resources has already been swapped. + // Save a bit of overhead by resetting the sync point that has initially been put there + // for us (mainly to clean the output of --enable-gpu-service-logging). + mailboxTexture->resource().sync_point = 0; + + resourcesToRelease->push_back(mailboxTexture->resource()); + } +} + +void DelegatedFrameNode::fetchTexturesAndUnlockQt(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch) +{ + // Fetch texture IDs from the mailboxes while we're on the GPU thread, where the MailboxManager lives. + gpu::gles2::MailboxManager *mailboxManager = mailbox_manager(); + Q_FOREACH (MailboxTexture *mailboxTexture, *mailboxesToFetch) + mailboxTexture->fetchTexture(mailboxManager); + + // glFlush before yielding to the SG thread, whose context might already start using + // some shared resources provided by the unflushed context here, on the Chromium GPU thread. + glFlush(); + + // Chromium provided everything we were waiting for, let Qt start rendering. + QMutexLocker lock(&frameNode->m_mutex); + frameNode->m_mailboxesFetchedWaitCond.wakeOne(); +} + +void DelegatedFrameNode::syncPointRetired(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch) +{ + // The way that sync points are normally used by the GpuCommandBufferStub is that it asks + // the GpuScheduler to resume the work of the associated GL command stream / context once + // the sync point has been retired by the dependency's context. In other words, a produced + // texture means that the mailbox can be consumed, but the texture itself isn't expected + // to be ready until to control is given back to the GpuScheduler through the event loop. + // Do the same for our implementation by posting a message to the event loop once the last + // of our syncpoints has been retired (the syncpoint callback is called synchronously) and + // only at this point we wake the Qt rendering thread. + QMutexLocker lock(&frameNode->m_mutex); + if (!--frameNode->m_numPendingSyncPoints) + base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::fetchTexturesAndUnlockQt, frameNode, mailboxesToFetch)); +} + +#endif // QT_VERSION diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h new file mode 100644 index 000000000..b73370874 --- /dev/null +++ b/src/core/delegated_frame_node.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DELEGATED_FRAME_NODE_H +#define DELEGATED_FRAME_NODE_H + +#include "cc/resources/transferable_resource.h" +#include <QMutex> +#include <QSGNode> +#include <QSharedPointer> +#include <QWaitCondition> + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)) + +QT_BEGIN_NAMESPACE +class QQuickWindow; +QT_END_NAMESPACE + +namespace cc { +class DelegatedFrameData; +} + +class MailboxTexture; +class RenderPassTexture; + +class DelegatedFrameNode : public QSGNode { +public: + DelegatedFrameNode(QQuickWindow *window); + ~DelegatedFrameNode(); + void preprocess(); + void commit(cc::DelegatedFrameData *frameData, cc::TransferableResourceArray *resourcesToRelease); + +private: + QQuickWindow *m_window; + QList<QSharedPointer<RenderPassTexture> > m_renderPassTextures; + QMap<int, QSharedPointer<MailboxTexture> > m_mailboxTextures; + int m_numPendingSyncPoints; + QWaitCondition m_mailboxesFetchedWaitCond; + QMutex m_mutex; + + // Making those callbacks static bypasses base::Bind's ref-counting requirement + // of the this pointer when the callback is a method. + static void fetchTexturesAndUnlockQt(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch); + static void syncPointRetired(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch); +}; + +#endif // QT_VERSION + +#endif // DELEGATED_FRAME_NODE_H diff --git a/src/core/dev_tools_http_handler_delegate_qt.cpp b/src/core/dev_tools_http_handler_delegate_qt.cpp new file mode 100644 index 000000000..0603f5dcc --- /dev/null +++ b/src/core/dev_tools_http_handler_delegate_qt.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dev_tools_http_handler_delegate_qt.h" + +#include <QByteArray> +#include <QFile> + +#include "base/files/file_path.h" +#include "content/public/browser/devtools_http_handler.h" +#include "net/socket/stream_listen_socket.h" +#include "net/socket/tcp_listen_socket.h" + +DevToolsHttpHandlerDelegateQt::DevToolsHttpHandlerDelegateQt(content::BrowserContext* browser_context) + : m_browserContext(browser_context) +{ + m_devtoolsHttpHandler = content::DevToolsHttpHandler::Start(new net::TCPListenSocketFactory("0.0.0.0", 1337), std::string(), this); +} + +DevToolsHttpHandlerDelegateQt::~DevToolsHttpHandlerDelegateQt() +{ + m_devtoolsHttpHandler->Stop(); +} + +std::string DevToolsHttpHandlerDelegateQt::GetDiscoveryPageHTML() +{ + static std::string html; + if (html.empty()) { + QFile html_file(":/data/discovery_page.html"); + html_file.open(QIODevice::ReadOnly); + QByteArray contents = html_file.readAll(); + html = contents.data(); + } + return html; +} + +bool DevToolsHttpHandlerDelegateQt::BundlesFrontendResources() +{ + return true; +} + +base::FilePath DevToolsHttpHandlerDelegateQt::GetDebugFrontendDir() +{ + return base::FilePath(); +} + +std::string DevToolsHttpHandlerDelegateQt::GetPageThumbnailData(const GURL& url) +{ + return std::string(); +} + +content::RenderViewHost* DevToolsHttpHandlerDelegateQt::CreateNewTarget() +{ + return NULL; +} + +content::DevToolsHttpHandlerDelegate::TargetType DevToolsHttpHandlerDelegateQt::GetTargetType(content::RenderViewHost*) +{ + return kTargetTypeTab; +} + +std::string DevToolsHttpHandlerDelegateQt::GetViewDescription(content::RenderViewHost*) +{ + return std::string(); +} + +scoped_refptr<net::StreamListenSocket> DevToolsHttpHandlerDelegateQt::CreateSocketForTethering(net::StreamListenSocket::Delegate* delegate, std::string* name) +{ + return NULL; +} diff --git a/src/core/dev_tools_http_handler_delegate_qt.h b/src/core/dev_tools_http_handler_delegate_qt.h new file mode 100644 index 000000000..e866f0765 --- /dev/null +++ b/src/core/dev_tools_http_handler_delegate_qt.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DEV_TOOLS_HTTP_HANDLER_DELEGATE_QT_H +#define DEV_TOOLS_HTTP_HANDLER_DELEGATE_QT_H + +#include "content/public/browser/devtools_http_handler_delegate.h" + +#include <QtCore/qcompilerdetection.h> // needed for Q_DECL_OVERRIDE + +namespace net { +class StreamListenSocket; +} + +namespace content { +class BrowserContext; +class DevToolsHttpHandler; +class RenderViewHost; +} + +class DevToolsHttpHandlerDelegateQt : public content::DevToolsHttpHandlerDelegate { +public: + + explicit DevToolsHttpHandlerDelegateQt(content::BrowserContext* browser_context); + virtual ~DevToolsHttpHandlerDelegateQt(); + + // content::DevToolsHttpHandlerDelegate Overrides + virtual std::string GetDiscoveryPageHTML() Q_DECL_OVERRIDE; + virtual bool BundlesFrontendResources() Q_DECL_OVERRIDE; + virtual base::FilePath GetDebugFrontendDir() Q_DECL_OVERRIDE; + virtual std::string GetPageThumbnailData(const GURL& url) Q_DECL_OVERRIDE; + virtual content::RenderViewHost* CreateNewTarget() Q_DECL_OVERRIDE; + virtual TargetType GetTargetType(content::RenderViewHost*) Q_DECL_OVERRIDE; + virtual std::string GetViewDescription(content::RenderViewHost*) Q_DECL_OVERRIDE; + virtual scoped_refptr<net::StreamListenSocket> CreateSocketForTethering(net::StreamListenSocket::Delegate* delegate, std::string* name) Q_DECL_OVERRIDE; + +private: + content::BrowserContext* m_browserContext; + content::DevToolsHttpHandler* m_devtoolsHttpHandler; +}; + +#endif // DEV_TOOLS_HTTP_HANDLER_DELEGATE_QT_H diff --git a/src/core/devtools.qrc b/src/core/devtools.qrc new file mode 100644 index 000000000..225f88f65 --- /dev/null +++ b/src/core/devtools.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="data"> + <file alias="devtools.pak">../resources/devtools_resources.pak</file> + <file alias="discovery_page.html">../resources/devtools_discovery_page.html</file> +</qresource> +</RCC> diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp new file mode 100644 index 000000000..27b61b1c9 --- /dev/null +++ b/src/core/download_manager_delegate_qt.cpp @@ -0,0 +1,250 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "download_manager_delegate_qt.h" + +#include "content/public/browser/download_item.h" +#include "content/public/browser/save_page_type.h" +#include "content/public/browser/web_contents.h" + +#include <QDir> +#include <QFile> +#include <QFileInfo> +#include <QMap> +#include <QStandardPaths> + +#include "type_conversion.h" +#include "qtwebenginecoreglobal.h" + +// Helper class to track currently ongoing downloads to prevent file name +// clashes / overwriting of files. +class DownloadTargetHelper : public content::DownloadItem::Observer { +public: + DownloadTargetHelper() + : m_defaultDownloadDirectory(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)) + { + + } + virtual ~DownloadTargetHelper() {} + + bool determineDownloadTarget(content::DownloadItem *item, const content::DownloadTargetCallback &callback); + + virtual void OnDownloadUpdated(content::DownloadItem *download) Q_DECL_OVERRIDE; + virtual void OnDownloadDestroyed(content::DownloadItem *download) Q_DECL_OVERRIDE; +private: + bool isPathAvailable(const QString& path); + + QDir m_defaultDownloadDirectory; + QMap<content::DownloadItem*, QString> m_ongoingDownloads; +}; + +bool DownloadTargetHelper::isPathAvailable(const QString& path) +{ + return !m_ongoingDownloads.values().contains(path) && !QFile::exists(path); +} + +bool DownloadTargetHelper::determineDownloadTarget(content::DownloadItem *item, const content::DownloadTargetCallback &callback) +{ + std::string suggestedFilename = item->GetSuggestedFilename(); + + if (suggestedFilename.empty()) + suggestedFilename = item->GetTargetFilePath().AsUTF8Unsafe(); + + if (suggestedFilename.empty()) + suggestedFilename = item->GetURL().ExtractFileName(); + + if (suggestedFilename.empty()) + suggestedFilename = "qwe_download"; + + if (!m_defaultDownloadDirectory.exists() && !m_defaultDownloadDirectory.mkpath(m_defaultDownloadDirectory.absolutePath())) + return false; + + QString suggestedFilePath = m_defaultDownloadDirectory.absoluteFilePath(QString::fromStdString(suggestedFilename)); + if (!isPathAvailable(suggestedFilePath)) { + int i = 1; + for (; i < 99; i++) { + QFileInfo tmpFile(suggestedFilePath); + QString tmpFilePath = QString("%1%2%3(%4).%5").arg(tmpFile.absolutePath()).arg(QDir::separator()).arg(tmpFile.baseName()).arg(i).arg(tmpFile.completeSuffix()); + if (isPathAvailable(tmpFilePath)) { + suggestedFilePath = tmpFilePath; + break; + } + } + if (i >= 99) { + callback.Run(base::FilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, base::FilePath()); + return false; + } + } + + m_ongoingDownloads.insert(item, suggestedFilePath); + item->AddObserver(this); + + base::FilePath filePathForCallback(toFilePathString(suggestedFilePath)); + callback.Run(filePathForCallback, content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, filePathForCallback.AddExtension("download")); + return true; +} + +void DownloadTargetHelper::OnDownloadUpdated(content::DownloadItem *download) +{ + switch (download->GetState()) { + case content::DownloadItem::COMPLETE: + case content::DownloadItem::CANCELLED: + case content::DownloadItem::INTERRUPTED: + download->RemoveObserver(this); + m_ongoingDownloads.remove(download); + break; + case content::DownloadItem::IN_PROGRESS: + default: + break; + } +} + +void DownloadTargetHelper::OnDownloadDestroyed(content::DownloadItem *download) +{ + download->RemoveObserver(this); + m_ongoingDownloads.remove(download); +} + +DownloadManagerDelegateQt::DownloadManagerDelegateQt() + : m_targetHelper(new DownloadTargetHelper()) + , m_currentId(0) +{ + +} + +DownloadManagerDelegateQt::~DownloadManagerDelegateQt() +{ + delete m_targetHelper; +} + + +void DownloadManagerDelegateQt::Shutdown() +{ + QT_NOT_YET_IMPLEMENTED +} + +void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& callback) +{ + callback.Run(++m_currentId); +} + +bool DownloadManagerDelegateQt::ShouldOpenFileBasedOnExtension(const base::FilePath& path) +{ + QT_NOT_YET_IMPLEMENTED + return false; +} + +bool DownloadManagerDelegateQt::ShouldCompleteDownload(content::DownloadItem* item, + const base::Closure& complete_callback) +{ + QT_NOT_YET_IMPLEMENTED + return true; +} + +bool DownloadManagerDelegateQt::ShouldOpenDownload(content::DownloadItem* item, + const content::DownloadOpenDelayedCallback& callback) +{ + QT_NOT_YET_IMPLEMENTED + return false; +} + +bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* item, + const content::DownloadTargetCallback& callback) +{ + // Keep the forced file path if set, also as the temporary file, so the check for existence + // will already return that the file exists. Forced file paths seem to be only used for + // store downloads and other special downloads, so they might never end up here anyway. + if (!item->GetForcedFilePath().empty()) { + callback.Run(item->GetForcedFilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, item->GetForcedFilePath()); + return true; + } + + // Let the target helper determine the download target path. + return m_targetHelper->determineDownloadTarget(item, callback); +} + +bool DownloadManagerDelegateQt::GenerateFileHash() +{ + QT_NOT_YET_IMPLEMENTED + return false; +} + +void DownloadManagerDelegateQt::ChooseSavePath( + content::WebContents* web_contents, + const base::FilePath& suggested_path, + const base::FilePath::StringType& default_extension, + bool can_save_as_complete, + const content::SavePackagePathPickedCallback& callback) +{ + QT_NOT_YET_IMPLEMENTED +} + +void DownloadManagerDelegateQt::OpenDownload(content::DownloadItem* download) +{ + QT_NOT_YET_IMPLEMENTED +} + +void DownloadManagerDelegateQt::ShowDownloadInShell(content::DownloadItem* download) +{ + QT_NOT_YET_IMPLEMENTED +} + +void DownloadManagerDelegateQt::CheckForFileExistence( + content::DownloadItem* download, + const content::CheckForFileExistenceCallback& callback) +{ + QT_NOT_YET_IMPLEMENTED +} + +void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_context, + base::FilePath* website_save_dir, + base::FilePath* download_save_dir, + bool* skip_dir_check) +{ + static base::FilePath::StringType save_dir = toFilePathString(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); + *website_save_dir = base::FilePath(save_dir); + *download_save_dir = base::FilePath(save_dir); + *skip_dir_check = true; +} + + diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h new file mode 100644 index 000000000..79f5de167 --- /dev/null +++ b/src/core/download_manager_delegate_qt.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DOWNLOAD_MANAGER_DELEGATE_QT_H +#define DOWNLOAD_MANAGER_DELEGATE_QT_H + +#include "content/public/browser/download_manager_delegate.h" + +#include <qglobal.h> + +namespace base { +class FilePath; +} + +namespace content { +class BrowserContext; +class DownloadItem; +class WebContents; +} + +class DownloadTargetHelper; + +class DownloadManagerDelegateQt : public content::DownloadManagerDelegate +{ +public: + DownloadManagerDelegateQt(); + virtual ~DownloadManagerDelegateQt(); + + void Shutdown() Q_DECL_OVERRIDE; + void GetNextId(const content::DownloadIdCallback& callback) Q_DECL_OVERRIDE; + bool ShouldOpenFileBasedOnExtension(const base::FilePath& path) Q_DECL_OVERRIDE; + bool ShouldCompleteDownload(content::DownloadItem* item, + const base::Closure& complete_callback) Q_DECL_OVERRIDE; + + bool ShouldOpenDownload(content::DownloadItem* item, + const content::DownloadOpenDelayedCallback& callback) Q_DECL_OVERRIDE; + + bool DetermineDownloadTarget(content::DownloadItem* item, + const content::DownloadTargetCallback& callback) Q_DECL_OVERRIDE; + + bool GenerateFileHash() Q_DECL_OVERRIDE; + void ChooseSavePath(content::WebContents* web_contents, + const base::FilePath& suggested_path, + const base::FilePath::StringType& default_extension, + bool can_save_as_complete, + const content::SavePackagePathPickedCallback& callback) Q_DECL_OVERRIDE; + + void OpenDownload(content::DownloadItem* download) Q_DECL_OVERRIDE; + void ShowDownloadInShell(content::DownloadItem* download) Q_DECL_OVERRIDE; + void CheckForFileExistence(content::DownloadItem* download, + const content::CheckForFileExistenceCallback& callback) Q_DECL_OVERRIDE; + + void GetSaveDir(content::BrowserContext* browser_context, + base::FilePath* website_save_dir, + base::FilePath* download_save_dir, + bool* skip_dir_check) Q_DECL_OVERRIDE; + +private: + DownloadTargetHelper* m_targetHelper; + uint64 m_currentId; + DISALLOW_COPY_AND_ASSIGN(DownloadManagerDelegateQt); +}; + +#endif //DOWNLOAD_MANAGER_DELEGATE_QT_H diff --git a/src/core/gyp_configure_host.pro b/src/core/gyp_configure_host.pro new file mode 100644 index 000000000..e99d1e7c5 --- /dev/null +++ b/src/core/gyp_configure_host.pro @@ -0,0 +1,16 @@ +# Prevent generating a makefile that attempts to create a lib +TEMPLATE = aux + +# Pick up the host toolchain +option(host_build) + +GYPI_CONTENTS = "{" \ + " 'make_global_settings': [" \ + " ['CC.host', '$$which($$QMAKE_CC)']," \ + " ['CXX.host', '$$which($$QMAKE_CXX)']," \ + " ['LD.host', '$$which($$QMAKE_LINK)']," + +GYPI_FILE = $$absolute_path('build/qmake_extras.gypi', $$QTWEBENGINE_ROOT) +!build_pass { + write_file($$GYPI_FILE, GYPI_CONTENTS) +} diff --git a/src/core/gyp_configure_target.pro b/src/core/gyp_configure_target.pro new file mode 100644 index 000000000..6d9f414c3 --- /dev/null +++ b/src/core/gyp_configure_target.pro @@ -0,0 +1,36 @@ +# Prevent generating a makefile that attempts to create a lib +TEMPLATE = aux + +TOOLCHAIN_INCLUDES = $${QMAKE_INCDIR_EGL} $${INCLUDEPATH} $${QMAKE_INCDIR} + +GYPI_CONTENTS += " ['CC', '$$which($$QMAKE_CC)']," \ + " ['CXX', '$$which($$QMAKE_CXX)']," \ + " ['LD', '$$which($$QMAKE_LINK)']," +GYPI_CONTENTS += " ]," \ + " 'target_defaults': {" \ + " 'target_conditions': [" \ + " ['_toolset==\"target\"', {" \ + " 'include_dirs': [" +for(includes, TOOLCHAIN_INCLUDES) { + GYPI_CONTENTS += " '$$includes'," +} +GYPI_CONTENTS += " ]," \ + " 'cflags': [" +for(cflag, QT_CFLAGS_DBUS) { + GYPI_CONTENTS += " '$$cflag'," +} +GYPI_CONTENTS += " ]," \ + " }]," \ + " ]," \ + " }," + +GYPI_CONTENTS += "}" + +GYPI_FILE = $$absolute_path('build/qmake_extras.gypi', $$QTWEBENGINE_ROOT) + +!exists($$GYPI_FILE): error("-- $$GYPI not found --") + +# Append to the file already containing the host settings. +!build_pass { + write_file($$GYPI_FILE, GYPI_CONTENTS, append) +} diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro new file mode 100644 index 000000000..e0c8b4af1 --- /dev/null +++ b/src/core/gyp_run.pro @@ -0,0 +1,61 @@ +# This .pro file serves a dual purpose: +# 1) invoking gyp through the gyp_qtwebengine script, which in turn makes use of the generated gypi include files +# 2) produce a Makefile that will run ninja, and take care of actually building everything. + +TEMPLATE = aux + +GYP_ARGS = "-D qt_cross_compile=0" +cross_compile { + GYP_ARGS = "-D qt_cross_compile=1 -D os_posix=1" + TOOLCHAIN_SYSROOT = $$[QT_SYSROOT] + !isEmpty(TOOLCHAIN_SYSROOT): GYP_ARGS += "-D sysroot=\"$${TOOLCHAIN_SYSROOT}\"" + + contains(QT_ARCH, "arm") { + GYP_ARGS += "-D target_arch=arm" + + # Extract ARM specific compiler options that we have to pass to gyp, + # but let gyp figure out a default if an option is not present. + MARCH = $$extractCFlag("-march=.*") + !isEmpty(MARCH): GYP_ARGS += "-D arm_arch=\"$$MARCH\"" + + MFPU = $$extractCFlag("-mfpu=.*") + !isEmpty(MFPU) { + GYP_ARGS += "-D arm_fpu=\"$$MFPU\"" + contains(MFPU, "neon"): GYP_ARGS += "-D arm_neon=\"$$NEON\"" + } + + MTUNE = $$extractCFlag("-mtune=.*") + !isEmpty(MTUNE): GYP_ARGS += "-D arm_tune=\"$$MTUNE\"" + + MFLOAT = $$extractCFlag("-mfloat-abi=.*") + !isEmpty(MFLOAT): GYP_ARGS += "-D arm_float_abi=\"$$MFLOAT\"" + + MARMV = $$replace(MARCH, "armv",) + !isEmpty(MARMV) { + MARMV = $$split(MARMV,) + MARMV = $$member(MARMV, 0) + GYP_ARGS += "-D arm_version=\"$$MARMV\"" + } + + contains(QMAKE_CFLAGS, "-mthumb"): GYP_ARGS += "-D arm_thumb=1" + } + + # Needed for v8, see chromium/v8/build/toolchain.gypi + GYP_ARGS += "-D CXX=\"$$which($$QMAKE_CXX)\"" +} + +!build_pass { + message(Running gyp_qtwebengine $${GYP_ARGS}...) + !system("python ./gyp_qtwebengine $${GYP_ARGS}"): error("-- running gyp_qtwebengine failed --") +} + +ninja.target = invoke_ninja +ninja.commands = $$findOrBuildNinja() $$(NINJAFLAGS) -C $$getOutDir()/$$getConfigDir() +ninja.depends: qmake +QMAKE_EXTRA_TARGETS += ninja + +build_pass:build_all:default_target.target = all +else: default_target.target = first +default_target.depends = ninja + +QMAKE_EXTRA_TARGETS += default_target diff --git a/src/core/javascript_dialog_manager_qt.cpp b/src/core/javascript_dialog_manager_qt.cpp new file mode 100644 index 000000000..b2f6d86bc --- /dev/null +++ b/src/core/javascript_dialog_manager_qt.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "javascript_dialog_manager_qt.h" + +#include "web_contents_adapter_client.h" +#include "web_contents_view_qt.h" +#include "type_conversion.h" + +#include "base/memory/singleton.h" + +Q_STATIC_ASSERT_X(static_cast<int>(content::JAVASCRIPT_MESSAGE_TYPE_PROMPT) == static_cast<int>(WebContentsAdapterClient::PromptDialog), "These enums should be in sync."); + +JavaScriptDialogManagerQt *JavaScriptDialogManagerQt::GetInstance() +{ + return Singleton<JavaScriptDialogManagerQt>::get(); +} + +void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, const GURL &originUrl, const std::string &acceptLang, content::JavaScriptMessageType javascriptMessageType, const base::string16 &messageText, const base::string16 &defaultPromptText, const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) +{ + Q_UNUSED(originUrl); + Q_UNUSED(acceptLang); + + WebContentsAdapterClient *client = WebContentsViewQt::from(webContents->GetView())->client(); + if (!client) { + *didSuppressMessage = true; + return; + } + + QString promptInput; + WebContentsAdapterClient::JavascriptDialogType dialogType = static_cast<WebContentsAdapterClient::JavascriptDialogType>(javascriptMessageType); + bool res = client->javascriptDialog(dialogType, toQt(messageText).toHtmlEscaped(), toQt(defaultPromptText).toHtmlEscaped(), &promptInput); + callback.Run(res, toString16(promptInput)); +} + +bool JavaScriptDialogManagerQt::HandleJavaScriptDialog(content::WebContents *, bool accept, const base::string16 *promptOverride) +{ + // FIXME: We might need to keep a queue of modal dialogs in there and unqueue them... + return false; +} diff --git a/src/core/javascript_dialog_manager_qt.h b/src/core/javascript_dialog_manager_qt.h new file mode 100644 index 000000000..de416e03e --- /dev/null +++ b/src/core/javascript_dialog_manager_qt.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef JAVASCRIPT_DIALOG_MANAGER_QT_H +#define JAVASCRIPT_DIALOG_MANAGER_QT_H + +#include "content/public/browser/javascript_dialog_manager.h" +#include "content/public/common/javascript_message_type.h" + +#include "qglobal.h" + +namespace content { +class WebContents; +} + +class JavaScriptDialogManagerQt : public content::JavaScriptDialogManager +{ +public: + // For use with the Singleton helper class from chromium + static JavaScriptDialogManagerQt *GetInstance(); + + virtual void RunJavaScriptDialog(content::WebContents *, const GURL &, const std::string &acceptLang, content::JavaScriptMessageType javascriptMessageType, + const base::string16 &messageText, const base::string16 &defaultPromptText, + const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) Q_DECL_OVERRIDE; + virtual void RunBeforeUnloadDialog(content::WebContents *, const base::string16 &messageText, bool isReload, + const content::JavaScriptDialogManager::DialogClosedCallback &callback) Q_DECL_OVERRIDE { Q_UNUSED(messageText); Q_UNUSED(isReload); Q_UNUSED(callback); } + virtual bool HandleJavaScriptDialog(content::WebContents *, bool accept, const base::string16 *promptOverride) Q_DECL_OVERRIDE; + virtual void CancelActiveAndPendingDialogs(content::WebContents *) Q_DECL_OVERRIDE {} + virtual void WebContentsDestroyed(content::WebContents *) Q_DECL_OVERRIDE {} + +}; + +#endif // JAVASCRIPT_DIALOG_MANAGER_QT_H + diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp new file mode 100644 index 000000000..27807c499 --- /dev/null +++ b/src/core/network_delegate_qt.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "network_delegate_qt.h" diff --git a/src/core/network_delegate_qt.h b/src/core/network_delegate_qt.h new file mode 100644 index 000000000..9413addb3 --- /dev/null +++ b/src/core/network_delegate_qt.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef NETWORK_DELEGATE_QT_H +#define NETWORK_DELEGATE_QT_H + +#include "net/base/network_delegate.h" + +#include "qglobal.h" + +class NetworkDelegateQt : public net::NetworkDelegate { +public: + NetworkDelegateQt() {} + virtual ~NetworkDelegateQt() {} + + + private: + // net::NetworkDelegate implementation. + virtual int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* new_url) Q_DECL_OVERRIDE + { + return net::OK; + } + + virtual int OnBeforeSendHeaders(net::URLRequest* request, const net::CompletionCallback& callback, net::HttpRequestHeaders* headers) Q_DECL_OVERRIDE + { + return net::OK; + } + + virtual void OnSendHeaders(net::URLRequest* request, const net::HttpRequestHeaders& headers) Q_DECL_OVERRIDE {} + virtual int OnHeadersReceived(net::URLRequest* request, const net::CompletionCallback& callback, + const net::HttpResponseHeaders* original_response_headers, + scoped_refptr<net::HttpResponseHeaders>* override_response_headers) Q_DECL_OVERRIDE { return net::OK; } + + virtual void OnBeforeRedirect(net::URLRequest* request, const GURL& new_location) Q_DECL_OVERRIDE { } + virtual void OnResponseStarted(net::URLRequest* request) Q_DECL_OVERRIDE { } + virtual void OnRawBytesRead(const net::URLRequest& request, int bytes_read) Q_DECL_OVERRIDE { } + virtual void OnCompleted(net::URLRequest* request, bool started) Q_DECL_OVERRIDE { } + virtual void OnURLRequestDestroyed(net::URLRequest* request) Q_DECL_OVERRIDE { } + + virtual void OnPACScriptError(int line_number, const base::string16& error) Q_DECL_OVERRIDE { } + virtual AuthRequiredResponse OnAuthRequired(net::URLRequest* request, const net::AuthChallengeInfo& auth_info, + const AuthCallback& callback, net::AuthCredentials* credentials) Q_DECL_OVERRIDE { return AUTH_REQUIRED_RESPONSE_NO_ACTION; } + + virtual bool OnCanGetCookies(const net::URLRequest& request, const net::CookieList& cookie_list) Q_DECL_OVERRIDE { return true; } + virtual bool OnCanSetCookie(const net::URLRequest& request, const std::string& cookie_line, net::CookieOptions* options) Q_DECL_OVERRIDE { return true; } + virtual bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& path) const Q_DECL_OVERRIDE { return true; } + virtual bool OnCanThrottleRequest(const net::URLRequest& request) const Q_DECL_OVERRIDE { return false; } + virtual int OnBeforeSocketStreamConnect(net::SocketStream* stream, const net::CompletionCallback& callback) Q_DECL_OVERRIDE { return net::OK; } + virtual void OnRequestWaitStateChange(const net::URLRequest& request, RequestWaitState state) Q_DECL_OVERRIDE { } +}; + +#endif // NETWORK_DELEGATE_QT_H diff --git a/src/core/process_main.cpp b/src/core/process_main.cpp new file mode 100644 index 000000000..af44ba600 --- /dev/null +++ b/src/core/process_main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "process_main.h" +#include "content/public/app/content_main.h" + +namespace QtWebEngine { + +int processMain(int argc, const char **argv) +{ + return content::ContentMain(argc, argv, 0); +} + +} diff --git a/src/core/process_main.h b/src/core/process_main.h new file mode 100644 index 000000000..2bd37a336 --- /dev/null +++ b/src/core/process_main.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtwebenginecoreglobal.h" + +namespace QtWebEngine { + +QWEBENGINE_EXPORT int processMain(int argc, const char **argv); + +} diff --git a/src/core/qtwebengine.gypi b/src/core/qtwebengine.gypi new file mode 100644 index 000000000..f13e781f5 --- /dev/null +++ b/src/core/qtwebengine.gypi @@ -0,0 +1,104 @@ +{ + 'variables': { + 'blink_process_product_name': 'Blink Process', +# Define used when building the user agent. Pass as recent enough chrome with an irrealistic minor version. + 'user_agent_version': '22.42.5.2', + 'conditions': [ + ['OS=="linux"', { + 'use_custom_freetype%': 1, + }, { + 'use_custom_freetype%': 0, + }], + ], + }, + 'dependencies': [ + '<(chromium_src_dir)/content/content.gyp:content', + '<(chromium_src_dir)/content/content.gyp:content_app_browser', + '<(chromium_src_dir)/content/content.gyp:content_browser', + '<(chromium_src_dir)/content/content.gyp:content_common', + '<(chromium_src_dir)/content/content.gyp:content_gpu', + '<(chromium_src_dir)/content/content.gyp:content_renderer', + '<(chromium_src_dir)/content/content.gyp:content_utility', + '<(chromium_src_dir)/content/content.gyp:content_worker', + '<(chromium_src_dir)/content/content_resources.gyp:content_resources', + '<(chromium_src_dir)/base/base.gyp:base', + '<(chromium_src_dir)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', + '<(chromium_src_dir)/ipc/ipc.gyp:ipc', + '<(chromium_src_dir)/media/media.gyp:media', + '<(chromium_src_dir)/net/net.gyp:net', + '<(chromium_src_dir)/net/net.gyp:net_resources', + '<(chromium_src_dir)/skia/skia.gyp:skia', + '<(chromium_src_dir)/ui/gl/gl.gyp:gl', + '<(chromium_src_dir)/ui/ui.gyp:ui', + '<(chromium_src_dir)/url/url.gyp:url_lib', + '<(chromium_src_dir)/v8/tools/gyp/v8.gyp:v8', + '<(chromium_src_dir)/webkit/webkit_resources.gyp:webkit_resources', + '<(chromium_src_dir)/webkit/support/webkit_support.gyp:webkit_support', + '<(chromium_src_dir)/third_party/WebKit/Source/web/web.gyp:webkit', + ], + 'include_dirs': [ + '<(qtwebengine_src_dir)', + '<(chromium_src_dir)', + ], + # Chromium code defines those in common.gypi, do the same for our code that include Chromium headers. + 'defines': [ + '__STDC_CONSTANT_MACROS', + '__STDC_FORMAT_MACROS', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS + }, + }, + 'conditions': [ + ['OS=="win" and win_use_allocator_shim==1', { + 'dependencies': [ + '<(chromium_src_dir)/base/allocator/allocator.gyp:allocator', + ], + }], + ['OS=="win"', { + 'resource_include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)/webkit', + ], + 'dependencies': [ + '<(DEPTH)/webkit/webkit_resources.gyp:webkit_strings', + ], + 'configurations': { + 'Debug_Base': { + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '<(msvs_large_module_debug_link_mode)', + }, + }, + }, + }, +# TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + 'msvs_disabled_warnings': [ 4267, ], + }], # OS=="win" + ['OS=="linux"', { + 'dependencies': [ + '<(chromium_src_dir)/build/linux/system.gyp:fontconfig', + ], + }], + ['os_posix==1 and linux_use_tcmalloc==1', { + 'dependencies': [ +# This is needed by content/app/content_main_runner.cc + '<(chromium_src_dir)/base/allocator/allocator.gyp:allocator', + ], + }], + ['use_aura==1', { + 'dependencies': [ + '<(chromium_src_dir)/ui/aura/aura.gyp:aura', + '<(chromium_src_dir)/ui/base/strings/ui_strings.gyp:ui_strings', + '<(chromium_src_dir)/ui/views/controls/webview/webview.gyp:webview', + '<(chromium_src_dir)/ui/views/views.gyp:views', + '<(chromium_src_dir)/ui/ui.gyp:ui_resources', + ], + }], # use_aura==1 + ['use_custom_freetype==1', { + 'dependencies': [ + '<(chromium_src_dir)/third_party/freetype2/freetype2.gyp:freetype2', + ], + }], + ], +} diff --git a/src/core/qtwebengine_extras.gypi b/src/core/qtwebengine_extras.gypi new file mode 100644 index 000000000..2937ee423 --- /dev/null +++ b/src/core/qtwebengine_extras.gypi @@ -0,0 +1,51 @@ +{ + 'target_defaults': { + # patterns used to exclude chromium files from the build when we have a drop-in replacement + 'sources/': [ + ['exclude', 'base/resource/resource_bundle_gtk.cc$'], + ['exclude', 'base/resource/resource_bundle_mac.mm$'], + ['exclude', 'base/resource/resource_bundle_win.cc$'], + ['exclude', 'browser/web_contents/web_contents_view_gtk\\.(cc|h)$'], + ['exclude', 'browser/web_contents/web_contents_view_mac\\.(mm|h)$'], + ['exclude', 'browser/web_contents/web_contents_view_win\\.(cc|h)$'], + ['exclude', 'browser/renderer_host/gtk_im_context_wrapper\\.cc$'], + ['exclude', 'browser/renderer_host/render_widget_host_view_gtk\\.(cc|h)$'], + ['exclude', 'browser/renderer_host/render_widget_host_view_mac\\.(mm|h)$'], + ['exclude', 'browser/renderer_host/render_widget_host_view_win\\.(cc|h)$'], + + # QNX-specific excludes + ['exclude', 'base/resource/resource_bundle_qnx.cc$'], + ['exclude', 'browser/qnx/'], + ['exclude', 'browser/renderer_host/render_widget_host_view_qnx\\.(cc|h)$'], + ['exclude', 'browser/web_contents/web_contents_view_qnx\\.(cc|h)$'], + ], + }, + 'conditions': [ + [ 'OS=="linux" and qt_cross_compile==1', { + 'target_defaults': { + 'defines': [ + 'TOOLKIT_QT', + ], + 'target_conditions': [ + ['_toolset=="target"', { + 'ldflags!': ['-L/usr/lib'], # garbage added by icu-config + 'conditions': [ + [ '_target_name=="gl"', { + 'defines': [ + 'GL_GLEXT_PROTOTYPES', + 'EGL_EGLEXT_PROTOTYPES', + ], + }], + ['_type=="shared_library"', { + 'ldflags': [ + # Tell the linker to prefer symbols within the library before looking outside + '-Wl,-shared,-Bsymbolic', + ], + }], + ], + }], + ], + }, + }], + ], +} diff --git a/src/core/qtwebenginecoreglobal.h b/src/core/qtwebenginecoreglobal.h new file mode 100644 index 000000000..b84c321d0 --- /dev/null +++ b/src/core/qtwebenginecoreglobal.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QTWEBENGINECOREGLOBAL_H +#define QTWEBENGINECOREGLOBAL_H + +#include <QtCore/qglobal.h> + +#ifdef QT_WEBENGINE_LOGGING +#define QT_NOT_YET_IMPLEMENTED fprintf(stderr, "function %s not implemented! - %s:%d\n", __func__, __FILE__, __LINE__); +#define QT_NOT_USED fprintf(stderr, "# function %s should not be used! - %s:%d\n", __func__, __FILE__, __LINE__); Q_UNREACHABLE(); +#else +#define QT_NOT_YET_IMPLEMENTED qt_noop(); +#define QT_NOT_USED Q_UNREACHABLE(); // This will assert in debug. +#endif + +#ifndef QT_STATIC +# if defined(BUILDING_CHROMIUM) +# define QWEBENGINE_EXPORT Q_DECL_EXPORT +# else +# define QWEBENGINE_EXPORT Q_DECL_IMPORT +# endif +#else +# define QWEBENGINE_EXPORT +#endif + +#endif // QTWEBENGINECOREGLOBAL_H diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp new file mode 100644 index 000000000..91e9ab585 --- /dev/null +++ b/src/core/render_widget_host_view_qt.cpp @@ -0,0 +1,910 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "render_widget_host_view_qt.h" + +#include "backing_store_qt.h" +#include "chromium_overrides.h" +#include "delegated_frame_node.h" +#include "render_widget_host_view_qt_delegate.h" +#include "type_conversion.h" +#include "web_event_factory.h" + +#include "cc/output/compositor_frame_ack.h" +#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/renderer_host/ui_events_helper.h" +#include "content/common/gpu/gpu_messages.h" +#include "content/common/view_messages.h" +#include "lib/type_conversion.h" +#include "third_party/WebKit/public/web/WebCursorInfo.h" +#include "ui/base/events/event.h" +#include "ui/gfx/size_conversions.h" +#include "webkit/common/cursors/webcursor.h" + +#include <QEvent> +#include <QFocusEvent> +#include <QGuiApplication> +#include <QKeyEvent> +#include <QMouseEvent> +#include <QScreen> +#include <QStyleHints> +#include <QVariant> +#include <QWheelEvent> +#include <QWindow> + +static inline ui::EventType toUIEventType(Qt::TouchPointState state) +{ + switch (state) { + case Qt::TouchPointPressed: + return ui::ET_TOUCH_PRESSED; + case Qt::TouchPointMoved: + return ui::ET_TOUCH_MOVED; + case Qt::TouchPointStationary: + return ui::ET_TOUCH_STATIONARY; + case Qt::TouchPointReleased: + return ui::ET_TOUCH_RELEASED; + default: + Q_ASSERT(false); + return ui::ET_UNKNOWN; + } +} + +static inline Qt::InputMethodHints toQtInputMethodHints(ui::TextInputType inputType) +{ + switch (inputType) { + case ui::TEXT_INPUT_TYPE_TEXT: + return Qt::ImhPreferLowercase; + case ui::TEXT_INPUT_TYPE_SEARCH: + return Qt::ImhPreferLowercase | Qt::ImhNoAutoUppercase; + case ui::TEXT_INPUT_TYPE_PASSWORD: + return Qt::ImhSensitiveData | Qt::ImhNoPredictiveText | Qt::ImhNoAutoUppercase; + case ui::TEXT_INPUT_TYPE_EMAIL: + return Qt::ImhEmailCharactersOnly; + case ui::TEXT_INPUT_TYPE_NUMBER: + return Qt::ImhFormattedNumbersOnly; + case ui::TEXT_INPUT_TYPE_TELEPHONE: + return Qt::ImhDialableCharactersOnly; + case ui::TEXT_INPUT_TYPE_URL: + return Qt::ImhUrlCharactersOnly | Qt::ImhNoPredictiveText | Qt::ImhNoAutoUppercase; + case ui::TEXT_INPUT_TYPE_DATE_TIME: + case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL: + case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD: + return Qt::ImhDate | Qt::ImhTime; + case ui::TEXT_INPUT_TYPE_DATE: + case ui::TEXT_INPUT_TYPE_MONTH: + case ui::TEXT_INPUT_TYPE_WEEK: + return Qt::ImhDate; + case ui::TEXT_INPUT_TYPE_TIME: + return Qt::ImhTime; + case ui::TEXT_INPUT_TYPE_TEXT_AREA: + case ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE: + return Qt::ImhMultiLine | Qt::ImhPreferLowercase; + default: + return Qt::ImhNone; + } +} + +static inline gfx::Point toGfxPoint(const QPoint& point) +{ + return gfx::Point(point.x(), point.y()); +} + +static void UpdateWebTouchEventAfterDispatch(WebKit::WebTouchEvent* event, WebKit::WebTouchPoint* point) { + if (point->state != WebKit::WebTouchPoint::StateReleased && + point->state != WebKit::WebTouchPoint::StateCancelled) + return; + --event->touchesLength; + for (unsigned i = point - event->touches; i < event->touchesLength; ++i) { + event->touches[i] = event->touches[i + 1]; + } +} + +RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget) + : m_host(content::RenderWidgetHostImpl::From(widget)) + , m_gestureRecognizer(ui::GestureRecognizer::Create(this)) + , m_backingStore(0) + , m_adapterClient(0) + , m_anchorPositionWithinSelection(0) + , m_cursorPositionWithinSelection(0) + , m_initPending(false) + , m_readyForSurface(false) +{ + m_host->SetView(this); +} + +RenderWidgetHostViewQt::~RenderWidgetHostViewQt() +{ +} + +void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate) +{ + m_delegate.reset(delegate); +} + +void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterClient) +{ + Q_ASSERT(!m_adapterClient); + + m_adapterClient = adapterClient; + if (m_initPending) + InitAsChild(0); +} + +BackingStoreQt* RenderWidgetHostViewQt::GetBackingStore() +{ + bool force_create = !m_host->empty(); + return static_cast<BackingStoreQt*>(m_host->GetBackingStore(force_create)); +} + +content::BackingStore *RenderWidgetHostViewQt::AllocBackingStore(const gfx::Size &size) +{ + Q_ASSERT(m_delegate); + return new BackingStoreQt(m_host, size, m_delegate->window()); +} + +void RenderWidgetHostViewQt::InitAsChild(gfx::NativeView) +{ + if (!m_adapterClient) { + m_initPending = true; + return; + } + m_initPending = false; + m_delegate->initAsChild(m_adapterClient); +} + +void RenderWidgetHostViewQt::InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect& rect) +{ + m_delegate->initAsPopup(toQt(rect)); +} + +void RenderWidgetHostViewQt::InitAsFullscreen(content::RenderWidgetHostView*) +{ +} + +content::RenderWidgetHost* RenderWidgetHostViewQt::GetRenderWidgetHost() const +{ + return m_host; +} + +void RenderWidgetHostViewQt::SetSize(const gfx::Size& size) +{ + int width = size.width(); + int height = size.height(); + + m_delegate->resize(width,height); +} + +void RenderWidgetHostViewQt::SetBounds(const gfx::Rect& rect) +{ + // This is called when webkit has sent us a Move message. + // if (IsPopup()) + // m_delegate->setGeometry(rect.x(), rect.y(), rect.width(), rect.height()); + SetSize(rect.size()); +} + +gfx::Size RenderWidgetHostViewQt::GetPhysicalBackingSize() const +{ + if (!m_delegate || !m_delegate->window() || !m_delegate->window()->screen()) + return gfx::Size(); + + const QScreen* screen = m_delegate->window()->screen(); + return gfx::ToCeiledSize(gfx::ScaleSize(GetViewBounds().size(), screen->devicePixelRatio())); +} + +gfx::NativeView RenderWidgetHostViewQt::GetNativeView() const +{ + // gfx::NativeView is a typedef to a platform specific view + // pointer (HWND, NSView*, GtkWidget*) and other ports use + // this function in the renderer_host layer when setting up + // the view hierarchy and for generating snapshots in tests. + // Since we manage the view hierarchy in Qt we can possibly + // avoid calls to this. + QT_NOT_USED + return gfx::NativeView(); +} + +gfx::NativeViewId RenderWidgetHostViewQt::GetNativeViewId() const +{ + const_cast<RenderWidgetHostViewQt *>(this)->m_readyForSurface = true; + return m_delegate->nativeWindowIdForCompositor(); +} + +gfx::NativeViewAccessible RenderWidgetHostViewQt::GetNativeViewAccessible() +{ + // We are not using accessibility features at this point. + QT_NOT_USED + return NULL; +} + +// Set focus to the associated View component. +void RenderWidgetHostViewQt::Focus() +{ + m_host->SetInputMethodActive(true); + m_delegate->setKeyboardFocus(); + m_host->Focus(); +} + +bool RenderWidgetHostViewQt::HasFocus() const +{ + return m_delegate->hasKeyboardFocus(); +} + +bool RenderWidgetHostViewQt::IsSurfaceAvailableForCopy() const +{ + return true; +} + +void RenderWidgetHostViewQt::Show() +{ + m_delegate->show(); +} + +void RenderWidgetHostViewQt::Hide() +{ + m_delegate->hide(); +} + +bool RenderWidgetHostViewQt::IsShowing() +{ + return m_delegate->isVisible(); +} + +// Retrieve the bounds of the View, in screen coordinates. +gfx::Rect RenderWidgetHostViewQt::GetViewBounds() const +{ + QRectF p = m_delegate->screenRect(); + return gfx::Rect(p.x(), p.y(), p.width(), p.height()); +} + +// Subclasses should override this method to do what is appropriate to set +// the custom background for their platform. +void RenderWidgetHostViewQt::SetBackground(const SkBitmap& background) +{ + RenderWidgetHostViewBase::SetBackground(background); + // Send(new ViewMsg_SetBackground(m_host->GetRoutingID(), background)); +} + +// Return value indicates whether the mouse is locked successfully or not. +bool RenderWidgetHostViewQt::LockMouse() +{ + QT_NOT_USED + return false; +} +void RenderWidgetHostViewQt::UnlockMouse() +{ + QT_NOT_USED +} + +// FIXME: remove TOOLKIT_GTK related things. +#if defined(TOOLKIT_GTK) +// Gets the event for the last mouse down. +GdkEventButton* RenderWidgetHostViewQt::GetLastMouseDown() +{ + return 0; +} + +gfx::NativeView RenderWidgetHostViewQt::BuildInputMethodsGtkMenu() +{ + return 0; +} +#endif // defined(TOOLKIT_GTK) + +void RenderWidgetHostViewQt::WasShown() +{ + if (m_delegate->isVisible()) + return; + + m_host->WasShown(); +} + +void RenderWidgetHostViewQt::WasHidden() +{ + if (!m_delegate->isVisible()) + return; + + m_host->WasHidden(); +} + +void RenderWidgetHostViewQt::MovePluginWindows(const gfx::Vector2d&, const std::vector<content::WebPluginGeometry>&) +{ + // QT_NOT_YET_IMPLEMENTED +} + +void RenderWidgetHostViewQt::Blur() +{ + m_host->SetInputMethodActive(false); + m_host->Blur(); +} + +void RenderWidgetHostViewQt::UpdateCursor(const WebCursor &webCursor) +{ + WebCursor::CursorInfo cursorInfo; + webCursor.GetCursorInfo(&cursorInfo); + Qt::CursorShape shape; + switch (cursorInfo.type) { + case WebKit::WebCursorInfo::TypePointer: + shape = Qt::ArrowCursor; + break; + case WebKit::WebCursorInfo::TypeCross: + shape = Qt::CrossCursor; + break; + case WebKit::WebCursorInfo::TypeHand: + shape = Qt::PointingHandCursor; + break; + case WebKit::WebCursorInfo::TypeIBeam: + shape = Qt::IBeamCursor; + break; + case WebKit::WebCursorInfo::TypeWait: + shape = Qt::WaitCursor; + break; + case WebKit::WebCursorInfo::TypeHelp: + shape = Qt::WhatsThisCursor; + break; + case WebKit::WebCursorInfo::TypeEastResize: + case WebKit::WebCursorInfo::TypeWestResize: + case WebKit::WebCursorInfo::TypeEastWestResize: + case WebKit::WebCursorInfo::TypeEastPanning: + case WebKit::WebCursorInfo::TypeWestPanning: + shape = Qt::SizeHorCursor; + break; + case WebKit::WebCursorInfo::TypeNorthResize: + case WebKit::WebCursorInfo::TypeSouthResize: + case WebKit::WebCursorInfo::TypeNorthSouthResize: + case WebKit::WebCursorInfo::TypeNorthPanning: + case WebKit::WebCursorInfo::TypeSouthPanning: + shape = Qt::SizeVerCursor; + break; + case WebKit::WebCursorInfo::TypeNorthEastResize: + case WebKit::WebCursorInfo::TypeSouthWestResize: + case WebKit::WebCursorInfo::TypeNorthEastSouthWestResize: + case WebKit::WebCursorInfo::TypeNorthEastPanning: + case WebKit::WebCursorInfo::TypeSouthWestPanning: + shape = Qt::SizeBDiagCursor; + break; + case WebKit::WebCursorInfo::TypeNorthWestResize: + case WebKit::WebCursorInfo::TypeSouthEastResize: + case WebKit::WebCursorInfo::TypeNorthWestSouthEastResize: + case WebKit::WebCursorInfo::TypeNorthWestPanning: + case WebKit::WebCursorInfo::TypeSouthEastPanning: + shape = Qt::SizeFDiagCursor; + break; + case WebKit::WebCursorInfo::TypeColumnResize: + shape = Qt::SplitHCursor; + break; + case WebKit::WebCursorInfo::TypeRowResize: + shape = Qt::SplitVCursor; + break; + case WebKit::WebCursorInfo::TypeMiddlePanning: + case WebKit::WebCursorInfo::TypeMove: + shape = Qt::SizeAllCursor; + break; + case WebKit::WebCursorInfo::TypeVerticalText: + case WebKit::WebCursorInfo::TypeCell: + case WebKit::WebCursorInfo::TypeContextMenu: + case WebKit::WebCursorInfo::TypeAlias: + case WebKit::WebCursorInfo::TypeProgress: + case WebKit::WebCursorInfo::TypeCopy: + case WebKit::WebCursorInfo::TypeZoomIn: + case WebKit::WebCursorInfo::TypeZoomOut: + // FIXME: Load from the resource bundle. + shape = Qt::ArrowCursor; + break; + case WebKit::WebCursorInfo::TypeNoDrop: + case WebKit::WebCursorInfo::TypeNotAllowed: + shape = Qt::ForbiddenCursor; + break; + case WebKit::WebCursorInfo::TypeNone: + shape = Qt::BlankCursor; + break; + case WebKit::WebCursorInfo::TypeGrab: + shape = Qt::OpenHandCursor; + break; + case WebKit::WebCursorInfo::TypeGrabbing: + shape = Qt::ClosedHandCursor; + break; + case WebKit::WebCursorInfo::TypeCustom: + // FIXME: Extract from the CursorInfo. + shape = Qt::ArrowCursor; + break; + default: + Q_UNREACHABLE(); + shape = Qt::ArrowCursor; + } + m_delegate->updateCursor(QCursor(shape)); +} + +void RenderWidgetHostViewQt::SetIsLoading(bool) +{ + // We use WebContentsDelegateQt::LoadingStateChanged to notify about loading state. +} + +void RenderWidgetHostViewQt::TextInputTypeChanged(ui::TextInputType type, bool, ui::TextInputMode) +{ + m_currentInputType = type; + m_delegate->inputMethodStateChanged(static_cast<bool>(type)); +} + +void RenderWidgetHostViewQt::ImeCancelComposition() +{ + QT_NOT_YET_IMPLEMENTED +} + +void RenderWidgetHostViewQt::ImeCompositionRangeChanged(const ui::Range&, const std::vector<gfx::Rect>&) +{ + // FIXME: not implemented? + QT_NOT_YET_IMPLEMENTED +} + +void RenderWidgetHostViewQt::DidUpdateBackingStore(const gfx::Rect& scroll_rect, const gfx::Vector2d& scroll_delta, const std::vector<gfx::Rect>& copy_rects, const ui::LatencyInfo& /* latency_info */) +{ + if (!m_delegate->isVisible()) + return; + + Paint(scroll_rect); + + for (size_t i = 0; i < copy_rects.size(); ++i) { + gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect); + if (rect.IsEmpty()) + continue; + Paint(rect); + } +} + +void RenderWidgetHostViewQt::RenderProcessGone(base::TerminationStatus, int) +{ + Destroy(); +} + +void RenderWidgetHostViewQt::Destroy() +{ + delete this; +} + +void RenderWidgetHostViewQt::SetTooltipText(const string16&) +{ + // QT_NOT_YET_IMPLEMENTED +} + +void RenderWidgetHostViewQt::SelectionBoundsChanged(const ViewHostMsg_SelectionBounds_Params ¶ms) +{ + if (selection_range_.IsValid()) { + if (params.is_anchor_first) { + m_anchorPositionWithinSelection = selection_range_.GetMin() - selection_text_offset_; + m_cursorPositionWithinSelection = selection_range_.GetMax() - selection_text_offset_; + } else { + m_anchorPositionWithinSelection = selection_range_.GetMax() - selection_text_offset_; + m_cursorPositionWithinSelection = selection_range_.GetMin() - selection_text_offset_; + } + } + + gfx::Rect caretRect = gfx::UnionRects(params.anchor_rect, params.focus_rect); + m_cursorRect = QRect(caretRect.x(), caretRect.y(), caretRect.width(), caretRect.height()); +} + +void RenderWidgetHostViewQt::ScrollOffsetChanged() +{ + // Not used. +} + +void RenderWidgetHostViewQt::CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& /* dst_size */, const base::Callback<void(bool, const SkBitmap&)>& callback) +{ + // Grab the snapshot from the renderer as that's the only reliable way to + // readback from the GPU for this platform right now. + // FIXME: is this true? + GetRenderWidgetHost()->GetSnapshotFromRenderer(src_subrect, callback); +} + +void RenderWidgetHostViewQt::CopyFromCompositingSurfaceToVideoFrame(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(bool)>& callback) +{ + NOTIMPLEMENTED(); + callback.Run(false); +} + +bool RenderWidgetHostViewQt::CanCopyToVideoFrame() const +{ + return false; +} + +void RenderWidgetHostViewQt::OnAcceleratedCompositingStateChange() +{ + // bool activated = m_host->is_accelerated_compositing_active(); + QT_NOT_YET_IMPLEMENTED +} + +void RenderWidgetHostViewQt::AcceleratedSurfaceBuffersSwapped(const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, int gpu_host_id) +{ + AcceleratedSurfaceMsg_BufferPresented_Params ack_params; + ack_params.sync_point = 0; + content::RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id, gpu_host_id, ack_params); +} + +void RenderWidgetHostViewQt::AcceleratedSurfacePostSubBuffer(const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, int gpu_host_id) +{ + AcceleratedSurfaceMsg_BufferPresented_Params ack_params; + ack_params.sync_point = 0; + content::RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id, gpu_host_id, ack_params); +} + +void RenderWidgetHostViewQt::AcceleratedSurfaceSuspend() +{ + QT_NOT_YET_IMPLEMENTED +} + +void RenderWidgetHostViewQt::AcceleratedSurfaceRelease() +{ + QT_NOT_YET_IMPLEMENTED +} + +bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&) +{ + return false; +} + +void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) +{ + Q_ASSERT(!m_pendingFrameData); + Q_ASSERT(frame->delegated_frame_data); + m_pendingOutputSurfaceId = output_surface_id; + m_pendingFrameData = frame->delegated_frame_data.Pass(); + m_delegate->update(); +} + +void RenderWidgetHostViewQt::GetScreenInfo(WebKit::WebScreenInfo* results) +{ + QWindow* window = m_delegate->window(); + if (!window) + return; + GetScreenInfoFromNativeWindow(window, results); +} + +gfx::Rect RenderWidgetHostViewQt::GetBoundsInRootWindow() +{ + if (!m_delegate->window()) + return gfx::Rect(); + + QRect r = m_delegate->window()->frameGeometry(); + return gfx::Rect(r.x(), r.y(), r.width(), r.height()); +} + +gfx::GLSurfaceHandle RenderWidgetHostViewQt::GetCompositingSurface() +{ + gfx::NativeViewId nativeViewId = GetNativeViewId(); + return nativeViewId ? gfx::GLSurfaceHandle(nativeViewId, gfx::NATIVE_TRANSPORT) : gfx::GLSurfaceHandle(); +} + +void RenderWidgetHostViewQt::SetHasHorizontalScrollbar(bool) { } + +void RenderWidgetHostViewQt::SetScrollOffsetPinning(bool, bool) { } + +void RenderWidgetHostViewQt::OnAccessibilityNotifications(const std::vector<AccessibilityHostMsg_NotificationParams>&) +{ + // We are not using accessibility features at this point. + QT_NOT_USED +} + +bool RenderWidgetHostViewQt::DispatchLongPressGestureEvent(ui::GestureEvent *) +{ + return false; +} + +bool RenderWidgetHostViewQt::DispatchCancelTouchEvent(ui::TouchEvent *) +{ + return false; +} + +void RenderWidgetHostViewQt::paint(QPainter *painter, const QRectF& boundingRect) +{ + if (m_backingStore) + m_backingStore->paintToTarget(painter, boundingRect); +} + +QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode, QQuickWindow *window) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)) + if (!m_pendingFrameData) + return oldNode; + + DelegatedFrameNode *frameNode = static_cast<DelegatedFrameNode *>(oldNode); + if (!frameNode) + frameNode = new DelegatedFrameNode(window); + + frameNode->commit(m_pendingFrameData.get(), &m_resourcesToRelease); + m_pendingFrameData.reset(); + + // This is possibly called from the Qt render thread, post the ack back to the UI + // to tell the child compositors to release resources and trigger a new frame. + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&RenderWidgetHostViewQt::sendDelegatedFrameAck, AsWeakPtr())); + + return frameNode; +#else + return 0; +#endif // QT_VERSION +} + +void RenderWidgetHostViewQt::fetchBackingStore() +{ + m_backingStore = GetBackingStore(); +} + +void RenderWidgetHostViewQt::notifyResize() +{ + GetRenderWidgetHost()->WasResized(); +} + +bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) +{ + switch (event->type()) { + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + Focus(); // Fall through. + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + handleMouseEvent(static_cast<QMouseEvent*>(event)); + break; + case QEvent::KeyPress: + case QEvent::KeyRelease: + handleKeyEvent(static_cast<QKeyEvent*>(event)); + break; + case QEvent::Wheel: + handleWheelEvent(static_cast<QWheelEvent*>(event)); + break; + case QEvent::TouchBegin: + Focus(); // Fall through. + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + handleTouchEvent(static_cast<QTouchEvent*>(event)); + break; + case QEvent::HoverEnter: + case QEvent::HoverLeave: + case QEvent::HoverMove: + handleHoverEvent(static_cast<QHoverEvent*>(event)); + break; + case QEvent::FocusIn: + case QEvent::FocusOut: + handleFocusEvent(static_cast<QFocusEvent*>(event)); + break; + default: + return false; + } + return true; +} + +QVariant RenderWidgetHostViewQt::inputMethodQuery(Qt::InputMethodQuery query) const +{ + switch (query) { + case Qt::ImEnabled: + return QVariant(m_currentInputType != ui::TEXT_INPUT_TYPE_NONE); + case Qt::ImCursorRectangle: + return m_cursorRect; + case Qt::ImFont: + return QVariant(); + case Qt::ImCursorPosition: + return static_cast<uint>(m_cursorPositionWithinSelection); + case Qt::ImAnchorPosition: + return static_cast<uint>(m_anchorPositionWithinSelection); + case Qt::ImSurroundingText: + return toQt(selection_text_); + case Qt::ImCurrentSelection: + return toQt(GetSelectedText()); + case Qt::ImMaximumTextLength: + return QVariant(); // No limit. + case Qt::ImHints: + return int(toQtInputMethodHints(m_currentInputType)); + default: + return QVariant(); + } +} + +void RenderWidgetHostViewQt::compositingSurfaceUpdated() +{ + // Don't report an update until we get asked at least once. + if (m_readyForSurface) + m_host->CompositingSurfaceUpdated(); +} + +void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) { + ScopedVector<ui::TouchEvent> events; + if (!content::MakeUITouchEventsFromWebTouchEvents(touch, &events, content::LOCAL_COORDINATES)) + return; + + ui::EventResult result = (ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED; + for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(), end = events.end(); iter != end; ++iter) { + (*iter)->latency()->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACKED_COMPONENT, static_cast<int64>(ack_result), 0); + scoped_ptr<ui::GestureRecognizer::Gestures> gestures; + gestures.reset(m_gestureRecognizer->ProcessTouchEventForGesture(*(*iter), result, this)); + ProcessGestures(gestures.get()); + } +} + +void RenderWidgetHostViewQt::sendDelegatedFrameAck() +{ + cc::CompositorFrameAck ack; + ack.resources = m_resourcesToRelease; + content::RenderWidgetHostImpl::SendSwapCompositorFrameAck( + m_host->GetRoutingID(), m_pendingOutputSurfaceId, + m_host->GetProcess()->GetID(), ack); + + m_resourcesToRelease.clear(); +} + +void RenderWidgetHostViewQt::Paint(const gfx::Rect& damage_rect) +{ + QRect r(damage_rect.x(), damage_rect.y(), damage_rect.width(), damage_rect.height()); + m_delegate->update(r); +} + +void RenderWidgetHostViewQt::ProcessGestures(ui::GestureRecognizer::Gestures *gestures) +{ + if (!gestures || gestures->empty()) + return; + for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin(); g_it != gestures->end(); ++g_it) { + const ui::GestureEvent &uiGestureEvent = **g_it; + WebKit::WebGestureEvent webGestureEvent = content::MakeWebGestureEventFromUIEvent(uiGestureEvent); + if (webGestureEvent.type != WebKit::WebInputEvent::Undefined) { + webGestureEvent.x = uiGestureEvent.x(); + webGestureEvent.y = uiGestureEvent.y(); + m_host->ForwardGestureEvent(webGestureEvent); + } + } +} + +// Find (or create) a mapping to a 0-based ID. +int RenderWidgetHostViewQt::GetMappedTouch(int qtTouchId) +{ + QMap<int, int>::const_iterator it = m_touchIdMapping.find(qtTouchId); + if (it != m_touchIdMapping.end()) + return it.value(); + int nextValue = 0; + for (it = m_touchIdMapping.begin(); it != m_touchIdMapping.end(); ++it) + nextValue = std::max(nextValue, it.value() + 1); + m_touchIdMapping[qtTouchId] = nextValue; + return nextValue; +} + +void RenderWidgetHostViewQt::RemoveExpiredMappings(QTouchEvent *ev) +{ + QMap<int, int> newMap; + for (QMap<int, int>::const_iterator it = m_touchIdMapping.begin(); it != m_touchIdMapping.end(); ++it) { + Q_FOREACH (const QTouchEvent::TouchPoint& touchPoint, ev->touchPoints()) { + if ((touchPoint.id() == it.key()) && + (touchPoint.state() != Qt::TouchPointReleased)) { + newMap.insert(it.key(), it.value()); + break; + } + } + } + m_touchIdMapping.swap(newMap); +} + +bool RenderWidgetHostViewQt::IsPopup() const +{ + return popup_type_ != WebKit::WebPopupTypeNone; +} + +void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) +{ + int eventType = event->type(); + if (eventType == QEvent::MouseButtonDblClick) + return; + + WebKit::WebMouseEvent webEvent = WebEventFactory::toWebMouseEvent(event); + if (eventType == QMouseEvent::MouseButtonPress) { + if (event->button() != m_clickHelper.lastPressButton + || (event->timestamp() - m_clickHelper.lastPressTimestamp > static_cast<ulong>(qGuiApp->styleHints()->mouseDoubleClickInterval())) + || (event->pos() - m_clickHelper.lastPressPosition).manhattanLength() > qGuiApp->styleHints()->startDragDistance()) + m_clickHelper.clickCounter = 0; + + m_clickHelper.lastPressTimestamp = event->timestamp(); + webEvent.clickCount = ++m_clickHelper.clickCounter; + m_clickHelper.lastPressButton = event->button(); + m_clickHelper.lastPressPosition = QPointF(event->pos()).toPoint(); + } + + m_host->ForwardMouseEvent(webEvent); +} + +void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) +{ + m_host->ForwardKeyboardEvent(WebEventFactory::toWebKeyboardEvent(ev)); +} + +void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev) +{ + m_host->ForwardWheelEvent(WebEventFactory::toWebWheelEvent(ev)); +} + +void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) +{ + // Convert each of our QTouchEvent::TouchPoint to the simpler ui::TouchEvent to + // be able to use the same code path for both gesture recognition and WebTouchEvents. + // It's a waste to do a double QTouchEvent -> ui::TouchEvent -> WebKit::WebTouchEvent + // conversion but this should hopefully avoid a few bugs in the future. + // FIXME: Carry Qt::TouchCancel from the event to each TouchPoint. + base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(ev->timestamp()); + Q_FOREACH (const QTouchEvent::TouchPoint& touchPoint, ev->touchPoints()) { + // Stationary touch points are already in our accumulator. + if (touchPoint.state() == Qt::TouchPointStationary) + continue; + + ui::TouchEvent uiEvent( + toUIEventType(touchPoint.state()), + toGfxPoint(touchPoint.pos().toPoint()), + 0, // flags + GetMappedTouch(touchPoint.id()), + timestamp, + 0, 0, // radius + 0, // angle + touchPoint.pressure()); + + WebKit::WebTouchPoint *point = content::UpdateWebTouchEventFromUIEvent(uiEvent, &m_accumTouchEvent); + if (point) { + if (m_host->ShouldForwardTouchEvent()) + // This will come back through ProcessAckedTouchEvent if the page didn't want it. + m_host->ForwardTouchEventWithLatencyInfo(m_accumTouchEvent, ui::LatencyInfo()); + else { + scoped_ptr<ui::GestureRecognizer::Gestures> gestures; + gestures.reset(m_gestureRecognizer->ProcessTouchEventForGesture(uiEvent, ui::ER_UNHANDLED, this)); + ProcessGestures(gestures.get()); + } + UpdateWebTouchEventAfterDispatch(&m_accumTouchEvent, point); + } + } + RemoveExpiredMappings(ev); +} + +void RenderWidgetHostViewQt::handleHoverEvent(QHoverEvent *ev) +{ + m_host->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(ev)); +} + +void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) +{ + if (ev->gotFocus()) { + m_host->GotFocus(); + m_host->SetActive(true); + ev->accept(); + } else if (ev->lostFocus()) { + m_host->SetActive(false); + m_host->Blur(); + ev->accept(); + } +} diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h new file mode 100644 index 000000000..c0905ffeb --- /dev/null +++ b/src/core/render_widget_host_view_qt.h @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef RENDER_WIDGET_HOST_VIEW_QT_H +#define RENDER_WIDGET_HOST_VIEW_QT_H + +#include "render_widget_host_view_qt_delegate.h" + +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "cc/resources/transferable_resource.h" +#include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "ui/base/gestures/gesture_recognizer.h" +#include "ui/base/gestures/gesture_types.h" +#include <QMap> +#include <QPoint> +#include <QRect> +#include <QtGlobal> + +class BackingStoreQt; + +QT_BEGIN_NAMESPACE +class QEvent; +class QFocusEvent; +class QHoverEvent; +class QKeyEvent; +class QMouseEvent; +class QTouchEvent; +class QVariant; +class QWheelEvent; +QT_END_NAMESPACE + +class WebContentsAdapterClient; + +struct MultipleMouseClickHelper +{ + QPoint lastPressPosition; + Qt::MouseButton lastPressButton; + int clickCounter; + ulong lastPressTimestamp; + + MultipleMouseClickHelper() + : lastPressPosition(QPoint()) + , lastPressButton(Qt::NoButton) + , clickCounter(0) + , lastPressTimestamp(0) + { + } +}; + +class RenderWidgetHostViewQt + : public content::RenderWidgetHostViewBase + , public ui::GestureConsumer + , public ui::GestureEventHelper + , public RenderWidgetHostViewQtDelegateClient + , public base::SupportsWeakPtr<RenderWidgetHostViewQt> +{ +public: + RenderWidgetHostViewQt(content::RenderWidgetHost* widget); + ~RenderWidgetHostViewQt(); + + void setDelegate(RenderWidgetHostViewQtDelegate *delegate); + void setAdapterClient(WebContentsAdapterClient *adapterClient); + BackingStoreQt* GetBackingStore(); + + virtual content::BackingStore *AllocBackingStore(const gfx::Size &size) Q_DECL_OVERRIDE; + + virtual void InitAsChild(gfx::NativeView) Q_DECL_OVERRIDE; + virtual void InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect&) Q_DECL_OVERRIDE; + virtual void InitAsFullscreen(content::RenderWidgetHostView*) Q_DECL_OVERRIDE; + virtual content::RenderWidgetHost* GetRenderWidgetHost() const Q_DECL_OVERRIDE; + virtual void SetSize(const gfx::Size& size) Q_DECL_OVERRIDE; + virtual void SetBounds(const gfx::Rect& rect) Q_DECL_OVERRIDE; + virtual gfx::Size GetPhysicalBackingSize() const Q_DECL_OVERRIDE; + virtual gfx::NativeView GetNativeView() const Q_DECL_OVERRIDE; + virtual gfx::NativeViewId GetNativeViewId() const Q_DECL_OVERRIDE; + virtual gfx::NativeViewAccessible GetNativeViewAccessible() Q_DECL_OVERRIDE; + virtual void Focus() Q_DECL_OVERRIDE; + virtual bool HasFocus() const Q_DECL_OVERRIDE; + virtual bool IsSurfaceAvailableForCopy() const Q_DECL_OVERRIDE; + virtual void Show() Q_DECL_OVERRIDE; + virtual void Hide() Q_DECL_OVERRIDE; + virtual bool IsShowing() Q_DECL_OVERRIDE; + virtual gfx::Rect GetViewBounds() const Q_DECL_OVERRIDE; + virtual void SetBackground(const SkBitmap& background) Q_DECL_OVERRIDE; + virtual bool LockMouse() Q_DECL_OVERRIDE; + virtual void UnlockMouse() Q_DECL_OVERRIDE; +#if defined(TOOLKIT_GTK) + virtual GdkEventButton* GetLastMouseDown() Q_DECL_OVERRIDE; + virtual gfx::NativeView BuildInputMethodsGtkMenu() Q_DECL_OVERRIDE; +#endif // defined(TOOLKIT_GTK) + virtual void WasShown() Q_DECL_OVERRIDE; + virtual void WasHidden() Q_DECL_OVERRIDE; + virtual void MovePluginWindows(const gfx::Vector2d&, const std::vector<content::WebPluginGeometry>&) Q_DECL_OVERRIDE; + virtual void Blur() Q_DECL_OVERRIDE; + virtual void UpdateCursor(const WebCursor&) Q_DECL_OVERRIDE; + virtual void SetIsLoading(bool) Q_DECL_OVERRIDE; + virtual void TextInputTypeChanged(ui::TextInputType, bool, ui::TextInputMode) Q_DECL_OVERRIDE; + virtual void ImeCancelComposition() Q_DECL_OVERRIDE; + virtual void ImeCompositionRangeChanged(const ui::Range&, const std::vector<gfx::Rect>&) Q_DECL_OVERRIDE; + virtual void DidUpdateBackingStore(const gfx::Rect& scroll_rect, const gfx::Vector2d& scroll_delta, const std::vector<gfx::Rect>& copy_rects, const ui::LatencyInfo&) Q_DECL_OVERRIDE; + virtual void RenderProcessGone(base::TerminationStatus, int) Q_DECL_OVERRIDE; + virtual void Destroy() Q_DECL_OVERRIDE; + virtual void SetTooltipText(const string16&) Q_DECL_OVERRIDE; + virtual void SelectionBoundsChanged(const ViewHostMsg_SelectionBounds_Params&) Q_DECL_OVERRIDE; + virtual void ScrollOffsetChanged() Q_DECL_OVERRIDE; + virtual void CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& /* dst_size */, const base::Callback<void(bool, const SkBitmap&)>& callback) Q_DECL_OVERRIDE; + virtual void CopyFromCompositingSurfaceToVideoFrame(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(bool)>& callback) Q_DECL_OVERRIDE; + virtual bool CanCopyToVideoFrame() const Q_DECL_OVERRIDE; + virtual void OnAcceleratedCompositingStateChange() Q_DECL_OVERRIDE; + virtual void AcceleratedSurfaceBuffersSwapped(const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, int gpu_host_id) Q_DECL_OVERRIDE; + virtual void AcceleratedSurfacePostSubBuffer(const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, int gpu_host_id) Q_DECL_OVERRIDE; + virtual void AcceleratedSurfaceSuspend() Q_DECL_OVERRIDE; + virtual void AcceleratedSurfaceRelease() Q_DECL_OVERRIDE; + virtual bool HasAcceleratedSurface(const gfx::Size&) Q_DECL_OVERRIDE; + virtual void OnSwapCompositorFrame(uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) Q_DECL_OVERRIDE; + virtual void GetScreenInfo(WebKit::WebScreenInfo* results) Q_DECL_OVERRIDE; + virtual gfx::Rect GetBoundsInRootWindow() Q_DECL_OVERRIDE; + virtual gfx::GLSurfaceHandle GetCompositingSurface() Q_DECL_OVERRIDE; + virtual void SetHasHorizontalScrollbar(bool) Q_DECL_OVERRIDE; + virtual void SetScrollOffsetPinning(bool, bool) Q_DECL_OVERRIDE; + virtual void OnAccessibilityNotifications(const std::vector<AccessibilityHostMsg_NotificationParams>&) Q_DECL_OVERRIDE; + virtual void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) Q_DECL_OVERRIDE; + + // Overridden from ui::GestureEventHelper. + virtual bool DispatchLongPressGestureEvent(ui::GestureEvent *event) Q_DECL_OVERRIDE; + virtual bool DispatchCancelTouchEvent(ui::TouchEvent *event) Q_DECL_OVERRIDE; + + // Overridden from RenderWidgetHostViewQtDelegateClient. + virtual void paint(QPainter *, const QRectF& boundingRect) Q_DECL_OVERRIDE; + virtual QSGNode *updatePaintNode(QSGNode *, QQuickWindow *) Q_DECL_OVERRIDE; + virtual void fetchBackingStore() Q_DECL_OVERRIDE; + virtual void notifyResize() Q_DECL_OVERRIDE; + virtual bool forwardEvent(QEvent *) Q_DECL_OVERRIDE; + virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const Q_DECL_OVERRIDE; + virtual void compositingSurfaceUpdated() Q_DECL_OVERRIDE; + + void handleMouseEvent(QMouseEvent*); + void handleKeyEvent(QKeyEvent*); + void handleWheelEvent(QWheelEvent*); + void handleTouchEvent(QTouchEvent*); + void handleHoverEvent(QHoverEvent*); + void handleFocusEvent(QFocusEvent*); + +#if defined(OS_MACOSX) + virtual void SetTakesFocusOnlyOnMouseDown(bool flag) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual void SetActive(bool active) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual bool IsSpeaking() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED; return false; } + virtual void SpeakSelection() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual bool PostProcessEventForPluginIme(const content::NativeWebKeyboardEvent& event) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED; return false; } + virtual void AboutToWaitForBackingStoreMsg() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual void StopSpeaking() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual void SetWindowVisibility(bool visible) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual bool SupportsSpeech() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED; return false; } + virtual void ShowDefinitionForSelection() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual void WindowFrameChanged() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } +#endif // defined(OS_MACOSX) + +#if defined(OS_ANDROID) + virtual void ShowDisambiguationPopup(const gfx::Rect&, const SkBitmap&) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual void HasTouchEventHandlers(bool) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } +#endif // defined(OS_ANDROID) + +private: + void sendDelegatedFrameAck(); + void Paint(const gfx::Rect& damage_rect); + void ProcessGestures(ui::GestureRecognizer::Gestures *gestures); + int GetMappedTouch(int qtTouchId); + void RemoveExpiredMappings(QTouchEvent *ev); + + bool IsPopup() const; + + content::RenderWidgetHostImpl *m_host; + scoped_ptr<ui::GestureRecognizer> m_gestureRecognizer; + QMap<int, int> m_touchIdMapping; + WebKit::WebTouchEvent m_accumTouchEvent; + scoped_ptr<RenderWidgetHostViewQtDelegate> m_delegate; + + BackingStoreQt *m_backingStore; + scoped_ptr<cc::DelegatedFrameData> m_pendingFrameData; + cc::TransferableResourceArray m_resourcesToRelease; + uint32 m_pendingOutputSurfaceId; + + WebContentsAdapterClient *m_adapterClient; + MultipleMouseClickHelper m_clickHelper; + + ui::TextInputType m_currentInputType; + QRect m_cursorRect; + size_t m_anchorPositionWithinSelection; + size_t m_cursorPositionWithinSelection; + + bool m_initPending; + bool m_readyForSurface; +}; + +#endif // RENDER_WIDGET_HOST_VIEW_QT_H diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h new file mode 100644 index 000000000..74151fdbf --- /dev/null +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_H +#define RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_H + +#include "qtwebenginecoreglobal.h" + +#include <QRect> +#include <QtGui/qwindowdefs.h> + +QT_BEGIN_NAMESPACE +class QCursor; +class QEvent; +class QPainter; +class QQuickWindow; +class QSGNode; +class QVariant; +class QWindow; +QT_END_NAMESPACE + +class WebContentsAdapterClient; + +class QWEBENGINE_EXPORT RenderWidgetHostViewQtDelegateClient { +public: + virtual ~RenderWidgetHostViewQtDelegateClient() { } + virtual void paint(QPainter *, const QRectF& boundingRect) = 0; + virtual QSGNode *updatePaintNode(QSGNode *, QQuickWindow *) = 0; + virtual void fetchBackingStore() = 0; + virtual void notifyResize() = 0; + virtual bool forwardEvent(QEvent *) = 0; + virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const = 0; + virtual void compositingSurfaceUpdated() = 0; +}; + +class QWEBENGINE_EXPORT RenderWidgetHostViewQtDelegate { +public: + virtual ~RenderWidgetHostViewQtDelegate() { } + virtual void initAsChild(WebContentsAdapterClient*) = 0; + virtual void initAsPopup(const QRect&) = 0; + virtual QRectF screenRect() const = 0; + virtual void setKeyboardFocus() = 0; + virtual bool hasKeyboardFocus() = 0; + virtual void show() = 0; + virtual void hide() = 0; + virtual bool isVisible() const = 0; + virtual WId nativeWindowIdForCompositor() const = 0; + virtual QWindow* window() const = 0; + virtual void update(const QRect& rect = QRect()) = 0; + virtual void updateCursor(const QCursor &) = 0; + virtual void resize(int width, int height) = 0; + virtual void inputMethodStateChanged(bool editorVisible) = 0; +}; + +#endif // RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_H diff --git a/src/core/resource_bundle_qt.cpp b/src/core/resource_bundle_qt.cpp new file mode 100644 index 000000000..044d00511 --- /dev/null +++ b/src/core/resource_bundle_qt.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/resource/data_pack.h" + +#include <QFile> +#include <QStringList> + +namespace ui { + +// ********************* data_pack.cc ********************* +// This is duplicated code originating from data_pack.cc. +// It should instead be moved to a header file and be included +// in both places. + +static const uint32 kFileFormatVersion = 4; +static const size_t kHeaderLength = 2 * sizeof(uint32) + sizeof(uint8); + +#pragma pack(push,2) +struct DataPackEntry { + uint16 resource_id; + uint32 file_offset; + + static int CompareById(const void* void_key, const void* void_entry) { + uint16 key = *reinterpret_cast<const uint16*>(void_key); + const DataPackEntry* entry = + reinterpret_cast<const DataPackEntry*>(void_entry); + if (key < entry->resource_id) { + return -1; + } else if (key > entry->resource_id) { + return 1; + } else { + return 0; + } + } +}; +#pragma pack(pop) +// ******************* data_pack.cc end ******************* + +class UI_EXPORT DataPackQt : public DataPack { + public: + DataPackQt(ui::ScaleFactor scale_factor) + : DataPack(scale_factor) + , m_data(NULL) + , m_resourceCount(0) { } + + virtual ~DataPackQt() { } + + bool LoadFromByteArray(const QByteArray& data) + { + m_data = data; + + if (kHeaderLength > static_cast<size_t>(m_data.size())) + return false; + + const uint32* ptr = reinterpret_cast<const uint32*>(m_data.data()); + uint32 version = ptr[0]; + if (version != kFileFormatVersion) { + LOG(ERROR) << "Bad data pack version: got " << version << ", expected " << kFileFormatVersion; + return false; + } + + m_resourceCount = ptr[1]; + return true; + } + + virtual bool HasResource(uint16 resource_id) const OVERRIDE + { + return !!bsearch(&resource_id, m_data.data() + kHeaderLength, m_resourceCount, sizeof(DataPackEntry), DataPackEntry::CompareById); + } + + virtual bool GetStringPiece(uint16 resource_id, base::StringPiece* data) const OVERRIDE + { + #if defined(__BYTE_ORDER) // Linux check + COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, datapack_assumes_little_endian); + #elif defined(__BIG_ENDIAN__) // Mac check + #error DataPack assumes little endian + #endif + + const DataPackEntry* target = reinterpret_cast<const DataPackEntry*>(bsearch(&resource_id, m_data.data() + kHeaderLength, m_resourceCount, sizeof(DataPackEntry), DataPackEntry::CompareById)); + if (!target) + return false; + + const DataPackEntry* next_entry = target + 1; + size_t length = next_entry->file_offset - target->file_offset; + + data->set(m_data.data() + target->file_offset, length); + return true; + } + + private: + QByteArray m_data; + size_t m_resourceCount; + DISALLOW_COPY_AND_ASSIGN(DataPackQt); +}; + + +void ResourceBundle::LoadCommonResources() +{ + QStringList resources; + resources << ":/data/resources.pak" << ":/data/devtools.pak"; + Q_FOREACH (const QString& pak, resources) { + QFile pak_file(pak); + if (!pak_file.open(QIODevice::ReadOnly)) { + qWarning("Resource file %s not loaded", qPrintable(pak)); + continue; + } + + scoped_ptr<DataPackQt> data_pack(new DataPackQt(SCALE_FACTOR_100P)); + if (data_pack->LoadFromByteArray(pak_file.readAll())) + AddDataPack(data_pack.release()); + } +} + +// As GetLocaleFilePath is excluded for Mac in resource_bundle.cc, +// we have to add a replacement for it using the inverted logic. +#if defined(OS_MACOSX) +base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& /*app_locale*/, bool /*test_file_exists*/) +{ + return base::FilePath(); +} +#endif + +gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) +{ + LOG(WARNING) << "Unable to load image with id " << resource_id; + NOTREACHED(); // Want to assert in debug mode. + return GetEmptyImage(); +} + +} // namespace ui diff --git a/src/core/resource_context_qt.cpp b/src/core/resource_context_qt.cpp new file mode 100644 index 000000000..ae5b989f0 --- /dev/null +++ b/src/core/resource_context_qt.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "resource_context_qt.h" + +#include "net/url_request/url_request_context_getter.h" + +#include "browser_context_qt.h" + +net::HostResolver *ResourceContextQt::GetHostResolver() +{ + CHECK(getter_); + return getter_->GetURLRequestContext()->host_resolver(); +} + +net::URLRequestContext* ResourceContextQt::GetRequestContext() +{ + if (getter_) + return getter_->GetURLRequestContext(); + return context->GetRequestContext()->GetURLRequestContext(); +} + +void ResourceContextQt::set_url_request_context_getter(net::URLRequestContextGetter *getter) +{ + getter_ = getter; +} diff --git a/src/core/resource_context_qt.h b/src/core/resource_context_qt.h new file mode 100644 index 000000000..cd01b8aee --- /dev/null +++ b/src/core/resource_context_qt.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef RESOURCE_CONTEXT_QT_H +#define RESOURCE_CONTEXT_QT_H + +#include "content/public/browser/resource_context.h" + +#include "qglobal.h" + +namespace net { +class URLRequestContextGetter; +} + +class BrowserContextQt; +class GURL; + +class ResourceContextQt : public content::ResourceContext +{ +public: + ResourceContextQt(BrowserContextQt *ctx) + : context(ctx) + , getter_(0) + {} + + virtual net::HostResolver* GetHostResolver() Q_DECL_OVERRIDE; + + virtual net::URLRequestContext* GetRequestContext() Q_DECL_OVERRIDE; + + virtual bool AllowMicAccess(const GURL& origin) Q_DECL_OVERRIDE { return false; } + virtual bool AllowCameraAccess(const GURL& origin) Q_DECL_OVERRIDE { return false; } + + void set_url_request_context_getter(net::URLRequestContextGetter* getter); + +private: + BrowserContextQt *context; + net::URLRequestContextGetter* getter_; + + DISALLOW_COPY_AND_ASSIGN(ResourceContextQt); +}; + +#endif // RESOURCE_CONTEXT_QT_H diff --git a/src/core/resources/devtools_discovery_page.html b/src/core/resources/devtools_discovery_page.html new file mode 100644 index 000000000..de848d348 --- /dev/null +++ b/src/core/resources/devtools_discovery_page.html @@ -0,0 +1,57 @@ +<!-- +Copyright (c) 2013 BlackBerry Limited. All rights reserved. +--> +<html> +<head> +<title>Content shell remote debugging</title> +<style> +</style> + +<script> +function onLoad() { + var tabs_list_request = new XMLHttpRequest(); + tabs_list_request.open('GET', '/json/list?t=' + new Date().getTime(), true); + tabs_list_request.onreadystatechange = onReady; + tabs_list_request.send(); +} + +function onReady() { + if(this.readyState == 4 && this.status == 200) { + if(this.response != null) + var responseJSON = JSON.parse(this.response); + for (var i = 0; i < responseJSON.length; ++i) + appendItem(responseJSON[i]); + } +} + +function appendItem(item_object) { + var frontend_ref; + if (item_object.devtoolsFrontendUrl) { + frontend_ref = document.createElement('a'); + frontend_ref.href = item_object.devtoolsFrontendUrl; + frontend_ref.title = item_object.title; + } else { + frontend_ref = document.createElement('div'); + frontend_ref.title = 'The tab already has active debugging session'; + } + + var text = document.createElement('div'); + if (item_object.title) + text.innerText = item_object.title; + else + text.innerText = '(untitled tab)'; + text.style.cssText = 'background-image:url(' + item_object.faviconUrl + ')'; + frontend_ref.appendChild(text); + + var item = document.createElement('p'); + item.appendChild(frontend_ref); + + document.getElementById('items').appendChild(item); +} +</script> +</head> +<body onload='onLoad()'> + <div id='caption'>Inspectable WebContents</div> + <div id='items'></div> +</body> +</html> diff --git a/src/core/resources/resources.pro b/src/core/resources/resources.pro new file mode 100644 index 000000000..a9404f3ec --- /dev/null +++ b/src/core/resources/resources.pro @@ -0,0 +1,7 @@ +# This is a dummy .pro file used to prepare chromium .pak resource files. +# These files will then be bundled using the Qt Resource System. +TEMPLATE = aux + +system(python ../build/scripts/build_resources.py) + + diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h new file mode 100644 index 000000000..0f0a8ab60 --- /dev/null +++ b/src/core/type_conversion.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TYPE_CONVERSION_H +#define TYPE_CONVERSION_H + +#include <QColor> +#include <QMatrix4x4> +#include <QRect> +#include <QString> +#include <QUrl> +#include "base/files/file_path.h" +#include "third_party/skia/include/utils/SkMatrix44.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/rect.h" +#include "url/gurl.h" + +inline QString toQt(const base::string16 &string) +{ + return QString::fromUtf16(string.data()); +} + +inline QString toQt(const std::string &string) +{ + return QString::fromStdString(string); +} + +inline base::string16 toString16(const QString &qString) +{ + return base::string16(qString.utf16()); +} + +inline QUrl toQt(const GURL &url) +{ + return QUrl(QString::fromStdString(url.spec())); +} + +inline GURL toGurl(const QUrl& url) +{ + return GURL(url.toString().toStdString()); +} + +inline QRect toQt(const gfx::Rect &rect) +{ + return QRect(rect.x(), rect.y(), rect.width(), rect.height()); +} + +inline QRectF toQt(const gfx::RectF &rect) +{ + return QRectF(rect.x(), rect.y(), rect.width(), rect.height()); +} + +inline QSize toQt(const gfx::Size &size) +{ + return QSize(size.width(), size.height()); +} + +inline QSizeF toQt(const gfx::SizeF &size) +{ + return QSizeF(size.width(), size.height()); +} + +inline QColor toQt(const SkColor &c) +{ + return QColor(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c), SkColorGetA(c)); +} + +inline QMatrix4x4 toQt(const SkMatrix44 &m) +{ + return QMatrix4x4( + m.get(0, 0), m.get(0, 1), m.get(0, 2), m.get(0, 3), + m.get(1, 0), m.get(1, 1), m.get(1, 2), m.get(1, 3), + m.get(2, 0), m.get(2, 1), m.get(2, 2), m.get(2, 3), + m.get(3, 0), m.get(3, 1), m.get(3, 2), m.get(3, 3)); +} + +inline base::FilePath::StringType toFilePathString(const QString &str) +{ +#if defined(OS_POSIX) + return str.toStdString(); +#elif defined(OS_WIN) + return str.toStdWString(); +#endif +} + +#endif // TYPE_CONVERSION_H diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp new file mode 100644 index 000000000..99bf68b1c --- /dev/null +++ b/src/core/url_request_context_getter_qt.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "url_request_context_getter_qt.h" + +#include "base/strings/string_util.h" +#include "base/threading/worker_pool.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/cookie_store_factory.h" +#include "net/base/cache_type.h" +#include "net/cert/cert_verifier.h" +#include "net/dns/host_resolver.h" +#include "net/dns/mapped_host_resolver.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_session.h" +#include "net/http/http_server_properties_impl.h" +#include "net/proxy/proxy_service.h" +#include "net/ssl/default_server_bound_cert_store.h" +#include "net/ssl/server_bound_cert_service.h" +#include "net/ssl/ssl_config_service_defaults.h" +#include "net/url_request/static_http_user_agent_settings.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/data_protocol_handler.h" +#include "net/url_request/file_protocol_handler.h" + +#include "network_delegate_qt.h" + +using content::BrowserThread; + +URLRequestContextGetterQt::URLRequestContextGetterQt(const base::FilePath &basePath) + : m_ignoreCertificateErrors(false) + , m_basePath(basePath) +{ + + // We must create the proxy config service on the UI loop on Linux because it + // must synchronously run on the glib message loop. This will be passed to + // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). +//#ifdef Q_OS_LINUX + m_proxyConfigService.reset(net::ProxyService::CreateSystemProxyConfigService(BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)->message_loop_proxy() + , BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE))); +//#endif +} + +net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() +{ + if (!m_urlRequestContext) { + + m_urlRequestContext.reset(new net::URLRequestContext()); + m_networkDelegate.reset(new NetworkDelegateQt); + + m_urlRequestContext->set_network_delegate(m_networkDelegate.get()); + + base::FilePath cookiesPath = m_basePath.Append(FILE_PATH_LITERAL("Cookies")); + scoped_refptr<net::CookieStore> cookieStore = content::CreatePersistentCookieStore(cookiesPath, true, NULL, NULL); + cookieStore->GetCookieMonster()->SetPersistSessionCookies(true); + + m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); + m_storage->set_cookie_store(cookieStore.get()); + m_storage->set_server_bound_cert_service(new net::ServerBoundCertService( + new net::DefaultServerBoundCertStore(NULL), + base::WorkerPool::GetTaskRunner(true))); + m_storage->set_http_user_agent_settings( + new net::StaticHttpUserAgentSettings("en-us,en", EmptyString())); + + scoped_ptr<net::HostResolver> host_resolver( + net::HostResolver::CreateDefaultResolver(NULL)); + + m_storage->set_cert_verifier(net::CertVerifier::CreateDefault()); + + m_storage->set_proxy_service(net::ProxyService::CreateUsingSystemProxyResolver(m_proxyConfigService.release(), 0, NULL)); + + m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); + m_storage->set_transport_security_state(new net::TransportSecurityState()); + + m_storage->set_http_auth_handler_factory( + net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); + m_storage->set_http_server_properties(scoped_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl)); + + base::FilePath cache_path = m_basePath.Append(FILE_PATH_LITERAL("Cache")); + net::HttpCache::DefaultBackend* main_backend = + new net::HttpCache::DefaultBackend( + net::DISK_CACHE, + net::CACHE_BACKEND_DEFAULT, + cache_path, + 0, + BrowserThread::GetMessageLoopProxyForThread( + BrowserThread::CACHE)); + + net::HttpNetworkSession::Params network_session_params; + network_session_params.transport_security_state = + m_urlRequestContext->transport_security_state(); + network_session_params.cert_verifier = + m_urlRequestContext->cert_verifier(); + network_session_params.server_bound_cert_service = + m_urlRequestContext->server_bound_cert_service(); + network_session_params.proxy_service = + m_urlRequestContext->proxy_service(); + network_session_params.ssl_config_service = + m_urlRequestContext->ssl_config_service(); + network_session_params.http_auth_handler_factory = + m_urlRequestContext->http_auth_handler_factory(); + network_session_params.network_delegate = + m_networkDelegate.get(); + network_session_params.http_server_properties = + m_urlRequestContext->http_server_properties(); + network_session_params.ignore_certificate_errors = + m_ignoreCertificateErrors; + + // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|. + m_storage->set_host_resolver(host_resolver.Pass()); + network_session_params.host_resolver = + m_urlRequestContext->host_resolver(); + + net::HttpCache* main_cache = new net::HttpCache( + network_session_params, main_backend); + m_storage->set_http_transaction_factory(main_cache); + + // FIXME: add protocol handling + + m_jobFactory.reset(new net::URLRequestJobFactoryImpl()); + m_jobFactory->SetProtocolHandler(chrome::kDataScheme, new net::DataProtocolHandler()); + m_jobFactory->SetProtocolHandler(chrome::kFileScheme, new net::FileProtocolHandler()); + m_urlRequestContext->set_job_factory(m_jobFactory.get()); + } + + return m_urlRequestContext.get(); +} + + +scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const +{ + return content::BrowserThread::GetMessageLoopProxyForThread(content::BrowserThread::IO); +} diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h new file mode 100644 index 000000000..ca56cb38e --- /dev/null +++ b/src/core/url_request_context_getter_qt.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef URL_REQUEST_CONTEXT_GETTER_QT_H +#define URL_REQUEST_CONTEXT_GETTER_QT_H + +#include "net/url_request/url_request_context_getter.h" + +#include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "base/single_thread_task_runner.h" +#include "net/url_request/url_request_context_storage.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "content/public/common/url_constants.h" + +#include "qglobal.h" + +namespace net { +class HostResolver; +class MappedHostResolver; +class NetworkDelegate; +class ProxyConfigService; +} + +class URLRequestContextGetterQt : public net::URLRequestContextGetter { +public: + explicit URLRequestContextGetterQt(const base::FilePath&); + + virtual net::URLRequestContext* GetURLRequestContext() Q_DECL_OVERRIDE; + + virtual scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const Q_DECL_OVERRIDE; + +private: + virtual ~URLRequestContextGetterQt() {} + + bool m_ignoreCertificateErrors; + base::FilePath m_basePath; + + scoped_ptr<net::ProxyConfigService> m_proxyConfigService; + scoped_ptr<net::URLRequestContext> m_urlRequestContext; + scoped_ptr<net::NetworkDelegate> m_networkDelegate; + scoped_ptr<net::URLRequestContextStorage> m_storage; + scoped_ptr<net::URLRequestJobFactoryImpl> m_jobFactory; +}; + +#endif // URL_REQUEST_CONTEXT_GETTER_QT_H diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp new file mode 100644 index 000000000..c09fc362a --- /dev/null +++ b/src/core/web_contents_adapter.cpp @@ -0,0 +1,346 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "web_contents_adapter.h" + +#include "content_browser_client_qt.h" +#include "browser_context_qt.h" +#include "type_conversion.h" +#include "web_contents_adapter_client.h" +#include "web_contents_delegate_qt.h" +#include "web_contents_view_qt.h" +#include "web_engine_context.h" + +#include "base/values.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/page_zoom.h" +#include "content/public/common/renderer_preferences.h" + +#include <QGuiApplication> +#include <QStyleHints> +#include <QVariant> + +static const int kTestWindowWidth = 800; +static const int kTestWindowHeight = 600; + +static QVariant fromJSValue(const base::Value *result) +{ + QVariant ret; + switch (result->GetType()) { + case base::Value::TYPE_NULL: + break; + case base::Value::TYPE_BOOLEAN: + { + bool out; + if (result->GetAsBoolean(&out)) + ret.setValue(out); + break; + } + case base::Value::TYPE_INTEGER: + { + int out; + if (result->GetAsInteger(&out)) + ret.setValue(out); + break; + } + case base::Value::TYPE_DOUBLE: + { + double out; + if (result->GetAsDouble(&out)) + ret.setValue(out); + break; + } + case base::Value::TYPE_STRING: + { + base::string16 out; + if (result->GetAsString(&out)) + ret.setValue(toQt(out)); + break; + } + case base::Value::TYPE_LIST: + { + const base::ListValue *out; + if (result->GetAsList(&out)) { + QVariantList list; + list.reserve(out->GetSize()); + for (size_t i = 0; i < out->GetSize(); ++i) { + const base::Value *outVal = 0; + if (out->Get(i, &outVal) && outVal) + list.insert(i, fromJSValue(outVal)); + } + ret.setValue(list); + } + break; + } + case base::Value::TYPE_DICTIONARY: + { + const base::DictionaryValue *out; + if (result->GetAsDictionary(&out)) { + QVariantMap map; + base::DictionaryValue::Iterator it(*out); + while (!it.IsAtEnd()) { + map.insert(toQt(it.key()), fromJSValue(&it.value())); + it.Advance(); + } + ret.setValue(map); + } + break; + } + case base::Value::TYPE_BINARY: + { + const base::BinaryValue *out = static_cast<const base::BinaryValue*>(result); + QByteArray data(out->GetBuffer(), out->GetSize()); + ret.setValue(data); + break; + } + default: + Q_UNREACHABLE(); + break; + } + return ret; +} + +static void callbackOnEvaluateJS(JSCallbackBase *callback, const base::Value *result) +{ + callback->call(fromJSValue(result)); + delete callback; +} + +class WebContentsAdapterPrivate { +public: + WebContentsAdapterPrivate(WebContentsAdapterClient::RenderingMode renderingMode); + scoped_refptr<WebEngineContext> engineContext; + scoped_ptr<content::WebContents> webContents; + scoped_ptr<WebContentsDelegateQt> webContentsDelegate; + WebContentsAdapterClient *adapterClient; +}; + +WebContentsAdapterPrivate::WebContentsAdapterPrivate(WebContentsAdapterClient::RenderingMode renderingMode) + // This has to be the first thing we create, and the last we destroy. + : engineContext(WebEngineContext::currentOrCreate(renderingMode)) +{ +} + +WebContentsAdapter::WebContentsAdapter(WebContentsAdapterClient::RenderingMode renderingMode, content::WebContents *webContents) + : d_ptr(new WebContentsAdapterPrivate(renderingMode)) +{ + Q_D(WebContentsAdapter); + d->webContents.reset(webContents); +} + +WebContentsAdapter::~WebContentsAdapter() +{ +} + +void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) +{ + Q_D(WebContentsAdapter); + d->adapterClient = adapterClient; + + // Create our own if a WebContents wasn't provided at construction. + if (!d->webContents) { + content::BrowserContext* browserContext = ContentBrowserClientQt::Get()->browser_context(); + content::WebContents::CreateParams create_params(browserContext, NULL); + create_params.routing_id = MSG_ROUTING_NONE; + create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight); + create_params.context = reinterpret_cast<gfx::NativeView>(adapterClient); + d->webContents.reset(content::WebContents::Create(create_params)); + } + + content::RendererPreferences* rendererPrefs = d->webContents->GetMutableRendererPrefs(); + rendererPrefs->use_custom_colors = true; + // Qt returns a flash time (the whole cycle) in ms, chromium expects just the interval in seconds + const int qtCursorFlashTime = QGuiApplication::styleHints()->cursorFlashTime(); + rendererPrefs->caret_blink_interval = 0.5 * static_cast<double>(qtCursorFlashTime) / 1000; + d->webContents->GetRenderViewHost()->SyncRendererPrefs(); + + // Create and attach a WebContentsDelegateQt to the WebContents. + d->webContentsDelegate.reset(new WebContentsDelegateQt(d->webContents.get(), adapterClient)); + + // Let the WebContent's view know about the WebContentsAdapterClient. + WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(d->webContents->GetView()); + contentsView->initialize(adapterClient); +} + +bool WebContentsAdapter::canGoBack() const +{ + Q_D(const WebContentsAdapter); + return d->webContents->GetController().CanGoBack(); +} + +bool WebContentsAdapter::canGoForward() const +{ + Q_D(const WebContentsAdapter); + return d->webContents->GetController().CanGoForward(); +} + +bool WebContentsAdapter::isLoading() const +{ + Q_D(const WebContentsAdapter); + return d->webContents->IsLoading(); +} + +void WebContentsAdapter::stop() +{ + Q_D(WebContentsAdapter); + content::NavigationController& controller = d->webContents->GetController(); + + int index = controller.GetPendingEntryIndex(); + if (index != -1) + controller.RemoveEntryAtIndex(index); + + d->webContents->GetView()->Focus(); +} + +void WebContentsAdapter::reload() +{ + Q_D(WebContentsAdapter); + d->webContents->GetController().Reload(/*checkRepost = */false); + d->webContents->GetView()->Focus(); +} + +void WebContentsAdapter::load(const QUrl &url) +{ + Q_D(WebContentsAdapter); + content::NavigationController::LoadURLParams params(toGurl(url)); + params.transition_type = content::PageTransitionFromInt(content::PAGE_TRANSITION_TYPED | content::PAGE_TRANSITION_FROM_ADDRESS_BAR); + d->webContents->GetController().LoadURLWithParams(params); + d->webContents->GetView()->Focus(); +} + +QUrl WebContentsAdapter::activeUrl() const +{ + Q_D(const WebContentsAdapter); + return toQt(d->webContents->GetVisibleURL()); +} + +QString WebContentsAdapter::pageTitle() const +{ + Q_D(const WebContentsAdapter); + content::NavigationEntry* entry = d->webContents->GetController().GetVisibleEntry(); + return entry ? toQt(entry->GetTitle()) : QString(); +} + +void WebContentsAdapter::navigateToIndex(int offset) +{ + Q_D(WebContentsAdapter); + d->webContents->GetController().GoToIndex(offset); + d->webContents->GetView()->Focus(); +} + +void WebContentsAdapter::navigateToOffset(int offset) +{ + Q_D(WebContentsAdapter); + d->webContents->GetController().GoToOffset(offset); + d->webContents->GetView()->Focus(); +} + +int WebContentsAdapter::navigationEntryCount() +{ + Q_D(WebContentsAdapter); + return d->webContents->GetController().GetEntryCount(); +} + +int WebContentsAdapter::currentNavigationEntryIndex() +{ + Q_D(WebContentsAdapter); + return d->webContents->GetController().GetCurrentEntryIndex(); +} + +QUrl WebContentsAdapter::getNavigationEntryOriginalUrl(int index) +{ + Q_D(WebContentsAdapter); + content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + return entry ? toQt(entry->GetOriginalRequestURL()) : QUrl(); +} + +QUrl WebContentsAdapter::getNavigationEntryUrl(int index) +{ + Q_D(WebContentsAdapter); + content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + return entry ? toQt(entry->GetURL()) : QUrl(); +} + +QString WebContentsAdapter::getNavigationEntryTitle(int index) +{ + Q_D(WebContentsAdapter); + content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); + return entry ? toQt(entry->GetTitle()) : QString(); +} + +void WebContentsAdapter::clearNavigationHistory() +{ + Q_D(WebContentsAdapter); + if (d->webContents->GetController().CanPruneAllButVisible()) + d->webContents->GetController().PruneAllButVisible(); +} + +void WebContentsAdapter::setZoomFactor(qreal factor) +{ + Q_D(WebContentsAdapter); + if (content::RenderViewHost *rvh = d->webContents->GetRenderViewHost()) + rvh->SetZoomLevel(content::ZoomFactorToZoomLevel(static_cast<double>(factor))); +} + +qreal WebContentsAdapter::currentZoomFactor() const +{ + Q_D(const WebContentsAdapter); + return static_cast<qreal>(content::ZoomLevelToZoomFactor(d->webContents->GetZoomLevel())); +} + +void WebContentsAdapter::enableInspector(bool enable) +{ + ContentBrowserClientQt::Get()->enableInspector(enable); +} + +void WebContentsAdapter::runJavaScript(const QString &javaScript, const QString &xPath, JSCallbackBase *func) +{ + Q_D(WebContentsAdapter); + content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + Q_ASSERT(rvh); + if (!func) + rvh->ExecuteJavascriptInWebFrame(toString16(xPath), toString16(javaScript)); + else { + content::RenderViewHost::JavascriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, func); + rvh->ExecuteJavascriptInWebFrameCallbackResult(toString16(xPath), toString16(javaScript), callback); + } +} diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h new file mode 100644 index 000000000..f631b6d69 --- /dev/null +++ b/src/core/web_contents_adapter.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef WEB_CONTENTS_ADAPTER_H +#define WEB_CONTENTS_ADAPTER_H + +#include "qtwebenginecoreglobal.h" +#include "web_contents_adapter_client.h" + +#include <QScopedPointer> +#include <QSharedData> +#include <QString> +#include <QUrl> + +QT_FORWARD_DECLARE_CLASS(QVariant) +namespace content { +class WebContents; +} +class WebContentsAdapterPrivate; + +struct JSCallbackBase { + virtual ~JSCallbackBase() {} + virtual void call(const QVariant&) = 0; +}; + +class QWEBENGINE_EXPORT WebContentsAdapter : public QSharedData { +public: + // Takes ownership of the WebContents. + WebContentsAdapter(WebContentsAdapterClient::RenderingMode renderingMode, content::WebContents *webContents = 0); + ~WebContentsAdapter(); + void initialize(WebContentsAdapterClient *adapterClient); + + bool canGoBack() const; + bool canGoForward() const; + bool isLoading() const; + void stop(); + void reload(); + void load(const QUrl&); + QUrl activeUrl() const; + QString pageTitle() const; + + void navigateToIndex(int); + void navigateToOffset(int); + int navigationEntryCount(); + int currentNavigationEntryIndex(); + QUrl getNavigationEntryOriginalUrl(int index); + QUrl getNavigationEntryUrl(int index); + QString getNavigationEntryTitle(int index); + void clearNavigationHistory(); + void setZoomFactor(qreal); + qreal currentZoomFactor() const; + void enableInspector(bool); + void runJavaScript(const QString &javaScript, const QString &xPath = QString(), JSCallbackBase * = 0); + +private: + Q_DISABLE_COPY(WebContentsAdapter); + Q_DECLARE_PRIVATE(WebContentsAdapter); + QScopedPointer<WebContentsAdapterPrivate> d_ptr; +}; +#endif // WEB_CONTENTS_ADAPTER_H diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h new file mode 100644 index 000000000..c7746ffb1 --- /dev/null +++ b/src/core/web_contents_adapter_client.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef WEB_CONTENTS_ADAPTER_CLIENT_H +#define WEB_CONTENTS_ADAPTER_CLIENT_H + +#include "qtwebenginecoreglobal.h" + +#include <QRect> +#include <QString> +#include <QUrl> + +class RenderWidgetHostViewQt; +class RenderWidgetHostViewQtDelegate; +class RenderWidgetHostViewQtDelegateClient; +class WebContentsAdapter; +class WebContentsDelegateQt; + +// FIXME: make this ref-counted and implicitely shared and expose as public API maybe ? +class WebEngineContextMenuData { + +public: + QPoint pos; + QUrl linkUrl; + QString linkText; + QString selectedText; +// Some likely candidates for future additions as we add support for the related actions: +// bool isImageBlocked; +// bool isEditable; +// bool isSpellCheckingEnabled; +// QStringList spellCheckingSuggestions; +// <enum tbd> mediaType; +// ... +}; + +class QWEBENGINE_EXPORT WebContentsAdapterClient { +public: + enum RenderingMode { + SoftwareRenderingMode, + HardwareAccelerationMode + }; + + // This must match window_open_disposition_list.h. + enum WindowOpenDisposition { + UnknownDisposition = 0, + SuppressOpenDisposition = 1, + CurrentTabDisposition = 2, + SingletonTabDisposition = 3, + NewForegroundTabDisposition = 4, + NewBackgroundTabDisposition = 5, + NewPopupDisposition = 6, + NewWindowDisposition = 7, + SaveToDiskDisposition = 8, + OffTheRecordDisposition = 9, + IgnoreActionDisposition = 10, + }; + + // Must match the values in javascript_message_type.h. + enum JavascriptDialogType { + AlertDialog, + ConfirmDialog, + PromptDialog + }; + + virtual ~WebContentsAdapterClient() { } + + virtual RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client, RenderingMode 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 void loadProgressChanged(int progress) = 0; + virtual QRectF viewportRect() const = 0; + virtual void loadFinished(bool success) = 0; + virtual void focusContainer() = 0; + virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, const QRect & initialGeometry) = 0; + virtual void close() = 0; + virtual bool contextMenuRequested(const WebEngineContextMenuData&) = 0; + virtual bool javascriptDialog(JavascriptDialogType type, const QString &message, const QString &defaultValue = QString(), QString *result = 0) = 0; +}; + +#endif // WEB_CONTENTS_ADAPTER_CLIENT_H diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp new file mode 100644 index 000000000..5a96d9be4 --- /dev/null +++ b/src/core/web_contents_delegate_qt.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "web_contents_delegate_qt.h" + +#include "type_conversion.h" +#include "web_contents_adapter.h" +#include "web_contents_adapter_client.h" +#include "web_engine_context.h" + +#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) +{ + webContents->SetDelegate(this); + Observe(webContents); +} + +void WebContentsDelegateQt::NavigationStateChanged(const content::WebContents* source, unsigned changed_flags) +{ + if (changed_flags & content::INVALIDATE_TYPE_URL) + m_viewClient->urlChanged(toQt(source->GetVisibleURL())); +} + +void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) +{ + WebContentsAdapter *newAdapter = new WebContentsAdapter(WebEngineContext::current()->renderingMode(), new_contents); + // Do the first ref-count manually to be able to know if the application is handling adoptNewWindow through the public API. + newAdapter->ref.ref(); + + m_viewClient->adoptNewWindow(newAdapter, static_cast<WebContentsAdapterClient::WindowOpenDisposition>(disposition), toQt(initial_pos)); + + if (!newAdapter->ref.deref()) { + // adoptNewWindow didn't increase the ref-count, new_contents needs to be discarded. + delete newAdapter; + newAdapter = 0; + } + + if (was_blocked) + *was_blocked = !newAdapter; +} + +void WebContentsDelegateQt::CloseContents(content::WebContents *source) +{ + m_viewClient->close(); +} + +void WebContentsDelegateQt::LoadingStateChanged(content::WebContents* source) +{ + m_viewClient->loadingStateChanged(); +} + +void WebContentsDelegateQt::LoadProgressChanged(content::WebContents* source, double progress) +{ + m_viewClient->loadProgressChanged(qRound(progress * 100)); +} + +void WebContentsDelegateQt::DidFailLoad(int64 frame_id, const GURL &validated_url, bool is_main_frame, int error_code, const string16 &error_description, content::RenderViewHost *render_view_host) +{ + if (is_main_frame) + m_viewClient->loadFinished(false); +} + +void WebContentsDelegateQt::DidFinishLoad(int64 frame_id, const GURL &validated_url, bool is_main_frame, content::RenderViewHost *render_view_host) +{ + 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; + } + } +} + +content::JavaScriptDialogManager *WebContentsDelegateQt::GetJavaScriptDialogManager() +{ + return JavaScriptDialogManagerQt::GetInstance(); +} diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h new file mode 100644 index 000000000..9e27c043f --- /dev/null +++ b/src/core/web_contents_delegate_qt.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WEB_CONTENTS_DELEGATE_QT_H +#define WEB_CONTENTS_DELEGATE_QT_H + +#include "content/public/browser/web_contents_delegate.h" +#include "content/public/browser/web_contents_observer.h" + +#include "javascript_dialog_manager_qt.h" + +namespace content { + class BrowserContext; + class SiteInstance; + class RenderViewHost; + class JavaScriptDialogManager; + class WebContents; +} +class WebContentsAdapterClient; + +class WebContentsDelegateQt : public content::WebContentsDelegate + , public content::WebContentsObserver +{ +public: + WebContentsDelegateQt(content::WebContents*, WebContentsAdapterClient *adapterClient); + + virtual void NavigationStateChanged(const content::WebContents* source, unsigned changed_flags) Q_DECL_OVERRIDE; + virtual void AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) Q_DECL_OVERRIDE; + virtual void CloseContents(content::WebContents *source) Q_DECL_OVERRIDE; + virtual void LoadingStateChanged(content::WebContents* source) Q_DECL_OVERRIDE; + // FIXME: with the next chromium update LoadProgressChanged with progress becomes available. Q_DECL_OVERRIDE must then be activated. + virtual void LoadProgressChanged(content::WebContents* source, double progress) /*Q_DECL_OVERRIDE*/; + 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) Q_DECL_OVERRIDE; + virtual void DidFinishLoad(int64 frame_id, const GURL &validated_url, bool is_main_frame, content::RenderViewHost *render_view_host) Q_DECL_OVERRIDE; + virtual void DidUpdateFaviconURL(int32 page_id, const std::vector<content::FaviconURL>& candidates) Q_DECL_OVERRIDE; + virtual content::JavaScriptDialogManager *GetJavaScriptDialogManager() Q_DECL_OVERRIDE; + +private: + WebContentsAdapterClient *m_viewClient; +}; + +#endif // WEB_CONTENTS_DELEGATE_QT_H diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp new file mode 100644 index 000000000..e89bac7a2 --- /dev/null +++ b/src/core/web_contents_view_qt.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "web_contents_view_qt.h" + +#include "browser_context_qt.h" +#include "content_browser_client_qt.h" +#include "render_widget_host_view_qt_delegate.h" +#include "web_engine_context.h" + +#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/public/common/context_menu_params.h" + +void WebContentsViewQt::initialize(WebContentsAdapterClient* client) +{ + m_client = client; + + // Check if a RWHV was created before the initialization. + if (m_webContents->GetRenderWidgetHostView()) + static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())->setAdapterClient(client); +} + +content::RenderWidgetHostView* WebContentsViewQt::CreateViewForWidget(content::RenderWidgetHost* render_widget_host) +{ + content::RenderWidgetHostView* view = CreateViewForPopupWidget(render_widget_host); + + // Tell the RWHV delegate to attach itself to the native view container. + view->InitAsChild(0); + + return view; +} + +content::RenderWidgetHostView* WebContentsViewQt::CreateViewForPopupWidget(content::RenderWidgetHost* render_widget_host) +{ + RenderWidgetHostViewQt *view = new RenderWidgetHostViewQt(render_widget_host); + + Q_ASSERT(m_factoryClient); + view->setDelegate(m_factoryClient->CreateRenderWidgetHostViewQtDelegate(view, WebEngineContext::current()->renderingMode())); + if (m_client) + view->setAdapterClient(m_client); + + return view; +} + +void WebContentsViewQt::CreateView(const gfx::Size& initial_size, gfx::NativeView context) +{ + // This is passed through content::WebContents::CreateParams::context either as the native view's client + // directly or, in the case of a page-created new window, the client of the creating window's native view. + m_factoryClient = reinterpret_cast<WebContentsAdapterClient *>(context); +} + +void WebContentsViewQt::SetPageTitle(const string16& title) +{ + m_client->titleChanged(toQt(title)); +} + +gfx::NativeView WebContentsViewQt::GetNativeView() const +{ + // Hack to provide the client to WebContentsImpl::CreateNewWindow. + return reinterpret_cast<gfx::NativeView>(m_client); +} + +void WebContentsViewQt::GetContainerBounds(gfx::Rect* out) const +{ + const QRectF r(m_client->viewportRect()); + *out = gfx::Rect(r.x(), r.y(), r.width(), r.height()); +} + +void WebContentsViewQt::Focus() +{ + m_client->focusContainer(); +} + +void WebContentsViewQt::SetInitialFocus() +{ + Focus(); +} + +static WebEngineContextMenuData fromParams(const content::ContextMenuParams ¶ms) +{ + WebEngineContextMenuData ret; + ret.pos = QPoint(params.x, params.y); + ret.linkUrl = toQt(params.link_url); + ret.linkText = toQt(params.link_text.data()); + ret.selectedText = toQt(params.selection_text.data()); + return ret; +} + +void WebContentsViewQt::ShowContextMenu(const content::ContextMenuParams ¶ms) +{ + WebEngineContextMenuData contextMenuData(fromParams(params)); + m_client->contextMenuRequested(contextMenuData); +} diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h new file mode 100644 index 000000000..ee81ccc81 --- /dev/null +++ b/src/core/web_contents_view_qt.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WEB_CONTENTS_VIEW_QT_H +#define WEB_CONTENTS_VIEW_QT_H + +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host.h" +#include "content/port/browser/render_view_host_delegate_view.h" +#include "content/port/browser/web_contents_view_port.h" + +#include "web_contents_adapter_client.h" +#include "render_widget_host_view_qt.h" +#include "web_contents_delegate_qt.h" +#include "web_engine_context.h" + +class WebContentsViewQt + : public content::WebContentsViewPort + , public content::RenderViewHostDelegateView +{ +public: + static inline WebContentsViewQt *from(WebContentsView *view) { return static_cast<WebContentsViewQt*>(view); } + + WebContentsViewQt(content::WebContents* webContents) + : m_webContents(webContents) + , m_client(0) + , m_factoryClient(0) + { } + + void initialize(WebContentsAdapterClient* client); + WebContentsAdapterClient *client() { return m_client; } + + virtual content::RenderWidgetHostView *CreateViewForWidget(content::RenderWidgetHost* render_widget_host) Q_DECL_OVERRIDE; + + virtual void CreateView(const gfx::Size& initial_size, gfx::NativeView context) Q_DECL_OVERRIDE; + + virtual content::RenderWidgetHostView* CreateViewForPopupWidget(content::RenderWidgetHost* render_widget_host) Q_DECL_OVERRIDE; + + virtual void SetPageTitle(const string16& title) Q_DECL_OVERRIDE; + + virtual void RenderViewCreated(content::RenderViewHost* host) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + + virtual void RenderViewSwappedIn(content::RenderViewHost* host) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + + virtual void SetOverscrollControllerEnabled(bool enabled) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + + virtual gfx::NativeView GetNativeView() const Q_DECL_OVERRIDE; + + virtual gfx::NativeView GetContentNativeView() const Q_DECL_OVERRIDE { QT_NOT_USED return 0; } + + virtual gfx::NativeWindow GetTopLevelNativeWindow() const Q_DECL_OVERRIDE { QT_NOT_USED return 0; } + + virtual void GetContainerBounds(gfx::Rect* out) const Q_DECL_OVERRIDE; + + virtual void OnTabCrashed(base::TerminationStatus status, int error_code) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + + virtual void SizeContents(const gfx::Size& size) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + + virtual void Focus() Q_DECL_OVERRIDE; + + virtual void SetInitialFocus() Q_DECL_OVERRIDE; + + virtual void StoreFocus() Q_DECL_OVERRIDE { QT_NOT_USED } + + virtual void RestoreFocus() Q_DECL_OVERRIDE { QT_NOT_USED } + + virtual content::DropData* GetDropData() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED return 0; } + + virtual gfx::Rect GetViewBounds() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED return gfx::Rect(); } + + virtual void ShowPopupMenu(const gfx::Rect& bounds, int item_height, double item_font_size, int selected_item, + const std::vector<content::MenuItem>& items, bool right_aligned, bool allow_multiple_selection) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + + virtual void ShowContextMenu(const content::ContextMenuParams ¶ms) Q_DECL_OVERRIDE; + +#if defined(OS_MACOSX) + virtual void SetAllowOverlappingViews(bool overlapping) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual void CloseTabAfterEventTracking() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual bool GetAllowOverlappingViews() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED; return false; } + virtual bool IsEventTracking() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED; return false; } +#endif // defined(OS_MACOSX) + +private: + content::WebContents *m_webContents; + WebContentsAdapterClient *m_client; + WebContentsAdapterClient *m_factoryClient; +}; + +#endif // WEB_CONTENTS_VIEW_QT_H diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp new file mode 100644 index 000000000..e26027207 --- /dev/null +++ b/src/core/web_engine_context.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "web_engine_context.h" + +#include <math.h> + +#include "base/command_line.h" +#include "base/files/file_path.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/content_switches.h" +#include "content/public/common/main_function_params.h" +#include "ui/gl/gl_switches.h" +#include "webkit/common/user_agent/user_agent_util.h" + +#include "content_browser_client_qt.h" +#include "content_client_qt.h" +#include "type_conversion.h" +#include <QGuiApplication> +#include <QStringList> +#include <qpa/qplatformnativeinterface.h> + +namespace { + +scoped_refptr<WebEngineContext> sContext; + +static QByteArray subProcessPath() { + static bool initialized = false; +#ifdef QTWEBENGINEPROCESS_PATH + static QByteArray processPath(QTWEBENGINEPROCESS_PATH); +#else + static QByteArray processPath; +#endif + if (initialized) + return processPath; + // Allow overriding at runtime for the time being. + const QByteArray fromEnv = qgetenv("QTWEBENGINEPROCESS_PATH"); + if (!fromEnv.isEmpty()) + processPath = fromEnv; + if (processPath.isEmpty()) + qFatal("QTWEBENGINEPROCESS_PATH environment variable not set or empty."); + initialized = true; + return processPath; +} + +} // namespace + +class ContentMainDelegateQt : public content::ContentMainDelegate +{ +public: + + // This is where the embedder puts all of its startup code that needs to run + // before the sandbox is engaged. + void PreSandboxStartup() Q_DECL_OVERRIDE + { + PathService::Override(base::FILE_EXE, base::FilePath(toFilePathString(subProcessPath()))); + } + + content::ContentBrowserClient* CreateContentBrowserClient() Q_DECL_OVERRIDE + { + m_browserClient.reset(new ContentBrowserClientQt); + return m_browserClient.get(); + } + + bool BasicStartupComplete(int* exit_code) Q_DECL_OVERRIDE + { + SetContentClient(new ContentClientQt); + return false; + } + +private: + scoped_ptr<ContentBrowserClientQt> m_browserClient; +}; + + +WebEngineContext::~WebEngineContext() +{ + m_runLoop->AfterRun(); +} + +scoped_refptr<WebEngineContext> WebEngineContext::currentOrCreate(WebContentsAdapterClient::RenderingMode renderingMode) +{ + if (!sContext) + sContext = new WebEngineContext(renderingMode); + else if (renderingMode != sContext->renderingMode()) + qFatal("Switching the QtWebEngine rendering mode once initialized in an application is not supported." + " If you're using both a QQuickWebView and a QtQuick WebEngineView, make sure that the" + " later is configured to use software rendering by setting:" + "\nqApp->setProperty(\"QQuickWebEngineView_DisableHardwareAcceleration\", QVariant(true));"); + return sContext; +} + +scoped_refptr<WebEngineContext> WebEngineContext::current() +{ + return sContext; +} + +WebContentsAdapterClient::RenderingMode WebEngineContext::renderingMode() +{ + return CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableDelegatedRenderer) + ? WebContentsAdapterClient::HardwareAccelerationMode + : WebContentsAdapterClient::SoftwareRenderingMode; +} + +WebEngineContext::WebEngineContext(WebContentsAdapterClient::RenderingMode renderingMode) + : m_mainDelegate(new ContentMainDelegateQt) + , m_contentRunner(content::ContentMainRunner::Create()) + , m_browserRunner(content::BrowserMainRunner::Create()) +{ + QList<QByteArray> args; + Q_FOREACH (const QString& arg, QCoreApplication::arguments()) + args << arg.toUtf8(); + const char* argv[args.size()]; + for (int i = 0; i < args.size(); ++i) + argv[i] = args[i].constData(); + CommandLine::Init(args.size(), argv); + + CommandLine* parsedCommandLine = CommandLine::ForCurrentProcess(); + parsedCommandLine->AppendSwitchASCII(switches::kUserAgent, webkit_glue::BuildUserAgentFromProduct("QtWebEngine/0.1")); + parsedCommandLine->AppendSwitchASCII(switches::kBrowserSubprocessPath, subProcessPath().constData()); + parsedCommandLine->AppendSwitch(switches::kNoSandbox); + parsedCommandLine->AppendSwitch(switches::kDisablePlugins); + + if (renderingMode == WebContentsAdapterClient::HardwareAccelerationMode && !parsedCommandLine->HasSwitch(switches::kDisableDelegatedRenderer)) { + parsedCommandLine->AppendSwitch(switches::kEnableDelegatedRenderer); + parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); + parsedCommandLine->AppendSwitch(switches::kInProcessGPU); + } + + // Tell Chromium to use EGL instead of GLX if the Qt xcb plugin also does. + if (qApp->platformName() == QStringLiteral("xcb") && qApp->platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("egldisplay"), 0)) + parsedCommandLine->AppendSwitchASCII(switches::kUseGL, gfx::kGLImplementationEGLName); + + m_contentRunner->Initialize(0, 0, m_mainDelegate.get()); + m_browserRunner->Initialize(content::MainFunctionParams(*CommandLine::ForCurrentProcess())); + + // Once the MessageLoop has been created, attach a top-level RunLoop. + m_runLoop.reset(new base::RunLoop); + m_runLoop->BeforeRun(); +} diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h new file mode 100644 index 000000000..cdd3e34b2 --- /dev/null +++ b/src/core/web_engine_context.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WEB_ENGINE_CONTEXT_H +#define WEB_ENGINE_CONTEXT_H + +#include "web_contents_adapter_client.h" + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +namespace base { +class RunLoop; +} + +namespace content { +class BrowserMainRunner; +class ContentMainRunner; +} + +class ContentMainDelegateQt; + +class WebEngineContext : public base::RefCounted<WebEngineContext> { +public: + static scoped_refptr<WebEngineContext> currentOrCreate(WebContentsAdapterClient::RenderingMode renderingMode); + static scoped_refptr<WebEngineContext> current(); + WebContentsAdapterClient::RenderingMode renderingMode(); + +private: + friend class base::RefCounted<WebEngineContext>; + WebEngineContext(WebContentsAdapterClient::RenderingMode renderingMode); + ~WebEngineContext(); + + scoped_ptr<base::RunLoop> m_runLoop; + scoped_ptr<ContentMainDelegateQt> m_mainDelegate; + scoped_ptr<content::ContentMainRunner> m_contentRunner; + scoped_ptr<content::BrowserMainRunner> m_browserRunner; +}; + +#endif // WEB_ENGINE_CONTEXT_H diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp new file mode 100644 index 000000000..d750aa3e0 --- /dev/null +++ b/src/core/web_event_factory.cpp @@ -0,0 +1,605 @@ +/**************************************************************************** +** +** Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "web_event_factory.h" +#include "third_party/WebKit/Source/core/platform/WindowsKeyboardCodes.h" + +#include <QElapsedTimer> +#include <QKeyEvent> +#include <QMouseEvent> +#include <QWheelEvent> + +static const int wheelScrollLines = 3; // FIXME: Still not available in QStyleHints in 5.1 + +using namespace WebKit; + +static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad) +{ + // Determine wheter the event comes from the keypad + if (isKeypad) { + switch (keycode) { + case Qt::Key_0: + return VK_NUMPAD0; // (60) Numeric keypad 0 key + case Qt::Key_1: + return VK_NUMPAD1; // (61) Numeric keypad 1 key + case Qt::Key_2: + return VK_NUMPAD2; // (62) Numeric keypad 2 key + case Qt::Key_3: + return VK_NUMPAD3; // (63) Numeric keypad 3 key + case Qt::Key_4: + return VK_NUMPAD4; // (64) Numeric keypad 4 key + case Qt::Key_5: + return VK_NUMPAD5; // (65) Numeric keypad 5 key + case Qt::Key_6: + return VK_NUMPAD6; // (66) Numeric keypad 6 key + case Qt::Key_7: + return VK_NUMPAD7; // (67) Numeric keypad 7 key + case Qt::Key_8: + return VK_NUMPAD8; // (68) Numeric keypad 8 key + case Qt::Key_9: + return VK_NUMPAD9; // (69) Numeric keypad 9 key + case Qt::Key_Asterisk: + return VK_MULTIPLY; // (6A) Multiply key + case Qt::Key_Plus: + return VK_ADD; // (6B) Add key + case Qt::Key_Minus: + return VK_SUBTRACT; // (6D) Subtract key + case Qt::Key_Period: + return VK_DECIMAL; // (6E) Decimal key + case Qt::Key_Slash: + return VK_DIVIDE; // (6F) Divide key + case Qt::Key_PageUp: + return VK_PRIOR; // (21) PAGE UP key + case Qt::Key_PageDown: + return VK_NEXT; // (22) PAGE DOWN key + case Qt::Key_End: + return VK_END; // (23) END key + case Qt::Key_Home: + return VK_HOME; // (24) HOME key + case Qt::Key_Left: + return VK_LEFT; // (25) LEFT ARROW key + case Qt::Key_Up: + return VK_UP; // (26) UP ARROW key + case Qt::Key_Right: + return VK_RIGHT; // (27) RIGHT ARROW key + case Qt::Key_Down: + return VK_DOWN; // (28) DOWN ARROW key + case Qt::Key_Enter: + case Qt::Key_Return: + return VK_RETURN; // (0D) Return key + case Qt::Key_Insert: + return VK_INSERT; // (2D) INS key + case Qt::Key_Delete: + return VK_DELETE; // (2E) DEL key + default: + return 0; + } + + } else + + switch (keycode) { + case Qt::Key_Backspace: + return VK_BACK; // (08) BACKSPACE key + case Qt::Key_Backtab: + case Qt::Key_Tab: + return VK_TAB; // (09) TAB key + case Qt::Key_Clear: + return VK_CLEAR; // (0C) CLEAR key + case Qt::Key_Enter: + case Qt::Key_Return: + return VK_RETURN; // (0D) Return key + case Qt::Key_Shift: + return VK_SHIFT; // (10) SHIFT key + case Qt::Key_Control: + return VK_CONTROL; // (11) CTRL key + case Qt::Key_Menu: + case Qt::Key_Alt: + return VK_MENU; // (12) ALT key + + case Qt::Key_F1: + return VK_F1; + case Qt::Key_F2: + return VK_F2; + case Qt::Key_F3: + return VK_F3; + case Qt::Key_F4: + return VK_F4; + case Qt::Key_F5: + return VK_F5; + case Qt::Key_F6: + return VK_F6; + case Qt::Key_F7: + return VK_F7; + case Qt::Key_F8: + return VK_F8; + case Qt::Key_F9: + return VK_F9; + case Qt::Key_F10: + return VK_F10; + case Qt::Key_F11: + return VK_F11; + case Qt::Key_F12: + return VK_F12; + case Qt::Key_F13: + return VK_F13; + case Qt::Key_F14: + return VK_F14; + case Qt::Key_F15: + return VK_F15; + case Qt::Key_F16: + return VK_F16; + case Qt::Key_F17: + return VK_F17; + case Qt::Key_F18: + return VK_F18; + case Qt::Key_F19: + return VK_F19; + case Qt::Key_F20: + return VK_F20; + case Qt::Key_F21: + return VK_F21; + case Qt::Key_F22: + return VK_F22; + case Qt::Key_F23: + return VK_F23; + case Qt::Key_F24: + return VK_F24; + + case Qt::Key_Pause: + return VK_PAUSE; // (13) PAUSE key + case Qt::Key_CapsLock: + return VK_CAPITAL; // (14) CAPS LOCK key + case Qt::Key_Kana_Lock: + case Qt::Key_Kana_Shift: + return VK_KANA; // (15) Input Method Editor (IME) Kana mode + case Qt::Key_Hangul: + return VK_HANGUL; // VK_HANGUL (15) IME Hangul mode + // VK_JUNJA (17) IME Junja mode + // VK_FINAL (18) IME final mode + case Qt::Key_Hangul_Hanja: + return VK_HANJA; // (19) IME Hanja mode + case Qt::Key_Kanji: + return VK_KANJI; // (19) IME Kanji mode + case Qt::Key_Escape: + return VK_ESCAPE; // (1B) ESC key + // VK_CONVERT (1C) IME convert + // VK_NONCONVERT (1D) IME nonconvert + // VK_ACCEPT (1E) IME accept + // VK_MODECHANGE (1F) IME mode change request + case Qt::Key_Space: + return VK_SPACE; // (20) SPACEBAR + case Qt::Key_PageUp: + return VK_PRIOR; // (21) PAGE UP key + case Qt::Key_PageDown: + return VK_NEXT; // (22) PAGE DOWN key + case Qt::Key_End: + return VK_END; // (23) END key + case Qt::Key_Home: + return VK_HOME; // (24) HOME key + case Qt::Key_Left: + return VK_LEFT; // (25) LEFT ARROW key + case Qt::Key_Up: + return VK_UP; // (26) UP ARROW key + case Qt::Key_Right: + return VK_RIGHT; // (27) RIGHT ARROW key + case Qt::Key_Down: + return VK_DOWN; // (28) DOWN ARROW key + case Qt::Key_Select: + return VK_SELECT; // (29) SELECT key + case Qt::Key_Print: + return VK_SNAPSHOT; // (2A) PRINT key + case Qt::Key_Execute: + return VK_EXECUTE; // (2B) EXECUTE key + case Qt::Key_Insert: + return VK_INSERT; // (2D) INS key + case Qt::Key_Delete: + return VK_DELETE; // (2E) DEL key + case Qt::Key_Help: + return VK_HELP; // (2F) HELP key + case Qt::Key_0: + case Qt::Key_ParenLeft: + return VK_0; // (30) 0) key + case Qt::Key_1: + return VK_1; // (31) 1 ! key + case Qt::Key_2: + case Qt::Key_At: + return VK_2; // (32) 2 & key + case Qt::Key_3: + case Qt::Key_NumberSign: + return VK_3; // case '3': case '#'; + case Qt::Key_4: + case Qt::Key_Dollar: // (34) 4 key '$'; + return VK_4; + case Qt::Key_5: + case Qt::Key_Percent: + return VK_5; // (35) 5 key '%' + case Qt::Key_6: + case Qt::Key_AsciiCircum: + return VK_6; // (36) 6 key '^' + case Qt::Key_7: + case Qt::Key_Ampersand: + return VK_7; // (37) 7 key case '&' + case Qt::Key_8: + case Qt::Key_Asterisk: + return VK_8; // (38) 8 key '*' + case Qt::Key_9: + case Qt::Key_ParenRight: + return VK_9; // (39) 9 key '(' + case Qt::Key_A: + return VK_A; // (41) A key case 'a': case 'A': return 0x41; + case Qt::Key_B: + return VK_B; // (42) B key case 'b': case 'B': return 0x42; + case Qt::Key_C: + return VK_C; // (43) C key case 'c': case 'C': return 0x43; + case Qt::Key_D: + return VK_D; // (44) D key case 'd': case 'D': return 0x44; + case Qt::Key_E: + return VK_E; // (45) E key case 'e': case 'E': return 0x45; + case Qt::Key_F: + return VK_F; // (46) F key case 'f': case 'F': return 0x46; + case Qt::Key_G: + return VK_G; // (47) G key case 'g': case 'G': return 0x47; + case Qt::Key_H: + return VK_H; // (48) H key case 'h': case 'H': return 0x48; + case Qt::Key_I: + return VK_I; // (49) I key case 'i': case 'I': return 0x49; + case Qt::Key_J: + return VK_J; // (4A) J key case 'j': case 'J': return 0x4A; + case Qt::Key_K: + return VK_K; // (4B) K key case 'k': case 'K': return 0x4B; + case Qt::Key_L: + return VK_L; // (4C) L key case 'l': case 'L': return 0x4C; + case Qt::Key_M: + return VK_M; // (4D) M key case 'm': case 'M': return 0x4D; + case Qt::Key_N: + return VK_N; // (4E) N key case 'n': case 'N': return 0x4E; + case Qt::Key_O: + return VK_O; // (4F) O key case 'o': case 'O': return 0x4F; + case Qt::Key_P: + return VK_P; // (50) P key case 'p': case 'P': return 0x50; + case Qt::Key_Q: + return VK_Q; // (51) Q key case 'q': case 'Q': return 0x51; + case Qt::Key_R: + return VK_R; // (52) R key case 'r': case 'R': return 0x52; + case Qt::Key_S: + return VK_S; // (53) S key case 's': case 'S': return 0x53; + case Qt::Key_T: + return VK_T; // (54) T key case 't': case 'T': return 0x54; + case Qt::Key_U: + return VK_U; // (55) U key case 'u': case 'U': return 0x55; + case Qt::Key_V: + return VK_V; // (56) V key case 'v': case 'V': return 0x56; + case Qt::Key_W: + return VK_W; // (57) W key case 'w': case 'W': return 0x57; + case Qt::Key_X: + return VK_X; // (58) X key case 'x': case 'X': return 0x58; + case Qt::Key_Y: + return VK_Y; // (59) Y key case 'y': case 'Y': return 0x59; + case Qt::Key_Z: + return VK_Z; // (5A) Z key case 'z': case 'Z': return 0x5A; + case Qt::Key_Meta: + return VK_LWIN; // (5B) Left Windows key (Microsoft Natural keyboard) + // case Qt::Key_Meta_R: FIXME: What to do here? + // return VK_RWIN; // (5C) Right Windows key (Natural keyboard) + // VK_APPS (5D) Applications key (Natural keyboard) + // VK_SLEEP (5F) Computer Sleep key + // VK_SEPARATOR (6C) Separator key + // VK_SUBTRACT (6D) Subtract key + // VK_DECIMAL (6E) Decimal key + // VK_DIVIDE (6F) Divide key + // handled by key code above + + case Qt::Key_NumLock: + return VK_NUMLOCK; // (90) NUM LOCK key + + case Qt::Key_ScrollLock: + return VK_SCROLL; // (91) SCROLL LOCK key + + // VK_LSHIFT (A0) Left SHIFT key + // VK_RSHIFT (A1) Right SHIFT key + // VK_LCONTROL (A2) Left CONTROL key + // VK_RCONTROL (A3) Right CONTROL key + // VK_LMENU (A4) Left MENU key + // VK_RMENU (A5) Right MENU key + // VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key + // VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key + // VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key + // VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key + // VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key + // VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key + // VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key + // VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key + // VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key + // VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key + // VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key + // VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key + // VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key + // VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key + // VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key + // VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key + // VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key + // VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key + + // VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key + case Qt::Key_Semicolon: + case Qt::Key_Colon: + return VK_OEM_1; // case ';': case ':': return 0xBA; + // VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key + case Qt::Key_Plus: + case Qt::Key_Equal: + return VK_OEM_PLUS; // case '=': case '+': return 0xBB; + // VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key + case Qt::Key_Comma: + case Qt::Key_Less: + return VK_OEM_COMMA; // case ',': case '<': return 0xBC; + // VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key + case Qt::Key_Minus: + case Qt::Key_Underscore: + return VK_OEM_MINUS; // case '-': case '_': return 0xBD; + // VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key + case Qt::Key_Period: + case Qt::Key_Greater: + return VK_OEM_PERIOD; // case '.': case '>': return 0xBE; + // VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key + case Qt::Key_Slash: + case Qt::Key_Question: + return VK_OEM_2; // case '/': case '?': return 0xBF; + // VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key + case Qt::Key_AsciiTilde: + case Qt::Key_QuoteLeft: + return VK_OEM_3; // case '`': case '~': return 0xC0; + // VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key + case Qt::Key_BracketLeft: + case Qt::Key_BraceLeft: + return VK_OEM_4; // case '[': case '{': return 0xDB; + // VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key + case Qt::Key_Backslash: + case Qt::Key_Bar: + return VK_OEM_5; // case '\\': case '|': return 0xDC; + // VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key + case Qt::Key_BracketRight: + case Qt::Key_BraceRight: + return VK_OEM_6; // case ']': case '}': return 0xDD; + // VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key + case Qt::Key_QuoteDbl: + return VK_OEM_7; // case '\'': case '"': return 0xDE; + // VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard. + // VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard + // VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key + // VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP + // VK_ATTN (F6) Attn key + // VK_CRSEL (F7) CrSel key + // VK_EXSEL (F8) ExSel key + // VK_EREOF (F9) Erase EOF key + // VK_PLAY (FA) Play key + // VK_ZOOM (FB) Zoom key + // VK_NONAME (FC) Reserved for future use + // VK_PA1 (FD) PA1 key + // VK_OEM_CLEAR (FE) Clear key + default: + return 0; + } +} + +static inline double currentTimeForEvent(const QInputEvent* event) +{ + Q_ASSERT(event); + + if (event->timestamp()) + return static_cast<double>(event->timestamp()) / 1000; + + static QElapsedTimer timer; + if (!timer.isValid()) + timer.start(); + return static_cast<double>(timer.elapsed()) / 1000; +} + +static WebMouseEvent::Button mouseButtonForEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton || (event->buttons() & Qt::LeftButton)) + return WebMouseEvent::ButtonLeft; + else if (event->button() == Qt::RightButton || (event->buttons() & Qt::RightButton)) + return WebMouseEvent::ButtonRight; + else if (event->button() == Qt::MidButton || (event->buttons() & Qt::MidButton)) + return WebMouseEvent::ButtonMiddle; + return WebMouseEvent::ButtonNone; +} + +template <typename T> +static unsigned mouseButtonsModifiersForEvent(const T* event) +{ + unsigned ret = 0; + if (event->buttons() & Qt::LeftButton) + ret |= WebInputEvent::LeftButtonDown; + if (event->buttons() & Qt::RightButton) + ret |= WebInputEvent::RightButtonDown; + if (event->buttons() & Qt::MidButton) + ret |= WebInputEvent::MiddleButtonDown; + return ret; +} + +static inline WebInputEvent::Modifiers modifiersForEvent(const QInputEvent* event) +{ + unsigned result = 0; + Qt::KeyboardModifiers modifiers = event->modifiers(); + if (modifiers & Qt::ShiftModifier) + result |= WebInputEvent::ShiftKey; + if (modifiers & Qt::ControlModifier) + result |= WebInputEvent::ControlKey; + if (modifiers & Qt::AltModifier) + result |= WebInputEvent::AltKey; + if (modifiers & Qt::MetaModifier) + result |= WebInputEvent::MetaKey; + if (modifiers & Qt::KeypadModifier) + result |= WebInputEvent::IsKeyPad; + + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + result |= mouseButtonsModifiersForEvent(static_cast<const QMouseEvent*>(event)); + break; + case QEvent::Wheel: + result |= mouseButtonsModifiersForEvent(static_cast<const QWheelEvent*>(event)); + break; + case QEvent::KeyPress: + case QEvent::KeyRelease: + if (static_cast<const QKeyEvent*>(event)->isAutoRepeat()) + result |= WebInputEvent::IsAutoRepeat; + default: + break; + } + + return (WebInputEvent::Modifiers)result; +} + +static WebInputEvent::Type webEventTypeForEvent(const QEvent* event) +{ + switch (event->type()) { + case QEvent::MouseButtonPress: + return WebInputEvent::MouseDown; + case QEvent::MouseButtonRelease: + return WebInputEvent::MouseUp; + case QEvent::Enter: + return WebInputEvent::MouseEnter; + case QEvent::Leave: + return WebInputEvent::MouseLeave; + case QEvent::MouseMove: + return WebInputEvent::MouseMove; + case QEvent::Wheel: + return WebInputEvent::MouseWheel; + case QEvent::KeyPress: + return WebInputEvent::KeyDown; + case QEvent::KeyRelease: + return WebInputEvent::KeyUp; + case QEvent::HoverMove: + return WebInputEvent::MouseMove; + case QEvent::TouchBegin: + return WebInputEvent::TouchStart; + case QEvent::TouchUpdate: + return WebInputEvent::TouchMove; + case QEvent::TouchEnd: + return WebInputEvent::TouchEnd; + case QEvent::TouchCancel: + return WebInputEvent::TouchCancel; + default: + Q_ASSERT(false); + return WebInputEvent::MouseMove; + } +} + +WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev) +{ + WebMouseEvent webKitEvent; + webKitEvent.timeStampSeconds = currentTimeForEvent(ev); + webKitEvent.button = mouseButtonForEvent(ev); + webKitEvent.modifiers = modifiersForEvent(ev); + + webKitEvent.x = webKitEvent.windowX = ev->x(); + webKitEvent.y = webKitEvent.windowY = ev->y(); + webKitEvent.globalX = ev->globalX(); + webKitEvent.globalY = ev->globalY(); + + webKitEvent.type = webEventTypeForEvent(ev); + webKitEvent.clickCount = 0; + + return webKitEvent; +} + +WebMouseEvent WebEventFactory::toWebMouseEvent(QHoverEvent *ev) +{ + WebMouseEvent webKitEvent; + webKitEvent.timeStampSeconds = currentTimeForEvent(ev); + webKitEvent.modifiers = modifiersForEvent(ev); + + webKitEvent.x = webKitEvent.windowX = ev->pos().x(); + webKitEvent.y = webKitEvent.windowY = ev->pos().y(); + + webKitEvent.type = webEventTypeForEvent(ev); + return webKitEvent; +} + +WebKit::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev) +{ + WebMouseWheelEvent webEvent; + webEvent.type = webEventTypeForEvent(ev); + webEvent.deltaX = 0; + webEvent.deltaY = 0; + webEvent.wheelTicksX = 0; + webEvent.wheelTicksY = 0; + webEvent.modifiers = modifiersForEvent(ev); + webEvent.timeStampSeconds = currentTimeForEvent(ev); + + if (ev->orientation() == Qt::Horizontal) + webEvent.wheelTicksX = ev->delta() / 120.0f; + else + webEvent.wheelTicksY = ev->delta() / 120.0f; + + + // Since we report the scroll by the pixel, convert the delta to pixel distance using standard scroll step. + // Use the same single scroll step as QTextEdit (in QTextEditPrivate::init [h,v]bar->setSingleStep) + static const float cDefaultQtScrollStep = 20.f; + + webEvent.deltaX = webEvent.wheelTicksX * wheelScrollLines * cDefaultQtScrollStep; + webEvent.deltaY = webEvent.wheelTicksY * wheelScrollLines * cDefaultQtScrollStep; + + webEvent.x = webEvent.windowX = ev->x(); + webEvent.y = webEvent.windowY = ev->y(); + webEvent.globalX = ev->globalX(); + webEvent.globalY = ev->globalY(); + return webEvent; +} + +content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev) +{ + content::NativeWebKeyboardEvent webKitEvent; + webKitEvent.timeStampSeconds = currentTimeForEvent(ev); + webKitEvent.modifiers = modifiersForEvent(ev); + webKitEvent.type = webEventTypeForEvent(ev); + + webKitEvent.nativeKeyCode = ev->nativeVirtualKey(); + webKitEvent.windowsKeyCode = windowsKeyCodeForKeyEvent(ev->key(), ev->modifiers() & Qt::KeypadModifier); + webKitEvent.setKeyIdentifierFromWindowsKeyCode(); + + memcpy(&webKitEvent.text, ev->text().utf16(), qMin(sizeof(webKitEvent.text), sizeof(ev->text().utf16()))); + return webKitEvent; +} diff --git a/src/core/web_event_factory.h b/src/core/web_event_factory.h new file mode 100644 index 000000000..e5ee91510 --- /dev/null +++ b/src/core/web_event_factory.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WEB_EVENT_FACTORY_H +#define WEB_EVENT_FACTORY_H + +#include "content/public/browser/native_web_keyboard_event.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" + +#include <QtGlobal> + +QT_BEGIN_NAMESPACE +class QHoverEvent; +class QKeyEvent; +class QMouseEvent; +class QWheelEvent; +QT_END_NAMESPACE + +class WebEventFactory { + +public: + static WebKit::WebMouseEvent toWebMouseEvent(QMouseEvent*); + static WebKit::WebMouseEvent toWebMouseEvent(QHoverEvent*); + static WebKit::WebMouseWheelEvent toWebWheelEvent(QWheelEvent*); + static content::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*); +}; + + +#endif // WEB_EVENT_FACTORY_H diff --git a/src/core/yuv_video_node.cpp b/src/core/yuv_video_node.cpp new file mode 100644 index 000000000..e6c0c7da9 --- /dev/null +++ b/src/core/yuv_video_node.cpp @@ -0,0 +1,274 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "yuv_video_node.h" + +#include <QtQuick/qsgtexture.h> + +class YUVVideoMaterialShader : public QSGMaterialShader +{ +public: + virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) Q_DECL_OVERRIDE; + + virtual char const *const *attributeNames() const Q_DECL_OVERRIDE { + static const char *names[] = { + "a_position", + "a_texCoord", + 0 + }; + return names; + } + +protected: + virtual const char *vertexShader() const Q_DECL_OVERRIDE { + // Keep in sync with cc::VertexShaderPosTexYUVStretch + const char *shader = + "attribute highp vec4 a_position;\n" + "attribute mediump vec2 a_texCoord;\n" + "uniform highp mat4 matrix;\n" + "varying mediump vec2 v_texCoord;\n" + "uniform mediump vec2 texScale;\n" + "void main() {\n" + " gl_Position = matrix * a_position;\n" + " v_texCoord = a_texCoord * texScale;\n" + "}"; + return shader; + } + + virtual const char *fragmentShader() const Q_DECL_OVERRIDE { + // Keep in sync with cc::FragmentShaderYUVVideo + static const char *shader = + "varying mediump vec2 v_texCoord;\n" + "uniform sampler2D y_texture;\n" + "uniform sampler2D u_texture;\n" + "uniform sampler2D v_texture;\n" + "uniform lowp float alpha;\n" + "uniform lowp vec3 yuv_adj;\n" + "uniform lowp mat3 yuv_matrix;\n" + "void main() {\n" + " lowp float y_raw = texture2D(y_texture, v_texCoord).x;\n" + " lowp float u_unsigned = texture2D(u_texture, v_texCoord).x;\n" + " lowp float v_unsigned = texture2D(v_texture, v_texCoord).x;\n" + " lowp vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;\n" + " lowp vec3 rgb = yuv_matrix * yuv;\n" + " gl_FragColor = vec4(rgb, 1.0) * alpha;\n" + "}"; + return shader; + } + + virtual void initialize() Q_DECL_OVERRIDE { + m_id_matrix = program()->uniformLocation("matrix"); + m_id_texScale = program()->uniformLocation("texScale"); + m_id_yTexture = program()->uniformLocation("y_texture"); + m_id_uTexture = program()->uniformLocation("u_texture"); + m_id_vTexture = program()->uniformLocation("v_texture"); + m_id_yuvMatrix = program()->uniformLocation("yuv_matrix"); + m_id_yuvAdjust = program()->uniformLocation("yuv_adj"); + m_id_opacity = program()->uniformLocation("alpha"); + } + + int m_id_matrix; + int m_id_texScale; + int m_id_yTexture; + int m_id_uTexture; + int m_id_vTexture; + int m_id_yuvMatrix; + int m_id_yuvAdjust; + int m_id_opacity; +}; + +class YUVAVideoMaterialShader : public YUVVideoMaterialShader +{ + virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) Q_DECL_OVERRIDE; + +protected: + virtual const char *fragmentShader() const Q_DECL_OVERRIDE { + // Keep in sync with cc::FragmentShaderYUVAVideo + static const char *shader = + // "precision mediump float;\n" + // "precision mediump int;\n" + "varying mediump vec2 v_texCoord;\n" + "uniform sampler2D y_texture;\n" + "uniform sampler2D u_texture;\n" + "uniform sampler2D v_texture;\n" + "uniform sampler2D a_texture;\n" + "uniform lowp float alpha;\n" + "uniform lowp vec3 yuv_adj;\n" + "uniform lowp mat3 yuv_matrix;\n" + "void main() {\n" + " lowp float y_raw = texture2D(y_texture, v_texCoord).x;\n" + " lowp float u_unsigned = texture2D(u_texture, v_texCoord).x;\n" + " lowp float v_unsigned = texture2D(v_texture, v_texCoord).x;\n" + " lowp float a_raw = texture2D(a_texture, v_texCoord).x;\n" + " lowp vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;\n" + " lowp vec3 rgb = yuv_matrix * yuv;\n" + " gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);\n" + "}"; + return shader; + } + + virtual void initialize() Q_DECL_OVERRIDE { + // YUVVideoMaterialShader has a subset of the uniforms. + YUVVideoMaterialShader::initialize(); + m_id_aTexture = program()->uniformLocation("a_texture"); + } + + int m_id_aTexture; +}; + +void YUVVideoMaterialShader::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) +{ + Q_UNUSED(oldMaterial); + + YUVVideoMaterial *mat = static_cast<YUVVideoMaterial *>(newMaterial); + program()->setUniformValue(m_id_yTexture, 0); + program()->setUniformValue(m_id_uTexture, 1); + program()->setUniformValue(m_id_vTexture, 2); + + glActiveTexture(GL_TEXTURE1); + mat->m_uTexture->bind(); + glActiveTexture(GL_TEXTURE2); + mat->m_vTexture->bind(); + glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit + mat->m_yTexture->bind(); + + program()->setUniformValue(m_id_texScale, mat->m_texScale); + + // These values are magic numbers that are used in the transformation from YUV + // to RGB color values. They are taken from the following webpage: + // http://www.fourcc.org/fccyvrgb.php + const float yuv_to_rgb[9] = { + 1.164f, 0.0f, 1.596f, + 1.164f, -.391f, -.813f, + 1.164f, 2.018f, 0.0f, + }; + const QMatrix3x3 yuvMatrix(yuv_to_rgb); + + // These values map to 16, 128, and 128 respectively, and are computed + // as a fraction over 256 (e.g. 16 / 256 = 0.0625). + // They are used in the YUV to RGBA conversion formula: + // Y - 16 : Gives 16 values of head and footroom for overshooting + // U - 128 : Turns unsigned U into signed U [-128,127] + // V - 128 : Turns unsigned V into signed V [-128,127] + const QVector3D yuvAdjust(-0.0625f, -0.5f, -0.5f); + program()->setUniformValue(m_id_yuvMatrix, yuvMatrix); + program()->setUniformValue(m_id_yuvAdjust, yuvAdjust); + + if (state.isOpacityDirty()) + program()->setUniformValue(m_id_opacity, state.opacity()); + + if (state.isMatrixDirty()) + program()->setUniformValue(m_id_matrix, state.combinedMatrix()); +} + +void YUVAVideoMaterialShader::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) +{ + YUVVideoMaterialShader::updateState(state, newMaterial, oldMaterial); + + YUVAVideoMaterial *mat = static_cast<YUVAVideoMaterial *>(newMaterial); + program()->setUniformValue(m_id_aTexture, 3); + + glActiveTexture(GL_TEXTURE3); + mat->m_aTexture->bind(); + + // Reset the default texture unit. + glActiveTexture(GL_TEXTURE0); +} + + +YUVVideoMaterial::YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, const QSizeF &texScale) + : m_yTexture(yTexture) + , m_uTexture(uTexture) + , m_vTexture(vTexture) + , m_texScale(texScale) +{ +} + +QSGMaterialShader *YUVVideoMaterial::createShader() const +{ + return new YUVVideoMaterialShader; +} + +int YUVVideoMaterial::compare(const QSGMaterial *other) const +{ + const YUVVideoMaterial *m = static_cast<const YUVVideoMaterial *>(other); + if (int diff = m_yTexture->textureId() - m->m_yTexture->textureId()) + return diff; + if (int diff = m_uTexture->textureId() - m->m_uTexture->textureId()) + return diff; + return m_vTexture->textureId() - m->m_vTexture->textureId(); +} + +YUVAVideoMaterial::YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, const QSizeF &texScale) + : YUVVideoMaterial(yTexture, uTexture, vTexture, texScale) + , m_aTexture(aTexture) +{ + setFlag(Blending, aTexture); +} + +QSGMaterialShader *YUVAVideoMaterial::createShader() const +{ + return new YUVAVideoMaterialShader; +} + +int YUVAVideoMaterial::compare(const QSGMaterial *other) const +{ + if (int diff = YUVVideoMaterial::compare(other)) + return diff; + const YUVAVideoMaterial *m = static_cast<const YUVAVideoMaterial *>(other); + return (m_aTexture ? m_aTexture->textureId() : 0) - (m->m_aTexture ? m->m_aTexture->textureId() : 0); +} + +YUVVideoNode::YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, const QSizeF &texScale) + : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) +{ + setGeometry(&m_geometry); + setFlag(QSGNode::OwnsMaterial); + if (aTexture) + m_material = new YUVAVideoMaterial(yTexture, uTexture, vTexture, aTexture, texScale); + else + m_material = new YUVVideoMaterial(yTexture, uTexture, vTexture, texScale); + setMaterial(m_material); +} + +void YUVVideoNode::setRect(const QRectF &rect) +{ + QSGGeometry::updateTexturedRectGeometry(geometry(), rect, QRectF(0, 0, 1, 1)); +} diff --git a/src/core/yuv_video_node.h b/src/core/yuv_video_node.h new file mode 100644 index 000000000..509ef40e6 --- /dev/null +++ b/src/core/yuv_video_node.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef YUV_VIDEO_NODE_H +#define YUV_VIDEO_NODE_H + +#include <QtQuick/qsgmaterial.h> +#include <QtQuick/qsgnode.h> + +QT_BEGIN_NAMESPACE +class QSGTexture; +QT_END_NAMESPACE + +// These classes duplicate, QtQuick style, the logic of GLRenderer::DrawYUVVideoQuad. +// Their behavior should stay as close as possible to GLRenderer. + +class YUVVideoMaterial : public QSGMaterial +{ +public: + YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, const QSizeF &texScale); + + virtual QSGMaterialType *type() const Q_DECL_OVERRIDE { + static QSGMaterialType theType; + return &theType; + } + + virtual QSGMaterialShader *createShader() const Q_DECL_OVERRIDE; + virtual int compare(const QSGMaterial *other) const Q_DECL_OVERRIDE; + + QSGTexture *m_yTexture; + QSGTexture *m_uTexture; + QSGTexture *m_vTexture; + QSizeF m_texScale; +}; + +class YUVAVideoMaterial : public YUVVideoMaterial +{ +public: + YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, const QSizeF &texScale); + + virtual QSGMaterialType *type() const Q_DECL_OVERRIDE{ + static QSGMaterialType theType; + return &theType; + } + + virtual QSGMaterialShader *createShader() const Q_DECL_OVERRIDE; + virtual int compare(const QSGMaterial *other) const Q_DECL_OVERRIDE; + + QSGTexture *m_aTexture; +}; + +class YUVVideoNode : public QSGGeometryNode +{ +public: + YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, const QSizeF &texScale); + void setRect(const QRectF &rect); + +private: + QSGGeometry m_geometry; + YUVVideoMaterial *m_material; +}; + +#endif // YUV_VIDEO_NODE_H |