diff options
Diffstat (limited to 'src')
123 files changed, 6751 insertions, 1838 deletions
diff --git a/src/3rdparty b/src/3rdparty -Subproject f9c03801de86b5e9da2b915a9e490c2f2254fec +Subproject a43649f5fb0cd4b284b2b02a010a397e1ff48f8 diff --git a/src/core/access_token_store_qt.cpp b/src/core/access_token_store_qt.cpp index 85a91c3f7..791d628ba 100644 --- a/src/core/access_token_store_qt.cpp +++ b/src/core/access_token_store_qt.cpp @@ -34,11 +34,27 @@ ** ****************************************************************************/ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "access_token_store_qt.h" -#include <QDebug> +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/browser_thread.h" + +#include "browser_context_qt.h" +#include "browser_context_adapter.h" +#include "content_browser_client_qt.h" +#include "web_engine_context.h" + +using content::AccessTokenStore; +using content::BrowserThread; AccessTokenStoreQt::AccessTokenStoreQt() + : m_systemRequestContext(0) { } @@ -48,9 +64,23 @@ AccessTokenStoreQt::~AccessTokenStoreQt() void AccessTokenStoreQt::LoadAccessTokens(const LoadAccessTokensCallbackType& callback) { + BrowserThread::PostTaskAndReply(BrowserThread::UI, FROM_HERE + , base::Bind(&AccessTokenStoreQt::performWorkOnUIThread, this) + , base::Bind(&AccessTokenStoreQt::respondOnOriginatingThread, this, callback)); +} + +void AccessTokenStoreQt::performWorkOnUIThread() +{ + m_systemRequestContext = WebEngineContext::current()->defaultBrowserContext()->browserContext()->GetRequestContext(); } -void AccessTokenStoreQt::SaveAccessToken(const GURL& server_url, const base::string16& access_token) +void AccessTokenStoreQt::respondOnOriginatingThread(const LoadAccessTokensCallbackType& callback) { + callback.Run(m_accessTokenSet, m_systemRequestContext); + m_systemRequestContext = 0; } +void AccessTokenStoreQt::SaveAccessToken(const GURL& serverUrl, const base::string16& accessToken) +{ + m_accessTokenSet[serverUrl] = accessToken; +} diff --git a/src/core/access_token_store_qt.h b/src/core/access_token_store_qt.h index 2a76681f0..9493da774 100644 --- a/src/core/access_token_store_qt.h +++ b/src/core/access_token_store_qt.h @@ -37,20 +37,33 @@ #ifndef ACCESS_TOKEN_STORE_QT_H #define ACCESS_TOKEN_STORE_QT_H +#include "base/memory/ref_counted.h" #include "content/public/browser/access_token_store.h" -#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE +#include <QtCore/qcompilerdetection.h> +#include <QtCore/QFile> +#include <QtCore/QScopedPointer> -class AccessTokenStoreQt : public content::AccessTokenStore -{ +namespace net { +class URLRequestContextGetter; +} + +class AccessTokenStoreQt : public content::AccessTokenStore { public: AccessTokenStoreQt(); ~AccessTokenStoreQt(); - virtual void LoadAccessTokens(const LoadAccessTokensCallbackType& callback) Q_DECL_OVERRIDE; - virtual void SaveAccessToken(const GURL& server_url, const base::string16& access_token) Q_DECL_OVERRIDE; + virtual void LoadAccessTokens(const LoadAccessTokensCallbackType& request) Q_DECL_OVERRIDE; + virtual void SaveAccessToken(const GURL& serverUrl, const base::string16& accessToken) Q_DECL_OVERRIDE; private: + void performWorkOnUIThread(); + void respondOnOriginatingThread(const LoadAccessTokensCallbackType& callback); + + + net::URLRequestContextGetter *m_systemRequestContext; + AccessTokenSet m_accessTokenSet; + DISALLOW_COPY_AND_ASSIGN(AccessTokenStoreQt); }; diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp index 28d0dd7e3..0157c8602 100644 --- a/src/core/browser_accessibility_manager_qt.cpp +++ b/src/core/browser_accessibility_manager_qt.cpp @@ -43,6 +43,19 @@ using namespace blink; namespace content { +BrowserAccessibilityManager* BrowserAccessibilityManager::Create( + const ui::AXTreeUpdate& initial_tree, + BrowserAccessibilityDelegate* delegate, + BrowserAccessibilityFactory* factory) +{ +#ifndef QT_NO_ACCESSIBILITY + return new BrowserAccessibilityManagerQt(0, initial_tree, delegate); +#else + return 0; +#endif // QT_NO_ACCESSIBILITY +} + +#ifndef QT_NO_ACCESSIBILITY BrowserAccessibility *BrowserAccessibilityFactoryQt::Create() { return new BrowserAccessibilityQt(); @@ -95,23 +108,12 @@ void BrowserAccessibilityManagerQt::NotifyAccessibilityEvent(ui::AXEvent event_t break; case ui::AX_EVENT_LOAD_COMPLETE: break; - case ui::AX_EVENT_TEXT_CHANGED: { QAccessibleTextUpdateEvent event(iface, -1, QString(), QString()); QAccessible::updateAccessibility(&event); break; } - case ui::AX_EVENT_TEXT_INSERTED: { - QAccessibleTextInsertEvent event(iface, -1, QString()); - QAccessible::updateAccessibility(&event); - break; - } - case ui::AX_EVENT_TEXT_REMOVED: { - QAccessibleTextRemoveEvent event(iface, -1, QString()); - QAccessible::updateAccessibility(&event); - break; - } - case ui::AX_EVENT_SELECTED_TEXT_CHANGED: { + case ui::AX_EVENT_TEXT_SELECTION_CHANGED: { QAccessibleTextInterface *textIface = iface->textInterface(); if (textIface) { int start = 0; @@ -131,5 +133,6 @@ void BrowserAccessibilityManagerQt::NotifyAccessibilityEvent(ui::AXEvent event_t break; } } +#endif // QT_NO_ACCESSIBILITY } diff --git a/src/core/browser_accessibility_manager_qt.h b/src/core/browser_accessibility_manager_qt.h index 5d8498d01..49b3af3b2 100644 --- a/src/core/browser_accessibility_manager_qt.h +++ b/src/core/browser_accessibility_manager_qt.h @@ -38,6 +38,7 @@ #define BROWSER_ACCESSIBILITY_MANAGER_QT_H #include "content/browser/accessibility/browser_accessibility_manager.h" +#ifndef QT_NO_ACCESSIBILITY #include <QtCore/qobject.h> QT_BEGIN_NAMESPACE @@ -74,4 +75,5 @@ private: } +#endif // QT_NO_ACCESSIBILITY #endif diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index b5cd26f2f..9d7dbe8d8 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -38,6 +38,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef QT_NO_ACCESSIBILITY #include "browser_accessibility_qt.h" #include "third_party/WebKit/public/web/WebAXEnums.h" @@ -384,8 +385,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::NoRole; // FIXME case ui::AX_ROLE_MATH: return QAccessible::Equation; - case ui::AX_ROLE_MATH_ELEMENT: - return QAccessible::Equation; case ui::AX_ROLE_MATTE: return QAccessible::NoRole; // FIXME case ui::AX_ROLE_MENU: @@ -898,3 +897,5 @@ void BrowserAccessibilityQt::modelChange(QAccessibleTableModelChangeEvent *) } } // namespace content + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h index db190ffc4..6baab98b3 100644 --- a/src/core/browser_accessibility_qt.h +++ b/src/core/browser_accessibility_qt.h @@ -36,6 +36,7 @@ #ifndef BROWSER_ACCESSIBILITY_QT_H #define BROWSER_ACCESSIBILITY_QT_H +#ifndef QT_NO_ACCESSIBILITY #include <QtGui/qaccessible.h> #include "content/browser/accessibility/browser_accessibility.h" @@ -145,4 +146,5 @@ public: } +#endif // QT_NO_ACCESSIBILITY #endif diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp new file mode 100644 index 000000000..586d2c2ef --- /dev/null +++ b/src/core/browser_context_adapter.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "browser_context_adapter.h" + +#include "content/public/browser/browser_thread.h" +#include "browser_context_qt.h" +#include "content_client_qt.h" +#include "download_manager_delegate_qt.h" +#include "web_engine_context.h" +#include "web_engine_visited_links_manager.h" +#include "url_request_context_getter_qt.h" + +#include "net/proxy/proxy_service.h" + +#include <QCoreApplication> +#include <QDir> +#include <QString> +#include <QStringBuilder> +#include <QStandardPaths> + +namespace { +inline QString buildLocationFromStandardPath(const QString &standardPath, const QString &name) { + QString location = standardPath; + if (location.isEmpty()) + location = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName(); + + location.append(QLatin1String("/QtWebEngine/") % name); + return location; +} +} + +BrowserContextAdapter::BrowserContextAdapter(bool offTheRecord) + : m_offTheRecord(offTheRecord) + , m_browserContext(new BrowserContextQt(this)) + , m_httpCacheType(DiskHttpCache) + , m_persistentCookiesPolicy(AllowPersistentCookies) + , m_visitedLinksPolicy(TrackVisitedLinksOnDisk) + , m_client(0) + , m_httpCacheMaxSize(0) +{ +} + +BrowserContextAdapter::BrowserContextAdapter(const QString &storageName) + : m_name(storageName) + , m_offTheRecord(false) + , m_browserContext(new BrowserContextQt(this)) + , m_httpCacheType(DiskHttpCache) + , m_persistentCookiesPolicy(AllowPersistentCookies) + , m_visitedLinksPolicy(TrackVisitedLinksOnDisk) + , m_httpCacheMaxSize(0) +{ +} + +BrowserContextAdapter::~BrowserContextAdapter() +{ + if (m_downloadManagerDelegate) + content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE, m_downloadManagerDelegate.take()); +} + +void BrowserContextAdapter::setStorageName(const QString &storageName) +{ + if (storageName == m_name) + return; + m_name = storageName; + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->updateStorageSettings(); + m_visitedLinksManager.reset(); +} + +void BrowserContextAdapter::setOffTheRecord(bool offTheRecord) +{ + if (offTheRecord == m_offTheRecord) + return; + m_offTheRecord = offTheRecord; + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->updateStorageSettings(); + m_visitedLinksManager.reset(); +} + +BrowserContextQt *BrowserContextAdapter::browserContext() +{ + return m_browserContext.data(); +} + +WebEngineVisitedLinksManager *BrowserContextAdapter::visitedLinksManager() +{ + if (!m_visitedLinksManager) + m_visitedLinksManager.reset(new WebEngineVisitedLinksManager(this)); + return m_visitedLinksManager.data(); +} + +DownloadManagerDelegateQt *BrowserContextAdapter::downloadManagerDelegate() +{ + if (!m_downloadManagerDelegate) + m_downloadManagerDelegate.reset(new DownloadManagerDelegateQt(this)); + return m_downloadManagerDelegate.data(); +} + +void BrowserContextAdapter::setClient(BrowserContextAdapterClient *adapterClient) +{ + m_client = adapterClient; +} + +void BrowserContextAdapter::cancelDownload(quint32 downloadId) +{ + downloadManagerDelegate()->cancelDownload(downloadId); +} + +BrowserContextAdapter* BrowserContextAdapter::defaultContext() +{ + return WebEngineContext::current()->defaultBrowserContext(); +} + +BrowserContextAdapter* BrowserContextAdapter::offTheRecordContext() +{ + return WebEngineContext::current()->offTheRecordBrowserContext(); +} + +QString BrowserContextAdapter::dataPath() const +{ + if (m_offTheRecord) + return QString(); + if (!m_dataPath.isEmpty()) + return m_dataPath; + if (!m_name.isNull()) + return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation), m_name); + return QString(); +} + +void BrowserContextAdapter::setDataPath(const QString &path) +{ + if (m_dataPath == path) + return; + m_dataPath = path; + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->updateStorageSettings(); + m_visitedLinksManager.reset(); +} + +QString BrowserContextAdapter::cachePath() const +{ + if (m_offTheRecord) + return QString(); + if (!m_cachePath.isEmpty()) + return m_cachePath; + if (!m_name.isNull()) + return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), m_name); + return QString(); +} + +void BrowserContextAdapter::setCachePath(const QString &path) +{ + if (m_cachePath == path) + return; + m_cachePath = path; + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->updateHttpCache(); +} + +QString BrowserContextAdapter::cookiesPath() const +{ + if (m_offTheRecord) + return QString(); + QString basePath = dataPath(); + if (!basePath.isEmpty()) + return basePath % QLatin1String("/Coookies"); + return QString(); +} + +QString BrowserContextAdapter::httpCachePath() const +{ + if (m_offTheRecord) + return QString(); + QString basePath = cachePath(); + if (!basePath.isEmpty()) + return basePath % QLatin1String("/Cache"); + return QString(); +} + +QString BrowserContextAdapter::httpUserAgent() const +{ + if (m_httpUserAgent.isNull()) + return QString::fromStdString(ContentClientQt::getUserAgent()); + return m_httpUserAgent; +} + +void BrowserContextAdapter::setHttpUserAgent(const QString &userAgent) +{ + if (m_httpUserAgent == userAgent) + return; + m_httpUserAgent = userAgent; + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->updateUserAgent(); +} + +BrowserContextAdapter::HttpCacheType BrowserContextAdapter::httpCacheType() const +{ + if (isOffTheRecord() || httpCachePath().isEmpty()) + return MemoryHttpCache; + return m_httpCacheType; +} + +void BrowserContextAdapter::setHttpCacheType(BrowserContextAdapter::HttpCacheType newhttpCacheType) +{ + BrowserContextAdapter::HttpCacheType oldCacheType = httpCacheType(); + m_httpCacheType = newhttpCacheType; + if (oldCacheType == httpCacheType()) + return; + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->updateHttpCache(); +} + +BrowserContextAdapter::PersistentCookiesPolicy BrowserContextAdapter::persistentCookiesPolicy() const +{ + if (isOffTheRecord() || cookiesPath().isEmpty()) + return NoPersistentCookies; + return m_persistentCookiesPolicy; +} + +void BrowserContextAdapter::setPersistentCookiesPolicy(BrowserContextAdapter::PersistentCookiesPolicy newPersistentCookiesPolicy) +{ + BrowserContextAdapter::PersistentCookiesPolicy oldPolicy = persistentCookiesPolicy(); + m_persistentCookiesPolicy = newPersistentCookiesPolicy; + if (oldPolicy == persistentCookiesPolicy()) + return; + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->updateCookieStore(); +} + +BrowserContextAdapter::VisitedLinksPolicy BrowserContextAdapter::visitedLinksPolicy() const +{ + if (isOffTheRecord() || m_visitedLinksPolicy == DoNotTrackVisitedLinks) + return DoNotTrackVisitedLinks; + if (dataPath().isEmpty()) + return TrackVisitedLinksInMemory; + return m_visitedLinksPolicy; +} + +bool BrowserContextAdapter::trackVisitedLinks() const +{ + switch (visitedLinksPolicy()) { + case DoNotTrackVisitedLinks: + return false; + default: + break; + } + return true; +} + +bool BrowserContextAdapter::persistVisitedLinks() const +{ + switch (visitedLinksPolicy()) { + case DoNotTrackVisitedLinks: + case TrackVisitedLinksInMemory: + return false; + default: + break; + } + return true; +} + +void BrowserContextAdapter::setVisitedLinksPolicy(BrowserContextAdapter::VisitedLinksPolicy visitedLinksPolicy) +{ + if (m_visitedLinksPolicy == visitedLinksPolicy) + return; + m_visitedLinksPolicy = visitedLinksPolicy; + m_visitedLinksManager.reset(); +} + +int BrowserContextAdapter::httpCacheMaxSize() const +{ + return m_httpCacheMaxSize; +} + +void BrowserContextAdapter::setHttpCacheMaxSize(int maxSize) +{ + if (m_httpCacheMaxSize == maxSize) + return; + m_httpCacheMaxSize = maxSize; + if (m_browserContext->url_request_getter_.get()) + m_browserContext->url_request_getter_->updateHttpCache(); +} diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h new file mode 100644 index 000000000..1c12c465d --- /dev/null +++ b/src/core/browser_context_adapter.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BROWSER_CONTEXT_ADAPTER_H +#define BROWSER_CONTEXT_ADAPTER_H + +#include "qtwebenginecoreglobal.h" + +#include <QScopedPointer> +#include <QSharedData> +#include <QString> + +class BrowserContextAdapterClient; +class BrowserContextQt; +class DownloadManagerDelegateQt; +class WebEngineVisitedLinksManager; + +class QWEBENGINE_EXPORT BrowserContextAdapter : public QSharedData +{ +public: + explicit BrowserContextAdapter(bool offTheRecord = false); + explicit BrowserContextAdapter(const QString &storagePrefix); + virtual ~BrowserContextAdapter(); + + static BrowserContextAdapter* defaultContext(); + static BrowserContextAdapter* offTheRecordContext(); + + WebEngineVisitedLinksManager *visitedLinksManager(); + DownloadManagerDelegateQt *downloadManagerDelegate(); + + BrowserContextAdapterClient* client() { return m_client; } + + void setClient(BrowserContextAdapterClient *adapterClient); + void cancelDownload(quint32 downloadId); + + BrowserContextQt *browserContext(); + + QString storageName() const { return m_name; } + void setStorageName(const QString &storageName); + + bool isOffTheRecord() const { return m_offTheRecord; } + void setOffTheRecord(bool offTheRecord); + + QString dataPath() const; + void setDataPath(const QString &path); + + QString cachePath() const; + void setCachePath(const QString &path); + + QString httpCachePath() const; + QString cookiesPath() const; + + QString httpUserAgent() const; + void setHttpUserAgent(const QString &userAgent); + + // KEEP IN SYNC with API or add mapping layer + enum HttpCacheType { + MemoryHttpCache = 0, + DiskHttpCache + }; + + enum PersistentCookiesPolicy { + NoPersistentCookies = 0, + AllowPersistentCookies, + ForcePersistentCookies + }; + + enum VisitedLinksPolicy { + DoNotTrackVisitedLinks = 0, + TrackVisitedLinksInMemory, + TrackVisitedLinksOnDisk, + }; + + HttpCacheType httpCacheType() const; + void setHttpCacheType(BrowserContextAdapter::HttpCacheType); + + PersistentCookiesPolicy persistentCookiesPolicy() const; + void setPersistentCookiesPolicy(BrowserContextAdapter::PersistentCookiesPolicy); + + VisitedLinksPolicy visitedLinksPolicy() const; + void setVisitedLinksPolicy(BrowserContextAdapter::VisitedLinksPolicy); + + int httpCacheMaxSize() const; + void setHttpCacheMaxSize(int maxSize); + + bool trackVisitedLinks() const; + bool persistVisitedLinks() const; + +private: + QString m_name; + bool m_offTheRecord; + QScopedPointer<BrowserContextQt> m_browserContext; + QScopedPointer<WebEngineVisitedLinksManager> m_visitedLinksManager; + QScopedPointer<DownloadManagerDelegateQt> m_downloadManagerDelegate; + QString m_dataPath; + QString m_cachePath; + QString m_httpUserAgent; + HttpCacheType m_httpCacheType; + PersistentCookiesPolicy m_persistentCookiesPolicy; + VisitedLinksPolicy m_visitedLinksPolicy; + BrowserContextAdapterClient *m_client; + int m_httpCacheMaxSize; + + Q_DISABLE_COPY(BrowserContextAdapter) +}; + +#endif // BROWSER_CONTEXT_ADAPTER_H diff --git a/src/core/browser_context_adapter_client.h b/src/core/browser_context_adapter_client.h new file mode 100644 index 000000000..a9e7eb726 --- /dev/null +++ b/src/core/browser_context_adapter_client.h @@ -0,0 +1,76 @@ + /**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BROWSER_CONTEXT_ADAPTER_CLIENT_H +#define BROWSER_CONTEXT_ADAPTER_CLIENT_H + +#include "qtwebenginecoreglobal.h" +#include <QString> +#include <QUrl> + +class QWEBENGINE_EXPORT BrowserContextAdapterClient +{ +public: + // Keep in sync with content::DownloadItem::DownloadState + enum DownloadState { + // Download is actively progressing. + DownloadInProgress = 0, + // Download is completely finished. + DownloadCompleted, + // Download has been cancelled. + DownloadCancelled, + // This state indicates that the download has been interrupted. + DownloadInterrupted + }; + + struct DownloadItemInfo { + const quint32 id; + const QUrl url; + const int state; + const qint64 totalBytes; + const qint64 receivedBytes; + + QString path; + bool accepted; + }; + + virtual ~BrowserContextAdapterClient() { } + + virtual void downloadRequested(DownloadItemInfo &info) = 0; + virtual void downloadUpdated(const DownloadItemInfo &info) = 0; +}; + +#endif // BROWSER_CONTEXT_ADAPTER_CLIENT_H diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp index 44b6ca4ef..7fcbdee07 100644 --- a/src/core/browser_context_qt.cpp +++ b/src/core/browser_context_qt.cpp @@ -36,27 +36,21 @@ #include "browser_context_qt.h" +#include "browser_context_adapter.h" +#include "download_manager_delegate_qt.h" #include "type_conversion.h" #include "qtwebenginecoreglobal.h" #include "resource_context_qt.h" #include "url_request_context_getter_qt.h" -#include "base/files/scoped_temp_dir.h" #include "base/time/time.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "net/proxy/proxy_config_service.h" -#include <QByteArray> -#include <QCoreApplication> -#include <QDir> -#include <QStandardPaths> -#include <QString> -#include <QStringBuilder> - -BrowserContextQt::BrowserContextQt() +BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter) + : m_adapter(adapter) { - resourceContext.reset(new ResourceContextQt(this)); } BrowserContextQt::~BrowserContextQt() @@ -67,29 +61,17 @@ BrowserContextQt::~BrowserContextQt() base::FilePath BrowserContextQt::GetPath() const { - QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - if (dataLocation.isEmpty()) - dataLocation = QDir::homePath() % QDir::separator() % QChar::fromLatin1('.') % QCoreApplication::applicationName(); - - dataLocation.append(QDir::separator() % QLatin1String("QtWebEngine")); - dataLocation.append(QDir::separator() % QLatin1String("Default")); - return base::FilePath(toFilePathString(dataLocation)); + return toFilePath(m_adapter->dataPath()); } base::FilePath BrowserContextQt::GetCachePath() const { - QString cacheLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); - if (cacheLocation.isEmpty()) - cacheLocation = QDir::homePath() % QDir::separator() % QChar::fromLatin1('.') % QCoreApplication::applicationName(); - - cacheLocation.append(QDir::separator() % QLatin1String("QtWebEngine")); - cacheLocation.append(QDir::separator() % QLatin1String("Default")); - return base::FilePath(toFilePathString(cacheLocation)); + return toFilePath(m_adapter->cachePath()); } bool BrowserContextQt::IsOffTheRecord() const { - return false; + return m_adapter->isOffTheRecord(); } net::URLRequestContextGetter *BrowserContextQt::GetRequestContext() @@ -119,12 +101,14 @@ net::URLRequestContextGetter *BrowserContextQt::GetMediaRequestContextForStorage content::ResourceContext *BrowserContextQt::GetResourceContext() { + if (!resourceContext) + resourceContext.reset(new ResourceContextQt(this)); return resourceContext.get(); } content::DownloadManagerDelegate *BrowserContextQt::GetDownloadManagerDelegate() { - return downloadManagerDelegate.get(); + return m_adapter->downloadManagerDelegate(); } content::BrowserPluginGuestManager *BrowserContextQt::GetGuestManager() @@ -132,7 +116,7 @@ content::BrowserPluginGuestManager *BrowserContextQt::GetGuestManager() return 0; } -quota::SpecialStoragePolicy *BrowserContextQt::GetSpecialStoragePolicy() +storage::SpecialStoragePolicy *BrowserContextQt::GetSpecialStoragePolicy() { QT_NOT_YET_IMPLEMENTED return 0; @@ -143,9 +127,14 @@ content::PushMessagingService *BrowserContextQt::GetPushMessagingService() return 0; } +content::SSLHostStateDelegate* BrowserContextQt::GetSSLHostStateDelegate() +{ + return 0; +} + net::URLRequestContextGetter *BrowserContextQt::CreateRequestContext(content::ProtocolHandlerMap *protocol_handlers) { - url_request_getter_ = new URLRequestContextGetterQt(GetPath(), GetCachePath(), protocol_handlers); - static_cast<ResourceContextQt*>(resourceContext.get())->set_url_request_context_getter(url_request_getter_.get()); + url_request_getter_ = new URLRequestContextGetterQt(m_adapter, protocol_handlers); + static_cast<ResourceContextQt*>(GetResourceContext())->set_url_request_context_getter(url_request_getter_.get()); return url_request_getter_.get(); } diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h index 125c0fc46..ad46751a0 100644 --- a/src/core/browser_context_qt.h +++ b/src/core/browser_context_qt.h @@ -41,12 +41,16 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/resource_context.h" #include "net/url_request/url_request_context.h" -#include "download_manager_delegate_qt.h" + +#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE + +class BrowserContextAdapter; +class URLRequestContextGetterQt; class BrowserContextQt : public content::BrowserContext { public: - explicit BrowserContextQt(); + explicit BrowserContextQt(BrowserContextAdapter *); virtual ~BrowserContextQt(); @@ -62,14 +66,17 @@ public: virtual content::ResourceContext *GetResourceContext() Q_DECL_OVERRIDE; virtual content::DownloadManagerDelegate *GetDownloadManagerDelegate() Q_DECL_OVERRIDE; virtual content::BrowserPluginGuestManager* GetGuestManager() Q_DECL_OVERRIDE; - virtual quota::SpecialStoragePolicy *GetSpecialStoragePolicy() Q_DECL_OVERRIDE; + virtual storage::SpecialStoragePolicy *GetSpecialStoragePolicy() Q_DECL_OVERRIDE; virtual content::PushMessagingService* GetPushMessagingService() Q_DECL_OVERRIDE; + virtual content::SSLHostStateDelegate* GetSSLHostStateDelegate() Q_DECL_OVERRIDE; net::URLRequestContextGetter *CreateRequestContext(content::ProtocolHandlerMap *protocol_handlers); + BrowserContextAdapter* adapter() { return m_adapter; } private: scoped_ptr<content::ResourceContext> resourceContext; - scoped_refptr<net::URLRequestContextGetter> url_request_getter_; - scoped_ptr<DownloadManagerDelegateQt> downloadManagerDelegate; + scoped_refptr<URLRequestContextGetterQt> url_request_getter_; + BrowserContextAdapter *m_adapter; + friend class BrowserContextAdapter; DISALLOW_COPY_AND_ASSIGN(BrowserContextQt); }; diff --git a/src/core/certificate_error_controller.cpp b/src/core/certificate_error_controller.cpp index b5c705de3..365caed22 100644 --- a/src/core/certificate_error_controller.cpp +++ b/src/core/certificate_error_controller.cpp @@ -51,7 +51,7 @@ void CertificateErrorControllerPrivate::accept(bool accepted) CertificateErrorControllerPrivate::CertificateErrorControllerPrivate(int cert_error, const net::SSLInfo& ssl_info, const GURL &request_url, - ResourceType::Type resource_type, + content::ResourceType resource_type, bool _overridable, bool strict_enforcement, const base::Callback<void(bool)>& cb @@ -63,7 +63,7 @@ CertificateErrorControllerPrivate::CertificateErrorControllerPrivate(int cert_er , strictEnforcement(strict_enforcement) , callback(cb) { - if (ssl_info.cert) { + if (ssl_info.cert.get()) { validStart = toQt(ssl_info.cert->valid_start()); validExpiry = toQt(ssl_info.cert->valid_expiry()); } @@ -135,8 +135,6 @@ QString CertificateErrorController::errorString() const return getQStringForMessageId(IDS_CERT_ERROR_CONTAINS_ERRORS_DESCRIPTION); case CertificateNoRevocationMechanism: return getQStringForMessageId(IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DETAILS); - case CertificateUnableToCheckRevocation: - return getQStringForMessageId(IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DETAILS); case CertificateRevoked: return getQStringForMessageId(IDS_CERT_ERROR_REVOKED_CERT_DESCRIPTION); case CertificateInvalid: @@ -149,6 +147,7 @@ QString CertificateErrorController::errorString() const return getQStringForMessageId(IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION); case CertificateNameConstraintViolation: return getQStringForMessageId(IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DESCRIPTION); + case CertificateUnableToCheckRevocation: // Deprecated in Chromium. default: break; } diff --git a/src/core/certificate_error_controller.h b/src/core/certificate_error_controller.h index f1e7c5bd8..6d364fc9f 100644 --- a/src/core/certificate_error_controller.h +++ b/src/core/certificate_error_controller.h @@ -40,12 +40,13 @@ #include "qtwebenginecoreglobal.h" #include <QtCore/QDateTime> -#include <QtCore/QSharedData> #include <QtCore/QUrl> +QT_BEGIN_NAMESPACE + class CertificateErrorControllerPrivate; -class QWEBENGINE_EXPORT CertificateErrorController : public QSharedData { +class QWEBENGINE_EXPORT CertificateErrorController { public: CertificateErrorController(CertificateErrorControllerPrivate *p); ~CertificateErrorController(); @@ -107,4 +108,6 @@ private: CertificateErrorControllerPrivate* d; }; +QT_END_NAMESPACE + #endif // CERTIFICATE_ERROR_CONTROLLER_H diff --git a/src/core/certificate_error_controller_p.h b/src/core/certificate_error_controller_p.h index af0ce12aa..308131eb5 100644 --- a/src/core/certificate_error_controller_p.h +++ b/src/core/certificate_error_controller_p.h @@ -41,9 +41,11 @@ #include "certificate_error_controller.h" +QT_BEGIN_NAMESPACE + class CertificateErrorControllerPrivate { public: - CertificateErrorControllerPrivate(int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, ResourceType::Type resource_type, bool overridable, bool strict_enforcement, const base::Callback<void(bool)>& callback); + CertificateErrorControllerPrivate(int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, content::ResourceType resource_type, bool overridable, bool strict_enforcement, const base::Callback<void(bool)>& callback); void accept(bool accepted); @@ -54,7 +56,9 @@ public: CertificateErrorController::ResourceType resourceType; bool overridable; bool strictEnforcement; - const base::Callback<void(bool)>& callback; + const base::Callback<void(bool)> callback; }; +QT_END_NAMESPACE + #endif // CERTIFICATE_ERROR_CONTROLLER_P_H diff --git a/src/core/chrome_qt.gyp b/src/core/chrome_qt.gyp index 81ab2e881..703ce7525 100644 --- a/src/core/chrome_qt.gyp +++ b/src/core/chrome_qt.gyp @@ -21,8 +21,6 @@ '<(chromium_src_dir)/chrome/browser/media/desktop_media_list.h', '<(chromium_src_dir)/chrome/common/localized_error.cc', '<(chromium_src_dir)/chrome/common/localized_error.h', - '<(chromium_src_dir)/chrome/common/net/net_error_info.cc', - '<(chromium_src_dir)/chrome/common/net/net_error_info.h', ], }, { diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp index 6287bd7c0..8ea8ad20d 100644 --- a/src/core/chromium_gpu_helper.cpp +++ b/src/core/chromium_gpu_helper.cpp @@ -96,7 +96,8 @@ gpu::gles2::MailboxManager *mailbox_manager() gpu::gles2::Texture* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::Mailbox& mailbox) { - return mailboxManager->ConsumeTexture(target, mailbox); + Q_UNUSED(target); + return mailboxManager->ConsumeTexture(mailbox); } unsigned int service_id(gpu::gles2::Texture *tex) diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index 9e97e3226..bb71d0d35 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -156,6 +156,7 @@ RenderText* RenderText::CreateNativeInstance() return 0; } +#if defined(OS_LINUX) PlatformFont* PlatformFont::CreateDefault() { QT_NOT_USED; @@ -173,6 +174,7 @@ PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string&, int) QT_NOT_USED; return 0; } +#endif } // namespace gfx diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 870c6ae2d..15d8e18dd 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -63,8 +63,6 @@ void ClipboardChangeObserver::trackChange(QClipboard::Mode mode) ++sequenceNumber[mode]; } -namespace ui { - namespace { const char kMimeTypeBitmap[] = "image/bmp"; @@ -83,6 +81,76 @@ QMimeData *getUncommittedData() } // namespace +namespace ui { + +// Factory function +Clipboard* Clipboard::Create() { + return new ClipboardQt; +} + +Clipboard::FormatType Clipboard::GetFormatType(const std::string& format_string) +{ + return FormatType::Deserialize(format_string); +} + +const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() +{ + CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeText)); + return type; +} + +const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() +{ + return GetPlainTextFormatType(); +} + +const Clipboard::FormatType& Clipboard::GetUrlFormatType() +{ + return GetPlainTextFormatType(); +} + +const Clipboard::FormatType& Clipboard::GetUrlWFormatType() +{ + return GetPlainTextWFormatType(); +} + +const Clipboard::FormatType& Clipboard::GetHtmlFormatType() +{ + CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML)); + return type; +} + +const Clipboard::FormatType& Clipboard::GetRtfFormatType() +{ + CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeRTF)); + return type; +} + +const Clipboard::FormatType& Clipboard::GetBitmapFormatType() +{ + CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap)); + return type; +} + +const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() +{ + CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste)); + return type; +} + +const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() +{ + CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomDataCopy)); + return type; +} + +const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() +{ + CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData)); + return type; +} + + Clipboard::FormatType::FormatType() { } @@ -111,15 +179,16 @@ bool Clipboard::FormatType::Equals(const FormatType& other) const return data_ == other.data_; } -Clipboard::Clipboard() +#if defined(OS_WIN) || defined(USE_AURA) +bool Clipboard::FormatType::operator<(const FormatType& other) const { + return data_.compare(other.data_) < 0; } +#endif -Clipboard::~Clipboard() -{ -} +} // namespace ui -void Clipboard::WriteObjects(ClipboardType type, const ObjectMap& objects) +void ClipboardQt::WriteObjects(ui::ClipboardType type, const ObjectMap& objects) { DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardType(type)); @@ -129,45 +198,45 @@ void Clipboard::WriteObjects(ClipboardType type, const ObjectMap& objects) // Commit the accumulated data. if (uncommittedData) - QGuiApplication::clipboard()->setMimeData(uncommittedData.take(), type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + QGuiApplication::clipboard()->setMimeData(uncommittedData.take(), type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); - if (type == CLIPBOARD_TYPE_COPY_PASTE) { + if (type == ui::CLIPBOARD_TYPE_COPY_PASTE) { ObjectMap::const_iterator text_iter = objects.find(CBF_TEXT); if (text_iter != objects.end()) { // Copy text and SourceTag to the selection clipboard. ObjectMap::const_iterator next_iter = text_iter; - WriteObjects(CLIPBOARD_TYPE_SELECTION, ObjectMap(text_iter, ++next_iter)); + WriteObjects(ui::CLIPBOARD_TYPE_SELECTION, ObjectMap(text_iter, ++next_iter)); } } } -void Clipboard::WriteText(const char* text_data, size_t text_len) +void ClipboardQt::WriteText(const char* text_data, size_t text_len) { getUncommittedData()->setText(QString::fromUtf8(text_data, text_len)); } -void Clipboard::WriteHTML(const char* markup_data, size_t markup_len, const char* url_data, size_t url_len) +void ClipboardQt::WriteHTML(const char* markup_data, size_t markup_len, const char* url_data, size_t url_len) { getUncommittedData()->setHtml(QString::fromUtf8(markup_data, markup_len)); } -void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) +void ClipboardQt::WriteRTF(const char* rtf_data, size_t data_len) { getUncommittedData()->setData(QString::fromLatin1(kMimeTypeRTF), QByteArray(rtf_data, data_len)); } -void Clipboard::WriteWebSmartPaste() +void ClipboardQt::WriteWebSmartPaste() { getUncommittedData()->setData(QString::fromLatin1(kMimeTypeWebkitSmartPaste), QByteArray()); } -void Clipboard::WriteBitmap(const SkBitmap& bitmap) +void ClipboardQt::WriteBitmap(const SkBitmap& bitmap) { QImage image(reinterpret_cast<const uchar *>(bitmap.getPixels()), bitmap.width(), bitmap.height(), QImage::Format_ARGB32); getUncommittedData()->setImageData(image.copy()); } -void Clipboard::WriteBookmark(const char* title_data, size_t title_len, const char* url_data, size_t url_len) +void ClipboardQt::WriteBookmark(const char* title_data, size_t title_len, const char* url_data, size_t url_len) { // FIXME: Untested, seems to be used only for drag-n-drop. // Write as a mozilla url (UTF16: URL, newline, title). @@ -181,23 +250,23 @@ void Clipboard::WriteBookmark(const char* title_data, size_t title_len, const ch getUncommittedData()->setData(QString::fromLatin1(kMimeTypeMozillaURL), data); } -void Clipboard::WriteData(const FormatType& format, const char* data_data, size_t data_len) +void ClipboardQt::WriteData(const FormatType& format, const char* data_data, size_t data_len) { - getUncommittedData()->setData(QString::fromStdString(format.data_), QByteArray(data_data, data_len)); + getUncommittedData()->setData(QString::fromStdString(format.ToString()), QByteArray(data_data, data_len)); } -bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format, ClipboardType type) const +bool ClipboardQt::IsFormatAvailable(const ui::Clipboard::FormatType& format, ui::ClipboardType type) const { - const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); - return mimeData->hasFormat(QString::fromStdString(format.data_)); + const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + return mimeData->hasFormat(QString::fromStdString(format.ToString())); } -void Clipboard::Clear(ClipboardType type) +void ClipboardQt::Clear(ui::ClipboardType type) { - QGuiApplication::clipboard()->clear(type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + QGuiApplication::clipboard()->clear(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); } -void Clipboard::ReadAvailableTypes(ui::ClipboardType type, std::vector<base::string16>* types, bool* contains_filenames) const +void ClipboardQt::ReadAvailableTypes(ui::ClipboardType type, std::vector<base::string16>* types, bool* contains_filenames) const { if (!types || !contains_filenames) { NOTREACHED(); @@ -205,29 +274,29 @@ void Clipboard::ReadAvailableTypes(ui::ClipboardType type, std::vector<base::str } types->clear(); - const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); Q_FOREACH (const QString &mimeType, mimeData->formats()) types->push_back(toString16(mimeType)); *contains_filenames = false; const QByteArray customData = mimeData->data(QString::fromLatin1(kMimeTypeWebCustomDataCopy)); - ReadCustomDataTypes(customData.constData(), customData.size(), types); + ui::ReadCustomDataTypes(customData.constData(), customData.size(), types); } -void Clipboard::ReadText(ClipboardType type, base::string16* result) const +void ClipboardQt::ReadText(ui::ClipboardType type, base::string16* result) const { - const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); *result = toString16(mimeData->text()); } -void Clipboard::ReadAsciiText(ClipboardType type, std::string* result) const +void ClipboardQt::ReadAsciiText(ui::ClipboardType type, std::string* result) const { - const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); *result = mimeData->text().toStdString(); } -void Clipboard::ReadHTML(ClipboardType type, base::string16* markup, std::string* src_url, uint32* fragment_start, uint32* fragment_end) const +void ClipboardQt::ReadHTML(ui::ClipboardType type, base::string16* markup, std::string* src_url, uint32* fragment_start, uint32* fragment_end) const { markup->clear(); if (src_url) @@ -235,23 +304,23 @@ void Clipboard::ReadHTML(ClipboardType type, base::string16* markup, std::string *fragment_start = 0; *fragment_end = 0; - const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); *markup = toString16(mimeData->html()); *fragment_end = static_cast<uint32>(markup->length()); } -void Clipboard::ReadRTF(ClipboardType type, std::string* result) const +void ClipboardQt::ReadRTF(ui::ClipboardType type, std::string* result) const { - const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); const QByteArray byteArray = mimeData->data(QString::fromLatin1(kMimeTypeRTF)); *result = std::string(byteArray.constData(), byteArray.length()); } -SkBitmap Clipboard::ReadImage(ClipboardType type) const +SkBitmap ClipboardQt::ReadImage(ui::ClipboardType type) const { // FIXME: Untested, pasting image data seems to only be supported through // FileReader.readAsDataURL in JavaScript and this isn't working down the pipe for some reason. - const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); QImage image = qvariant_cast<QImage>(mimeData->imageData()); Q_ASSERT(image.format() == QImage::Format_ARGB32); @@ -265,97 +334,28 @@ SkBitmap Clipboard::ReadImage(ClipboardType type) const return copy; } -void Clipboard::ReadCustomData(ClipboardType clipboard_type, const base::string16& type, base::string16* result) const +void ClipboardQt::ReadCustomData(ui::ClipboardType clipboard_type, const base::string16& type, base::string16* result) const { - const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(clipboard_type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); + const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(clipboard_type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); const QByteArray customData = mimeData->data(QString::fromLatin1(kMimeTypeWebCustomDataCopy)); - ReadCustomDataForType(customData.constData(), customData.size(), type, result); + ui::ReadCustomDataForType(customData.constData(), customData.size(), type, result); } -void Clipboard::ReadBookmark(base::string16* title, std::string* url) const +void ClipboardQt::ReadBookmark(base::string16* title, std::string* url) const { NOTIMPLEMENTED(); } -void Clipboard::ReadData(const FormatType& format, std::string* result) const +void ClipboardQt::ReadData(const FormatType& format, std::string* result) const { const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData(); - const QByteArray byteArray = mimeData->data(QString::fromStdString(format.data_)); + const QByteArray byteArray = mimeData->data(QString::fromStdString(format.ToString())); *result = std::string(byteArray.constData(), byteArray.length()); } -uint64 Clipboard::GetSequenceNumber(ClipboardType type) -{ - return clipboardChangeObserver()->getSequenceNumber(type == CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); -} - -Clipboard::FormatType Clipboard::GetFormatType(const std::string& format_string) -{ - return FormatType::Deserialize(format_string); -} - -const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() -{ - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeText)); - return type; -} - -const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() -{ - return GetPlainTextFormatType(); -} - -const Clipboard::FormatType& Clipboard::GetUrlFormatType() -{ - return GetPlainTextFormatType(); -} - -const Clipboard::FormatType& Clipboard::GetUrlWFormatType() +uint64 ClipboardQt::GetSequenceNumber(ui::ClipboardType type) { - return GetPlainTextWFormatType(); + return clipboardChangeObserver()->getSequenceNumber(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); } -const Clipboard::FormatType& Clipboard::GetHtmlFormatType() -{ - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML)); - return type; -} - -const Clipboard::FormatType& Clipboard::GetRtfFormatType() -{ - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeRTF)); - return type; -} - -const Clipboard::FormatType& Clipboard::GetBitmapFormatType() -{ - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap)); - return type; -} - -const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() -{ - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste)); - return type; -} - -const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() -{ - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomDataCopy)); - return type; -} - -const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() -{ - CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData)); - return type; -} - -#if defined(OS_WIN) || defined(USE_AURA) -bool Clipboard::FormatType::operator<(const FormatType& other) const -{ - return data_.compare(other.data_) < 0; -} -#endif -} // namespace ui diff --git a/src/core/clipboard_qt.h b/src/core/clipboard_qt.h index 87f2c2c2a..02db41c25 100644 --- a/src/core/clipboard_qt.h +++ b/src/core/clipboard_qt.h @@ -37,6 +37,8 @@ #ifndef CLIPBOARD_QT_H #define CLIPBOARD_QT_H +#include "ui/base/clipboard/clipboard.h" + #include <QClipboard> #include <QMap> #include <QObject> @@ -56,4 +58,34 @@ private: QMap<QClipboard::Mode, quint64> sequenceNumber; }; +class ClipboardQt : public ui::Clipboard { +public: + virtual uint64 GetSequenceNumber(ui::ClipboardType type) Q_DECL_OVERRIDE; + virtual bool IsFormatAvailable(const FormatType& format, ui::ClipboardType type) const Q_DECL_OVERRIDE; + virtual void Clear(ui::ClipboardType type) Q_DECL_OVERRIDE; + virtual void ReadAvailableTypes(ui::ClipboardType type, std::vector<base::string16>* types, bool* contains_filenames) const Q_DECL_OVERRIDE; + virtual void ReadText(ui::ClipboardType type, base::string16* result) const Q_DECL_OVERRIDE; + virtual void ReadAsciiText(ui::ClipboardType type, std::string* result) const Q_DECL_OVERRIDE; + virtual void ReadHTML(ui::ClipboardType type, + base::string16* markup, + std::string* src_url, + uint32* fragment_start, + uint32* fragment_end) const Q_DECL_OVERRIDE; + virtual void ReadRTF(ui::ClipboardType type, std::string* result) const Q_DECL_OVERRIDE; + virtual SkBitmap ReadImage(ui::ClipboardType type) const Q_DECL_OVERRIDE; + virtual void ReadCustomData(ui::ClipboardType clipboard_type, const base::string16& type, base::string16* result) const Q_DECL_OVERRIDE; + virtual void ReadBookmark(base::string16* title, std::string* url) const Q_DECL_OVERRIDE; + virtual void ReadData(const FormatType& format, std::string* result) const Q_DECL_OVERRIDE; + +protected: + virtual void WriteObjects(ui::ClipboardType type, const ObjectMap& objects) Q_DECL_OVERRIDE; + virtual void WriteText(const char* text_data, size_t text_len) Q_DECL_OVERRIDE; + virtual void WriteHTML(const char* markup_data, size_t markup_len, const char* url_data, size_t url_len) Q_DECL_OVERRIDE; + virtual void WriteRTF(const char* rtf_data, size_t data_len) Q_DECL_OVERRIDE; + virtual void WriteBookmark(const char* title_data, size_t title_len, const char* url_data, size_t url_len) Q_DECL_OVERRIDE; + virtual void WriteWebSmartPaste() Q_DECL_OVERRIDE; + virtual void WriteBitmap(const SkBitmap& bitmap) Q_DECL_OVERRIDE; + virtual void WriteData(const FormatType& format, const char* data_data, size_t data_len) Q_DECL_OVERRIDE; +}; + #endif diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index 315987cd3..5ae5fef7d 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -29,6 +29,8 @@ IPC_MESSAGE_ROUTED1(QtRenderViewObserver_FetchDocumentMarkup, IPC_MESSAGE_ROUTED1(QtRenderViewObserver_FetchDocumentInnerText, uint64 /* requestId */) +IPC_MESSAGE_ROUTED1(WebChannelIPCTransport_Message, std::vector<char> /*binaryJSON*/) + //----------------------------------------------------------------------------- // WebContents messages // These are messages sent from the renderer back to the browser process. @@ -42,3 +44,5 @@ IPC_MESSAGE_ROUTED2(QtRenderViewObserverHost_DidFetchDocumentInnerText, base::string16 /* innerText */) IPC_MESSAGE_ROUTED0(QtRenderViewObserverHost_DidFirstVisuallyNonEmptyLayout) + +IPC_MESSAGE_ROUTED1(WebChannelIPCTransportHost_SendMessage, std::vector<char> /*binaryJSON*/) diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri index 57fb39f6e..500e04448 100644 --- a/src/core/config/desktop_linux.pri +++ b/src/core/config/desktop_linux.pri @@ -13,5 +13,7 @@ GYP_CONFIG += \ use_gnome_keyring=0 \ use_kerberos=0 \ use_pango=0 \ + host_clang=0 \ + clang=0 \ !contains(QT_CONFIG, pulseaudio): GYP_CONFIG += use_pulseaudio=0 diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 4948d1d8d..7251e2db0 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -55,17 +55,22 @@ #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_share_group.h" +#include "access_token_store_qt.h" #include "browser_context_qt.h" #include "certificate_error_controller.h" #include "certificate_error_controller_p.h" #include "desktop_screen_qt.h" #include "dev_tools_http_handler_delegate_qt.h" +#ifdef QT_USE_POSITIONING +#include "location_provider_qt.h" +#endif #include "media_capture_devices_dispatcher.h" #include "resource_dispatcher_host_delegate_qt.h" #include "web_contents_delegate_qt.h" #include "access_token_store_qt.h" #include <QGuiApplication> +#include <QLocale> #include <QOpenGLContext> #include <qpa/qplatformnativeinterface.h> @@ -203,12 +208,10 @@ public: void PreMainMessageLoopRun() Q_DECL_OVERRIDE { - m_browserContext.reset(new BrowserContextQt()); } void PostMainMessageLoopRun() { - m_browserContext.reset(); } int PreCreateThreads() Q_DECL_OVERRIDE @@ -219,13 +222,7 @@ public: return 0; } - BrowserContextQt* browser_context() const { - return m_browserContext.get(); - } - private: - scoped_ptr<BrowserContextQt> m_browserContext; - DISALLOW_COPY_AND_ASSIGN(BrowserMainPartsQt); }; @@ -246,7 +243,7 @@ public: m_handle = pni->nativeResourceForContext(QByteArrayLiteral("cglcontextobj"), qtContext); else if (platform == QLatin1String("qnx")) m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else if (platform == QLatin1String("eglfs")) + else if (platform == QLatin1String("eglfs") || platform == QLatin1String("wayland")) m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); else if (platform == QLatin1String("windows")) { if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) @@ -342,7 +339,7 @@ void ContentBrowserClientQt::ResourceDispatcherHostCreated() gfx::GLShareGroup *ContentBrowserClientQt::GetInProcessGpuShareGroup() { - if (!m_shareGroupQtQuick) + if (!m_shareGroupQtQuick.get()) m_shareGroupQtQuick = new ShareGroupQtQuick; return m_shareGroupQtQuick.get(); } @@ -352,7 +349,7 @@ content::MediaObserver *ContentBrowserClientQt::GetMediaObserver() return MediaCaptureDevicesDispatcher::GetInstance(); } -void ContentBrowserClientQt::OverrideWebkitPrefs(content::RenderViewHost *rvh, const GURL &url, WebPreferences *web_prefs) +void ContentBrowserClientQt::OverrideWebkitPrefs(content::RenderViewHost *rvh, const GURL &url, content::WebPreferences *web_prefs) { Q_UNUSED(url); if (content::WebContents *webContents = rvh->GetDelegate()->GetAsWebContents()) @@ -364,25 +361,9 @@ content::AccessTokenStore *ContentBrowserClientQt::CreateAccessTokenStore() return new AccessTokenStoreQt; } -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, content::URLRequestInterceptorScopedVector request_interceptors) +net::URLRequestContextGetter* ContentBrowserClientQt::CreateRequestContext(content::BrowserContext* browser_context, content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) { - 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(); - } + return static_cast<BrowserContextQt*>(browser_context)->CreateRequestContext(protocol_handlers); } content::QuotaPermissionContext *ContentBrowserClientQt::CreateQuotaPermissionContext() @@ -392,8 +373,9 @@ content::QuotaPermissionContext *ContentBrowserClientQt::CreateQuotaPermissionCo void ContentBrowserClientQt::AllowCertificateError(int render_process_id, int render_frame_id, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, - ResourceType::Type resource_type, + content::ResourceType resource_type, bool overridable, bool strict_enforcement, + bool expired_previous_decision, const base::Callback<void(bool)>& callback, content::CertificateRequestResultType* result) { @@ -405,23 +387,60 @@ void ContentBrowserClientQt::AllowCertificateError(int render_process_id, int re if (content::WebContents *webContents = frameHost->GetRenderViewHost()->GetDelegate()->GetAsWebContents()) contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); - QExplicitlySharedDataPointer<CertificateErrorController> errorController(new CertificateErrorController(new CertificateErrorControllerPrivate(cert_error, ssl_info, request_url, resource_type, overridable, strict_enforcement, callback))); + QSharedPointer<CertificateErrorController> errorController(new CertificateErrorController(new CertificateErrorControllerPrivate(cert_error, ssl_info, request_url, resource_type, overridable, strict_enforcement, callback))); contentsDelegate->allowCertificateError(errorController); } -void ContentBrowserClientQt::RequestGeolocationPermission(content::WebContents *webContents, - int bridge_id, - const GURL &requesting_frame, - bool user_gesture, - base::Callback<void(bool)> result_callback, - base::Closure *cancel_callback) +void ContentBrowserClientQt::RequestPermission(content::PermissionType permission, + content::WebContents* web_contents, + int bridge_id, + const GURL& requesting_frame, + bool user_gesture, + const base::Callback<void(bool)>& result_callback) { - Q_UNUSED(webContents); Q_UNUSED(bridge_id); - Q_UNUSED(requesting_frame); Q_UNUSED(user_gesture); - Q_UNUSED(cancel_callback); + WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(web_contents->GetDelegate()); + Q_ASSERT(contentsDelegate); + if (permission == content::PERMISSION_GEOLOCATION) + contentsDelegate->requestGeolocationPermission(requesting_frame, result_callback); + else + result_callback.Run(false); +} + + +void ContentBrowserClientQt::CancelPermissionRequest(content::PermissionType permission, + content::WebContents* web_contents, + int bridge_id, + const GURL& requesting_frame) +{ + Q_UNUSED(bridge_id); + WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(web_contents->GetDelegate()); + Q_ASSERT(contentsDelegate); + if (permission == content::PERMISSION_GEOLOCATION) + contentsDelegate->cancelGeolocationPermissionRequest(requesting_frame); +} - // TODO: Add geolocation support - result_callback.Run(false); +blink::WebNotificationPermission ContentBrowserClientQt::CheckDesktopNotificationPermission(const GURL&, content::ResourceContext *, int ) +{ + return blink::WebNotificationPermission::WebNotificationPermissionDenied; +} + +content::LocationProvider *ContentBrowserClientQt::OverrideSystemLocationProvider() +{ +#ifdef QT_USE_POSITIONING + return new LocationProviderQt; +#else + return 0; // Leave it up to Chromium to figure something out. +#endif +} + +std::string ContentBrowserClientQt::GetApplicationLocale() +{ + return QLocale().bcp47Name().toStdString(); +} + +content::DevToolsManagerDelegate* ContentBrowserClientQt::GetDevToolsManagerDelegate() +{ + return new DevToolsManagerDelegateQt; } diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index f1ecf5825..42ee25907 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -40,6 +40,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "content/public/browser/content_browser_client.h" +#include "third_party/WebKit/public/platform/WebNotificationPermission.h" #include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE @@ -50,8 +51,10 @@ class URLRequestContextGetter; namespace content { class BrowserContext; class BrowserMainParts; +class DevToolsManagerDelegate; class RenderProcessHost; class RenderViewHostDelegateView; +class ResourceContext; class WebContentsViewPort; class WebContents; struct MainFunctionParams; @@ -63,7 +66,6 @@ class GLShareGroup; class BrowserContextQt; class BrowserMainPartsQt; -class DevToolsHttpHandlerDelegateQt; class ResourceDispatcherHostDelegateQt; class ShareGroupQtQuick; @@ -78,37 +80,42 @@ public: virtual void ResourceDispatcherHostCreated() Q_DECL_OVERRIDE; virtual gfx::GLShareGroup* GetInProcessGpuShareGroup() Q_DECL_OVERRIDE; virtual content::MediaObserver* GetMediaObserver() Q_DECL_OVERRIDE; - virtual void OverrideWebkitPrefs(content::RenderViewHost *, const GURL &, WebPreferences *) Q_DECL_OVERRIDE; - virtual content::AccessTokenStore *CreateAccessTokenStore() Q_DECL_OVERRIDE; + virtual content::AccessTokenStore* CreateAccessTokenStore() Q_DECL_OVERRIDE; virtual content::QuotaPermissionContext *CreateQuotaPermissionContext() Q_DECL_OVERRIDE; + virtual void OverrideWebkitPrefs(content::RenderViewHost *, const GURL &, content::WebPreferences *) Q_DECL_OVERRIDE; virtual void AllowCertificateError( int render_process_id, int render_frame_id, int cert_error, const net::SSLInfo& ssl_info, const GURL& request_url, - ResourceType::Type resource_type, + content::ResourceType resource_type, bool overridable, bool strict_enforcement, + bool expired_previous_decision, const base::Callback<void(bool)>& callback, content::CertificateRequestResultType* result) Q_DECL_OVERRIDE; - virtual void RequestGeolocationPermission( - content::WebContents *webContents, + virtual void RequestPermission( + content::PermissionType permission, + content::WebContents* web_contents, int bridge_id, - const GURL &requesting_frame, + const GURL& requesting_frame, bool user_gesture, - base::Callback<void(bool)> result_callback, - base::Closure *cancel_callback) Q_DECL_OVERRIDE; + const base::Callback<void(bool)>& result_callback) Q_DECL_OVERRIDE; + virtual void CancelPermissionRequest(content::PermissionType permission, + content::WebContents* web_contents, + int bridge_id, + const GURL& requesting_frame) Q_DECL_OVERRIDE; + content::LocationProvider* OverrideSystemLocationProvider() Q_DECL_OVERRIDE; + content::DevToolsManagerDelegate *GetDevToolsManagerDelegate() Q_DECL_OVERRIDE; + virtual net::URLRequestContextGetter *CreateRequestContext(content::BrowserContext *browser_context, content::ProtocolHandlerMap *protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptorss) Q_DECL_OVERRIDE; - BrowserContextQt* browser_context(); + virtual blink::WebNotificationPermission CheckDesktopNotificationPermission(const GURL& source_origin, content::ResourceContext* context, int render_process_id) Q_DECL_OVERRIDE; - virtual net::URLRequestContextGetter *CreateRequestContext(content::BrowserContext *content_browser_context, content::ProtocolHandlerMap *protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptorss) Q_DECL_OVERRIDE; - - void enableInspector(bool); + virtual std::string GetApplicationLocale() Q_DECL_OVERRIDE; private: BrowserMainPartsQt* m_browserMainParts; - scoped_ptr<DevToolsHttpHandlerDelegateQt> m_devtools; scoped_ptr<ResourceDispatcherHostDelegateQt> m_resourceDispatcherHostDelegate; scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick; }; diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index e41888976..a997e398c 100644 --- a/src/core/content_main_delegate_qt.cpp +++ b/src/core/content_main_delegate_qt.cpp @@ -52,6 +52,8 @@ #include "renderer/content_renderer_client_qt.h" #include "web_engine_library_info.h" +#include <QLocale> + static base::StringPiece PlatformResourceProvider(int key) { if (key == IDR_DIR_HEADER_HTML) { base::StringPiece html_data = ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_DIR_HEADER_HTML); @@ -63,7 +65,7 @@ static base::StringPiece PlatformResourceProvider(int key) { void ContentMainDelegateQt::PreSandboxStartup() { net::NetModule::SetResourceProvider(PlatformResourceProvider); - ui::ResourceBundle::InitSharedInstanceWithLocale(l10n_util::GetApplicationLocale(std::string("en-US")), 0); + ui::ResourceBundle::InitSharedInstanceWithLocale(QLocale().name().toStdString(), 0, ui::ResourceBundle::LOAD_COMMON_RESOURCES); // Suppress info, warning and error messages per default. int logLevel = logging::LOG_FATAL; diff --git a/src/core/core_common.pri b/src/core/core_common.pri new file mode 100644 index 000000000..2e9ee4198 --- /dev/null +++ b/src/core/core_common.pri @@ -0,0 +1,8 @@ +# NOTE: The TARGET, QT, QT_PRIVATE variables are used in both core_module.pro and core_gyp_generator.pro +# gyp/ninja will take care of the compilation, qmake/make will finish with linking and install. + +TARGET = QtWebEngineCore +QT += qml quick webchannel +QT_PRIVATE += quick-private gui-private core-private + +qtHaveModule(positioning):QT += positioning diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro index 3817c334b..3980dcc5a 100644 --- a/src/core/core_gyp_generator.pro +++ b/src/core/core_gyp_generator.pro @@ -7,11 +7,7 @@ GYPINCLUDES += qtwebengine.gypi TEMPLATE = lib -# NOTE: The TARGET, QT, QT_PRIVATE variables must match those in core_module.pro. -# gyp/ninja will take care of the compilation, qmake/make will finish with linking and install. -TARGET = QtWebEngineCore -QT += qml quick -QT_PRIVATE += gui-private +include(core_common.pri) # Defining keywords such as 'signal' clashes with the chromium code base. DEFINES += QT_NO_KEYWORDS \ @@ -35,6 +31,7 @@ SOURCES = \ access_token_store_qt.cpp \ browser_accessibility_manager_qt.cpp \ browser_accessibility_qt.cpp \ + browser_context_adapter.cpp \ browser_context_qt.cpp \ certificate_error_controller.cpp \ chromium_gpu_helper.cpp \ @@ -53,6 +50,7 @@ SOURCES = \ javascript_dialog_controller.cpp \ javascript_dialog_manager_qt.cpp \ media_capture_devices_dispatcher.cpp \ + native_web_keyboard_event_qt.cpp \ network_delegate_qt.cpp \ ozone_platform_eglfs.cpp \ process_main.cpp \ @@ -61,6 +59,7 @@ SOURCES = \ render_widget_host_view_qt.cpp \ renderer/content_renderer_client_qt.cpp \ renderer/qt_render_view_observer.cpp \ + renderer/web_channel_ipc_transport.cpp \ resource_bundle_qt.cpp \ resource_context_qt.cpp \ resource_dispatcher_host_delegate_qt.cpp \ @@ -68,6 +67,7 @@ SOURCES = \ surface_factory_qt.cpp \ url_request_context_getter_qt.cpp \ url_request_qrc_job_qt.cpp \ + web_channel_ipc_transport_host.cpp \ web_contents_adapter.cpp \ web_contents_delegate_qt.cpp \ web_contents_view_qt.cpp \ @@ -83,6 +83,8 @@ HEADERS = \ access_token_store_qt.h \ browser_accessibility_manager_qt.h \ browser_accessibility_qt.h \ + browser_context_adapter.h \ + browser_context_adapter_client.h \ browser_context_qt.h \ certificate_error_controller_p.h \ certificate_error_controller.h \ @@ -112,12 +114,15 @@ HEADERS = \ render_widget_host_view_qt_delegate.h \ renderer/content_renderer_client_qt.h \ renderer/qt_render_view_observer.h \ + renderer/web_channel_ipc_transport.h \ resource_context_qt.h \ resource_dispatcher_host_delegate_qt.h \ stream_video_node.h \ surface_factory_qt.h \ + type_conversion.h \ url_request_context_getter_qt.h \ url_request_qrc_job_qt.h \ + web_channel_ipc_transport_host.h \ web_contents_adapter.h \ web_contents_adapter_client.h \ web_contents_adapter_p.h \ @@ -130,3 +135,9 @@ HEADERS = \ web_engine_visited_links_manager.h \ web_event_factory.h \ yuv_video_node.h + +qtHaveModule(positioning) { + SOURCES += location_provider_qt.cpp + HEADERS += location_provider_qt.h + DEFINES += QT_USE_POSITIONING=1 +} diff --git a/src/core/core_module.pro b/src/core/core_module.pro index 8e445bd3a..afa11d31f 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -1,9 +1,6 @@ MODULE = webenginecore -TARGET = QtWebEngineCore - -QT += qml quick -QT_PRIVATE += gui-private +include(core_common.pri) # Needed to set a CFBundleIdentifier QMAKE_INFO_PLIST = Info_mac.plist diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index e12873c81..33ffbc66a 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -55,6 +55,7 @@ #include "base/bind.h" #include "cc/output/delegated_frame_data.h" #include "cc/quads/checkerboard_draw_quad.h" +#include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/draw_quad.h" #include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/solid_color_draw_quad.h" @@ -62,80 +63,60 @@ #include "cc/quads/texture_draw_quad.h" #include "cc/quads/tile_draw_quad.h" #include "cc/quads/yuv_video_draw_quad.h" +#include "content/common/host_shared_bitmap_manager.h" #include <QOpenGLContext> -#include <QOpenGLFramebufferObject> #include <QOpenGLFunctions> -#include <QSGAbstractRenderer> -#include <QSGEngine> #include <QSGSimpleRectNode> #include <QSGSimpleTextureNode> #include <QSGTexture> +#include <private/qsgadaptationlayer_p.h> #if !defined(QT_NO_EGL) #include <EGL/egl.h> #include <EGL/eglext.h> #endif -class RenderPassTexture : public QSGTexture, protected QOpenGLFunctions -{ -public: - RenderPassTexture(const cc::RenderPass::Id &id); - - 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; } - QSGNode *rootNode() { return m_rootNode.data(); } - - void grab(); - -private: - cc::RenderPass::Id m_id; - QRect m_rect; - GLenum m_format; - - QScopedPointer<QSGEngine> m_sgEngine; - QScopedPointer<QSGRootNode> m_rootNode; - QScopedPointer<QSGAbstractRenderer> m_renderer; - QScopedPointer<QOpenGLFramebufferObject> m_fbo; -}; - class MailboxTexture : public QSGTexture, protected QOpenGLFunctions { public: - MailboxTexture(const cc::TransferableResource &resource); + MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QSize textureSize); 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; } - cc::ReturnedResource returnResource(); + gpu::MailboxHolder &mailboxHolder() { return m_mailboxHolder; } void fetchTexture(gpu::gles2::MailboxManager *mailboxManager); void setTarget(GLenum target); - void incImportCount() { ++m_importCount; } private: - cc::TransferableResource m_resource; + gpu::MailboxHolder m_mailboxHolder; int m_textureId; QSize m_textureSize; bool m_hasAlpha; GLenum m_target; - int m_importCount; #ifdef Q_OS_QNX EGLStreamData m_eglStreamData; #endif }; +class ResourceHolder { +public: + ResourceHolder(const cc::TransferableResource &resource); + QSharedPointer<QSGTexture> initTexture(bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0); + QSGTexture *texture() const { return m_texture.data(); } + cc::TransferableResource &transferableResource() { return m_resource; } + cc::ReturnedResource returnResource(); + void incImportCount() { ++m_importCount; } + bool needsToFetch() const { return !m_resource.is_software && m_texture && !m_texture.data()->textureId(); } + +private: + QWeakPointer<QSGTexture> m_texture; + cc::TransferableResource m_resource; + int m_importCount; +}; + class RectClipNode : public QSGClipNode { public: @@ -144,23 +125,13 @@ private: QSGGeometry m_geometry; }; -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 inline QSharedPointer<MailboxTexture> &findMailboxTexture(unsigned resourceId - , QHash<unsigned, QSharedPointer<MailboxTexture> > &usedTextures - , QHash<unsigned, QSharedPointer<MailboxTexture> > &candidateTextures) +static inline QSharedPointer<QSGLayer> findRenderPassLayer(const cc::RenderPassId &id, const QList<QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > > &list) { - QSharedPointer<MailboxTexture> &texture = usedTextures[resourceId]; - if (!texture) - texture = candidateTextures.take(resourceId); - Q_ASSERT(texture); - return texture; + typedef QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > Pair; + Q_FOREACH (const Pair &pair, list) + if (pair.first == id) + return pair.second; + return QSharedPointer<QSGLayer>(); } static QSGNode *buildRenderPassChain(QSGNode *chainParent) @@ -294,59 +265,20 @@ static void deleteChromiumSync(gfx::TransferableFence *sync) Q_ASSERT(!*sync); } -RenderPassTexture::RenderPassTexture(const cc::RenderPass::Id &id) - : QSGTexture() - , m_id(id) - , m_format(GL_RGBA) - , m_sgEngine(new QSGEngine) - , m_rootNode(new QSGRootNode) -{ - initializeOpenGLFunctions(); -} - -void RenderPassTexture::bind() -{ - glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0); - updateBindOptions(); -} - -void RenderPassTexture::grab() -{ - if (!m_renderer) { - m_sgEngine->initialize(QOpenGLContext::currentContext()); - m_renderer.reset(m_sgEngine->createRenderer()); - m_renderer->setRootNode(m_rootNode.data()); - } - - 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_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_renderer->renderScene(m_fbo->handle()); -} - -MailboxTexture::MailboxTexture(const cc::TransferableResource &resource) - : m_resource(resource) +MailboxTexture::MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QSize textureSize) + : m_mailboxHolder(mailboxHolder) , m_textureId(0) - , m_textureSize(toQt(resource.size)) + , m_textureSize(textureSize) , m_hasAlpha(false) , m_target(GL_TEXTURE_2D) - , m_importCount(1) { initializeOpenGLFunctions(); + + // Assume that resources without a size will be used with a full source rect. + // Setting a size of 1x1 will let any texture node compute a normalized source + // rect of (0, 0) to (1, 1) while an empty texture size would set (0, 0) on all corners. + if (m_textureSize.isEmpty()) + m_textureSize = QSize(1, 1); } void MailboxTexture::bind() @@ -373,7 +305,55 @@ void MailboxTexture::setTarget(GLenum target) m_target = target; } -cc::ReturnedResource MailboxTexture::returnResource() +void MailboxTexture::fetchTexture(gpu::gles2::MailboxManager *mailboxManager) +{ + gpu::gles2::Texture *tex = ConsumeTexture(mailboxManager, m_target, m_mailboxHolder.mailbox); + + // The texture might already have been deleted (e.g. when navigating away from a page). + if (tex) { + m_textureId = service_id(tex); +#ifdef Q_OS_QNX + if (m_target == GL_TEXTURE_EXTERNAL_OES) { + m_eglStreamData = eglstream_connect_consumer(tex); + } +#endif + } +} + +ResourceHolder::ResourceHolder(const cc::TransferableResource &resource) + : m_resource(resource) + , m_importCount(1) +{ +} + +QSharedPointer<QSGTexture> ResourceHolder::initTexture(bool quadNeedsBlending, RenderWidgetHostViewQtDelegate *apiDelegate) +{ + QSharedPointer<QSGTexture> texture = m_texture.toStrongRef(); + if (!texture) { + if (m_resource.is_software) { + Q_ASSERT(apiDelegate); + scoped_ptr<cc::SharedBitmap> sharedBitmap = content::HostSharedBitmapManager::current()->GetSharedBitmapFromId(m_resource.size, m_resource.mailbox_holder.mailbox); + // QSG interprets QImage::hasAlphaChannel meaning that a node should enable blending + // to draw it but Chromium keeps this information in the quads. + // The input format is currently always Format_ARGB32_Premultiplied, so assume that all + // alpha bytes are 0xff if quads aren't requesting blending and avoid the conversion + // from Format_ARGB32_Premultiplied to Format_RGB32 just to get hasAlphaChannel to + // return false. + QImage::Format format = quadNeedsBlending ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; + QImage image(sharedBitmap->pixels(), m_resource.size.width(), m_resource.size.height(), format); + texture.reset(apiDelegate->createTextureFromImage(image.copy())); + } else { + texture.reset(new MailboxTexture(m_resource.mailbox_holder, toQt(m_resource.size))); + static_cast<MailboxTexture *>(texture.data())->setHasAlphaChannel(quadNeedsBlending); + } + m_texture = texture; + } + // All quads using a resource should request the same blending state. + Q_ASSERT(texture->hasAlphaChannel() || !quadNeedsBlending); + return texture; +} + +cc::ReturnedResource ResourceHolder::returnResource() { cc::ReturnedResource returned; // The ResourceProvider ensures that the resource isn't used by the parent compositor's GL @@ -389,20 +369,6 @@ cc::ReturnedResource MailboxTexture::returnResource() return returned; } -void MailboxTexture::fetchTexture(gpu::gles2::MailboxManager *mailboxManager) -{ - gpu::gles2::Texture *tex = ConsumeTexture(mailboxManager, m_target, m_resource.mailbox_holder.mailbox); - - // The texture might already have been deleted (e.g. when navigating away from a page). - if (tex) { - m_textureId = service_id(tex); -#ifdef Q_OS_QNX - if (m_target == GL_TEXTURE_EXTERNAL_OES) { - m_eglStreamData = eglstream_connect_consumer(tex); - } -#endif - } -} RectClipNode::RectClipNode(const QRectF &rect) : m_geometry(QSGGeometry::defaultAttributes_Point2D(), 4) @@ -429,9 +395,12 @@ void DelegatedFrameNode::preprocess() // 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_data->mailboxTextures.values()) - if (mailboxTexture->needsToFetch()) - mailboxesToFetch.append(mailboxTexture.data()); + typedef QHash<unsigned, QSharedPointer<ResourceHolder> >::const_iterator ResourceHolderIterator; + ResourceHolderIterator end = m_chromiumCompositorData->resourceHolders.constEnd(); + for (ResourceHolderIterator it = m_chromiumCompositorData->resourceHolders.constBegin(); it != end ; ++it) { + if ((*it)->needsToFetch()) + mailboxesToFetch.append(static_cast<MailboxTexture *>((*it)->texture())); + } if (!mailboxesToFetch.isEmpty()) { QMap<uint32, gfx::TransferableFence> transferredFences; @@ -442,7 +411,7 @@ void DelegatedFrameNode::preprocess() Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) { m_numPendingSyncPoints++; - AddSyncPointCallbackOnGpuThread(gpuMessageLoop, syncPointManager, mailboxTexture->resource().mailbox_holder.sync_point, base::Bind(&DelegatedFrameNode::syncPointRetired, this, &mailboxesToFetch)); + AddSyncPointCallbackOnGpuThread(gpuMessageLoop, syncPointManager, mailboxTexture->mailboxHolder().sync_point, base::Bind(&DelegatedFrameNode::syncPointRetired, this, &mailboxesToFetch)); } m_mailboxesFetchedWaitCond.wait(&m_mutex); @@ -452,7 +421,7 @@ void DelegatedFrameNode::preprocess() // Tell GL to wait until Chromium is done generating resource textures on the GPU thread // for each mailbox. We can safely start referencing those textures onto geometries afterward. Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) { - gfx::TransferableFence fence = transferredFences.take(mailboxTexture->resource().mailbox_holder.sync_point); + gfx::TransferableFence fence = transferredFences.take(mailboxTexture->mailboxHolder().sync_point); waitChromiumSync(&fence); deleteChromiumSync(&fence); } @@ -464,14 +433,19 @@ void DelegatedFrameNode::preprocess() } // Then render any intermediate RenderPass in order. - Q_FOREACH (const QSharedPointer<RenderPassTexture> &renderPass, m_renderPassTextures) - renderPass->grab(); + typedef QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > Pair; + Q_FOREACH (const Pair &pair, m_sgObjects.renderPassLayers) { + // The layer is non-live, request a one-time update here. + pair.second->scheduleUpdate(); + // Proceed with the actual update. + pair.second->updateTexture(); + } } -void DelegatedFrameNode::commit(DelegatedFrameNodeData* data, cc::ReturnedResourceArray *resourcesToRelease) +void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, cc::ReturnedResourceArray *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate) { - m_data = data; - cc::DelegatedFrameData* frameData = m_data->frameData.get(); + m_chromiumCompositorData = chromiumCompositorData; + cc::DelegatedFrameData* frameData = m_chromiumCompositorData->frameData.get(); if (!frameData) return; @@ -479,14 +453,15 @@ void DelegatedFrameNode::commit(DelegatedFrameNodeData* data, cc::ReturnedResour // countering the scale of devicePixel-scaled tiles when rendering them // to the final surface. QMatrix4x4 matrix; - matrix.scale(1 / m_data->frameDevicePixelRatio, 1 / m_data->frameDevicePixelRatio); + matrix.scale(1 / m_chromiumCompositorData->frameDevicePixelRatio, 1 / m_chromiumCompositorData->frameDevicePixelRatio); setMatrix(matrix); - // Keep the old texture lists around to find the ones we can re-use. - QList<QSharedPointer<RenderPassTexture> > oldRenderPassTextures; - m_renderPassTextures.swap(oldRenderPassTextures); - QHash<unsigned, QSharedPointer<MailboxTexture> > mailboxTextureCandidates; - m_data->mailboxTextures.swap(mailboxTextureCandidates); + // Keep the old objects in scope to hold a ref on layers, resources and textures + // that we can re-use. Destroy the remaining objects before returning. + SGObjects previousSGObjects; + qSwap(m_sgObjects, previousSGObjects); + QHash<unsigned, QSharedPointer<ResourceHolder> > resourceCandidates; + qSwap(m_chromiumCompositorData->resourceHolders, resourceCandidates); // 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 @@ -494,16 +469,23 @@ void DelegatedFrameNode::commit(DelegatedFrameNodeData* data, cc::ReturnedResour // to the producing child compositor. for (unsigned i = 0; i < frameData->resource_list.size(); ++i) { const cc::TransferableResource &res = frameData->resource_list.at(i); - if (QSharedPointer<MailboxTexture> texture = mailboxTextureCandidates.value(res.id)) - texture->incImportCount(); + if (QSharedPointer<ResourceHolder> resource = resourceCandidates.value(res.id)) + resource->incImportCount(); else - mailboxTextureCandidates[res.id] = QSharedPointer<MailboxTexture>(new MailboxTexture(res)); + resourceCandidates[res.id] = QSharedPointer<ResourceHolder>(new ResourceHolder(res)); } frameData->resource_list.clear(); + // 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. + // Intermediate render pass node chains are going to be destroyed when previousSGObjects + // goes out of scope together with any QSGLayer that could reference them. + while (QSGNode *oldChain = firstChild()) + delete oldChain; + // 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. + // to its dependencies through a RenderPassId 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. @@ -515,21 +497,24 @@ void DelegatedFrameNode::commit(DelegatedFrameNodeData* data, cc::ReturnedResour QSGNode *renderPassParent = 0; if (pass != rootRenderPass) { - QSharedPointer<RenderPassTexture> rpTexture = findRenderPassTexture(pass->id, oldRenderPassTextures); - if (!rpTexture) - rpTexture = QSharedPointer<RenderPassTexture>(new RenderPassTexture(pass->id)); - m_renderPassTextures.append(rpTexture); - rpTexture->setRect(toQt(pass->output_rect)); - rpTexture->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB); - renderPassParent = rpTexture->rootNode(); + QSharedPointer<QSGLayer> rpLayer = findRenderPassLayer(pass->id, previousSGObjects.renderPassLayers); + if (!rpLayer) { + rpLayer = QSharedPointer<QSGLayer>(apiDelegate->createLayer()); + // Avoid any premature texture update since we need to wait + // for the GPU thread to produce the dependent resources first. + rpLayer->setLive(false); + } + QSharedPointer<QSGRootNode> rootNode(new QSGRootNode); + rpLayer->setRect(toQt(pass->output_rect)); + rpLayer->setSize(toQt(pass->output_rect.size())); + rpLayer->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB); + rpLayer->setItem(rootNode.data()); + m_sgObjects.renderPassLayers.append(QPair<cc::RenderPassId, QSharedPointer<QSGLayer> >(pass->id, rpLayer)); + m_sgObjects.renderPassRootNodes.append(rootNode); + renderPassParent = rootNode.data(); } 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); const cc::SharedQuadState *currentLayerState = 0; QSGNode *currentLayerChain = 0; @@ -537,7 +522,7 @@ void DelegatedFrameNode::commit(DelegatedFrameNodeData* data, cc::ReturnedResour cc::QuadList::ConstBackToFrontIterator it = pass->quad_list.BackToFrontBegin(); cc::QuadList::ConstBackToFrontIterator end = pass->quad_list.BackToFrontEnd(); for (; it != end; ++it) { - cc::DrawQuad *quad = *it; + const cc::DrawQuad *quad = *it; if (currentLayerState != quad->shared_quad_state) { currentLayerState = quad->shared_quad_state; @@ -555,37 +540,28 @@ void DelegatedFrameNode::commit(DelegatedFrameNodeData* data, cc::ReturnedResour break; } case cc::DrawQuad::RENDER_PASS: { const cc::RenderPassDrawQuad *renderPassQuad = cc::RenderPassDrawQuad::MaterialCast(quad); - QSGTexture *texture = findRenderPassTexture(renderPassQuad->render_pass_id, m_renderPassTextures).data(); + QSGTexture *layer = findRenderPassLayer(renderPassQuad->render_pass_id, m_sgObjects.renderPassLayers).data(); // cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes. - if (!texture) + if (!layer) continue; - QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode; - textureNode->setRect(toQt(quad->rect)); - textureNode->setTexture(texture); - currentLayerChain->appendChildNode(textureNode); + // Only QSGImageNode currently supports QSGLayer textures. + QSGImageNode *imageNode = apiDelegate->createImageNode(); + imageNode->setTargetRect(toQt(quad->rect)); + imageNode->setInnerTargetRect(toQt(quad->rect)); + imageNode->setTexture(layer); + imageNode->update(); + currentLayerChain->appendChildNode(imageNode); break; } case cc::DrawQuad::TEXTURE_CONTENT: { const cc::TextureDrawQuad *tquad = cc::TextureDrawQuad::MaterialCast(quad); - QSharedPointer<MailboxTexture> &texture = findMailboxTexture(tquad->resource_id, m_data->mailboxTextures, mailboxTextureCandidates); - - // 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); + ResourceHolder *resource = findAndHoldResource(tquad->resource_id, resourceCandidates); 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()); + textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); + textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate)); currentLayerChain->appendChildNode(textureNode); break; } case cc::DrawQuad::SOLID_COLOR: { @@ -601,46 +577,67 @@ void DelegatedFrameNode::commit(DelegatedFrameNodeData* data, cc::ReturnedResour rectangleNode->setColor(toQt(scquad->color)); currentLayerChain->appendChildNode(rectangleNode); break; + } case cc::DrawQuad::DEBUG_BORDER: { + const cc::DebugBorderDrawQuad *dbquad = cc::DebugBorderDrawQuad::MaterialCast(quad); + QSGGeometryNode *geometryNode = new QSGGeometryNode; + + QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4); + geometry->setDrawingMode(GL_LINE_LOOP); + geometry->setLineWidth(dbquad->width); + // QSGGeometry::updateRectGeometry would actually set the corners in the following order: + // top-left, bottom-left, top-right, bottom-right, leading to a nice criss cross, instead + // of having a closed loop. + const gfx::Rect &r(dbquad->rect); + geometry->vertexDataAsPoint2D()[0].set(r.x(), r.y()); + geometry->vertexDataAsPoint2D()[1].set(r.x() + r.width(), r.y()); + geometry->vertexDataAsPoint2D()[2].set(r.x() + r.width(), r.y() + r.height()); + geometry->vertexDataAsPoint2D()[3].set(r.x(), r.y() + r.height()); + geometryNode->setGeometry(geometry); + + QSGFlatColorMaterial *material = new QSGFlatColorMaterial; + material->setColor(toQt(dbquad->color)); + geometryNode->setMaterial(material); + + geometryNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial); + currentLayerChain->appendChildNode(geometryNode); + break; } case cc::DrawQuad::TILED_CONTENT: { const cc::TileDrawQuad *tquad = cc::TileDrawQuad::MaterialCast(quad); - QSharedPointer<MailboxTexture> &texture = findMailboxTexture(tquad->resource_id, m_data->mailboxTextures, mailboxTextureCandidates); - - if (!quad->visible_rect.IsEmpty() && !quad->opaque_rect.Contains(quad->visible_rect)) - texture->setHasAlphaChannel(true); + ResourceHolder *resource = findAndHoldResource(tquad->resource_id, resourceCandidates); 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))); + textureNode->setSourceRect(toQt(tquad->tex_coord_rect)); + textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); + textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate)); currentLayerChain->appendChildNode(textureNode); break; } case cc::DrawQuad::YUV_VIDEO_CONTENT: { const cc::YUVVideoDrawQuad *vquad = cc::YUVVideoDrawQuad::MaterialCast(quad); - QSharedPointer<MailboxTexture> &yTexture = findMailboxTexture(vquad->y_plane_resource_id, m_data->mailboxTextures, mailboxTextureCandidates); - QSharedPointer<MailboxTexture> &uTexture = findMailboxTexture(vquad->u_plane_resource_id, m_data->mailboxTextures, mailboxTextureCandidates); - QSharedPointer<MailboxTexture> &vTexture = findMailboxTexture(vquad->v_plane_resource_id, m_data->mailboxTextures, mailboxTextureCandidates); - - // Do not use a reference for this one, it might be null. - QSharedPointer<MailboxTexture> aTexture; + ResourceHolder *yResource = findAndHoldResource(vquad->y_plane_resource_id, resourceCandidates); + ResourceHolder *uResource = findAndHoldResource(vquad->u_plane_resource_id, resourceCandidates); + ResourceHolder *vResource = findAndHoldResource(vquad->v_plane_resource_id, resourceCandidates); + ResourceHolder *aResource = 0; // This currently requires --enable-vp8-alpha-playback and needs a video with alpha data to be triggered. if (vquad->a_plane_resource_id) - aTexture = findMailboxTexture(vquad->a_plane_resource_id, m_data->mailboxTextures, mailboxTextureCandidates); + aResource = findAndHoldResource(vquad->a_plane_resource_id, resourceCandidates); - YUVVideoNode *videoNode = new YUVVideoNode(yTexture.data(), uTexture.data(), vTexture.data(), aTexture.data(), toQt(vquad->tex_coord_rect)); + YUVVideoNode *videoNode = new YUVVideoNode( + initAndHoldTexture(yResource, quad->ShouldDrawWithBlending()), + initAndHoldTexture(uResource, quad->ShouldDrawWithBlending()), + initAndHoldTexture(vResource, quad->ShouldDrawWithBlending()), + aResource ? initAndHoldTexture(aResource, quad->ShouldDrawWithBlending()) : 0, toQt(vquad->tex_coord_rect)); videoNode->setRect(toQt(quad->rect)); currentLayerChain->appendChildNode(videoNode); break; #ifdef GL_OES_EGL_image_external } case cc::DrawQuad::STREAM_VIDEO_CONTENT: { const cc::StreamVideoDrawQuad *squad = cc::StreamVideoDrawQuad::MaterialCast(quad); - QSharedPointer<MailboxTexture> &texture = findMailboxTexture(squad->resource_id, m_data->mailboxTextures, mailboxTextureCandidates); + ResourceHolder *resource = findAndHoldResource(squad->resource_id, resourceCandidates); + MailboxTexture *texture = static_cast<MailboxTexture *>(initAndHoldTexture(resource, quad->ShouldDrawWithBlending())); texture->setTarget(GL_TEXTURE_EXTERNAL_OES); // since this is not default TEXTURE_2D type - StreamVideoNode *svideoNode = new StreamVideoNode(texture.data()); + StreamVideoNode *svideoNode = new StreamVideoNode(texture); svideoNode->setRect(toQt(squad->rect)); svideoNode->setTextureMatrix(toQt(squad->matrix.matrix())); currentLayerChain->appendChildNode(svideoNode); @@ -653,8 +650,30 @@ void DelegatedFrameNode::commit(DelegatedFrameNodeData* data, cc::ReturnedResour } // 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()) - resourcesToRelease->push_back(mailboxTexture->returnResource()); + typedef QHash<unsigned, QSharedPointer<ResourceHolder> >::const_iterator ResourceHolderIterator; + ResourceHolderIterator end = resourceCandidates.constEnd(); + for (ResourceHolderIterator it = resourceCandidates.constBegin(); it != end ; ++it) + resourcesToRelease->push_back((*it)->returnResource()); +} + +ResourceHolder *DelegatedFrameNode::findAndHoldResource(unsigned resourceId, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates) +{ + // ResourceHolders must survive when the scene graph destroys our node branch + QSharedPointer<ResourceHolder> &resource = m_chromiumCompositorData->resourceHolders[resourceId]; + if (!resource) + resource = candidates.take(resourceId); + Q_ASSERT(resource); + return resource.data(); +} + +QSGTexture *DelegatedFrameNode::initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate) +{ + // QSGTextures must be destroyed in the scene graph thread as part of the QSGNode tree, + // so we can't store them with the ResourceHolder in m_chromiumCompositorData. + // Hold them through a QSharedPointer solely on the root DelegatedFrameNode of the web view + // and access them through a QWeakPointer from the resource holder to find them later. + m_sgObjects.textureStrongRefs.append(resource->initTexture(quadIsAllOpaque, apiDelegate)); + return m_sgObjects.textureStrongRefs.last().data(); } void DelegatedFrameNode::fetchTexturesAndUnlockQt(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch) diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h index a031a464f..3ef984a09 100644 --- a/src/core/delegated_frame_node.h +++ b/src/core/delegated_frame_node.h @@ -38,6 +38,7 @@ #define DELEGATED_FRAME_NODE_H #include "base/memory/scoped_ptr.h" +#include "cc/quads/render_pass.h" #include "cc/resources/transferable_resource.h" #include <QMutex> #include <QSGNode> @@ -46,20 +47,25 @@ #include <QWaitCondition> #include "chromium_gpu_helper.h" +#include "render_widget_host_view_qt_delegate.h" + +QT_BEGIN_NAMESPACE +class QSGLayer; +QT_END_NAMESPACE namespace cc { class DelegatedFrameData; } class MailboxTexture; -class RenderPassTexture; +class ResourceHolder; // Separating this data allows another DelegatedFrameNode to reconstruct the QSGNode tree from the mailbox textures // and render pass information. -class DelegatedFrameNodeData : public QSharedData { +class ChromiumCompositorData : public QSharedData { public: - DelegatedFrameNodeData() : frameDevicePixelRatio(1) { } - QHash<unsigned, QSharedPointer<MailboxTexture> > mailboxTextures; + ChromiumCompositorData() : frameDevicePixelRatio(1) { } + QHash<unsigned, QSharedPointer<ResourceHolder> > resourceHolders; scoped_ptr<cc::DelegatedFrameData> frameData; qreal frameDevicePixelRatio; }; @@ -69,20 +75,27 @@ public: DelegatedFrameNode(); ~DelegatedFrameNode(); void preprocess(); - void commit(DelegatedFrameNodeData* data, cc::ReturnedResourceArray *resourcesToRelease); + void commit(ChromiumCompositorData *chromiumCompositorData, cc::ReturnedResourceArray *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate); private: - QExplicitlySharedDataPointer<DelegatedFrameNodeData> m_data; - QList<QSharedPointer<RenderPassTexture> > m_renderPassTextures; - int m_numPendingSyncPoints; - QMap<uint32, gfx::TransferableFence> m_mailboxGLFences; - 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); + + ResourceHolder *findAndHoldResource(unsigned resourceId, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates); + QSGTexture *initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0); + + QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; + struct SGObjects { + QList<QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > > renderPassLayers; + QList<QSharedPointer<QSGRootNode> > renderPassRootNodes; + QList<QSharedPointer<QSGTexture> > textureStrongRefs; + } m_sgObjects; + int m_numPendingSyncPoints; + QMap<uint32, gfx::TransferableFence> m_mailboxGLFences; + QWaitCondition m_mailboxesFetchedWaitCond; + QMutex m_mutex; }; #endif // DELEGATED_FRAME_NODE_H diff --git a/src/core/desktop_screen_qt.cpp b/src/core/desktop_screen_qt.cpp index 34b02e379..1d9114260 100644 --- a/src/core/desktop_screen_qt.cpp +++ b/src/core/desktop_screen_qt.cpp @@ -36,13 +36,6 @@ #include "desktop_screen_qt.h" -bool DesktopScreenQt::IsDIPEnabled() -{ - // Currently only used by GetScaleFactorForNativeView for drag events. - // Short-circuit this until we can test any implementation properly in real code. - return false; -} - gfx::Point DesktopScreenQt::GetCursorScreenPoint() { Q_UNREACHABLE(); diff --git a/src/core/desktop_screen_qt.h b/src/core/desktop_screen_qt.h index ad57c1616..bf0c589f7 100644 --- a/src/core/desktop_screen_qt.h +++ b/src/core/desktop_screen_qt.h @@ -44,7 +44,6 @@ class DesktopScreenQt : public gfx::Screen { public: // Overridden from gfx::Screen: - virtual bool IsDIPEnabled() Q_DECL_OVERRIDE; virtual gfx::Point GetCursorScreenPoint() Q_DECL_OVERRIDE; virtual gfx::NativeWindow GetWindowUnderCursor() Q_DECL_OVERRIDE; virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) Q_DECL_OVERRIDE; diff --git a/src/core/dev_tools_http_handler_delegate_qt.cpp b/src/core/dev_tools_http_handler_delegate_qt.cpp index 4f8992dab..4b866a6bc 100644 --- a/src/core/dev_tools_http_handler_delegate_qt.cpp +++ b/src/core/dev_tools_http_handler_delegate_qt.cpp @@ -34,43 +34,159 @@ ** ****************************************************************************/ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "dev_tools_http_handler_delegate_qt.h" +#include "type_conversion.h" + #include <QByteArray> #include <QFile> #include "base/command_line.h" #include "base/files/file_path.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_http_handler.h" #include "content/public/browser/devtools_target.h" +#include "content/public/browser/favicon_status.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/browser/web_contents_delegate.h" #include "content/public/common/content_switches.h" +#include "net/base/ip_endpoint.h" #include "net/socket/stream_listen_socket.h" -#include "net/socket/tcp_listen_socket.h" +#include "net/socket/tcp_server_socket.h" using namespace content; -DevToolsHttpHandlerDelegateQt::DevToolsHttpHandlerDelegateQt(BrowserContext* browser_context) - : m_browserContext(browser_context) +namespace { + +const char kTargetTypePage[] = "page"; +const char kTargetTypeServiceWorker[] = "service_worker"; +const char kTargetTypeOther[] = "other"; + +class TCPServerSocketFactory + : public DevToolsHttpHandler::ServerSocketFactory { +public: + TCPServerSocketFactory(const std::string& address, int port, int backlog) + : DevToolsHttpHandler::ServerSocketFactory(address, port, backlog) {} +private: + scoped_ptr<net::ServerSocket> Create() const override { + return scoped_ptr<net::ServerSocket>(new net::TCPServerSocket(NULL, net::NetLog::Source())); + } + DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory); +}; + +class Target : public content::DevToolsTarget { +public: + explicit Target(scoped_refptr<DevToolsAgentHost> agent_host); + + virtual std::string GetId() const override { return agent_host_->GetId(); } + virtual std::string GetParentId() const override { return std::string(); } + virtual std::string GetType() const override { + switch (agent_host_->GetType()) { + case DevToolsAgentHost::TYPE_WEB_CONTENTS: + return kTargetTypePage; + case DevToolsAgentHost::TYPE_SERVICE_WORKER: + return kTargetTypeServiceWorker; + default: + break; + } + return kTargetTypeOther; + } + virtual std::string GetTitle() const override { return agent_host_->GetTitle(); } + virtual std::string GetDescription() const override { return std::string(); } + virtual GURL GetURL() const override { return agent_host_->GetURL(); } + virtual GURL GetFaviconURL() const override { return favicon_url_; } + virtual base::TimeTicks GetLastActivityTime() const override { + return last_activity_time_; + } + virtual bool IsAttached() const override { + return agent_host_->IsAttached(); + } + virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const override { + return agent_host_; + } + virtual bool Activate() const override; + virtual bool Close() const override; + +private: + scoped_refptr<DevToolsAgentHost> agent_host_; + GURL favicon_url_; + base::TimeTicks last_activity_time_; +}; + +Target::Target(scoped_refptr<DevToolsAgentHost> agent_host) + : agent_host_(agent_host) +{ + if (WebContents* web_contents = agent_host_->GetWebContents()) { + NavigationController& controller = web_contents->GetController(); + NavigationEntry* entry = controller.GetActiveEntry(); + if (entry != NULL && entry->GetURL().is_valid()) + favicon_url_ = entry->GetFavicon().url; + last_activity_time_ = web_contents->GetLastActiveTime(); + } +} + +bool Target::Activate() const { + return agent_host_->Activate(); +} + +bool Target::Close() const { + return agent_host_->Close(); +} + +} // namespace + +DevToolsHttpHandlerDelegateQt::DevToolsHttpHandlerDelegateQt() + : m_devtoolsHttpHandler(0) + , m_bindAddress(QLatin1String("127.0.0.1")) + , m_port(0) { - const int defaultPort = 1337; - int listeningPort = defaultPort; + const QString inspectorEnv = QString::fromUtf8(qgetenv("QTWEBENGINE_REMOTE_DEBUGGING")); const CommandLine &commandLine = *CommandLine::ForCurrentProcess(); + QString portStr; + if (commandLine.HasSwitch(switches::kRemoteDebuggingPort)) { - std::string portString = - commandLine.GetSwitchValueASCII(switches::kRemoteDebuggingPort); - int portInt = 0; - if (base::StringToInt(portString, &portInt) && portInt > 0 && portInt < 65535) - listeningPort = portInt; - } - m_devtoolsHttpHandler = DevToolsHttpHandler::Start(new net::TCPListenSocketFactory("0.0.0.0", listeningPort), std::string(), this, base::FilePath()); + portStr = QString::fromStdString(commandLine.GetSwitchValueASCII(switches::kRemoteDebuggingPort)); + } else if (!inspectorEnv.isEmpty()) { + int portColonPos = inspectorEnv.lastIndexOf(':'); + if (portColonPos != -1) { + portStr = inspectorEnv.mid(portColonPos + 1); + m_bindAddress = inspectorEnv.mid(0, portColonPos); + } else + portStr = inspectorEnv; + } else + return; + + bool ok = false; + m_port = portStr.toInt(&ok); + if (ok && m_port > 0 && m_port < 65535) { + scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory> factory(new TCPServerSocketFactory(m_bindAddress.toStdString(), m_port, 1)); + m_devtoolsHttpHandler = DevToolsHttpHandler::Start(factory.Pass(), std::string(), this, base::FilePath()); + } else + qWarning("Invalid port given for the inspector server \"%s\". Examples of valid input: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's network interface).", qPrintable(portStr)); } DevToolsHttpHandlerDelegateQt::~DevToolsHttpHandlerDelegateQt() { - m_devtoolsHttpHandler->Stop(); + // Stop() takes care of deleting the DevToolsHttpHandler. + if (m_devtoolsHttpHandler) + m_devtoolsHttpHandler->Stop(); +} + +void DevToolsHttpHandlerDelegateQt::Initialized(const net::IPEndPoint& ip_address) +{ + if (ip_address.address().size()) { + QString addressAndPort = QString::fromStdString(ip_address.ToString()); + qWarning("Remote debugging server started successfully. Try pointing a Chromium-based browser to http://%s", qPrintable(addressAndPort)); + } else + qWarning("Couldn't start the inspector server on bind address \"%s\" and port \"%d\". In case of invalid input, try something like: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's interface).", qPrintable(m_bindAddress), m_port); } std::string DevToolsHttpHandlerDelegateQt::GetDiscoveryPageHTML() @@ -95,22 +211,30 @@ base::FilePath DevToolsHttpHandlerDelegateQt::GetDebugFrontendDir() return base::FilePath(); } -std::string DevToolsHttpHandlerDelegateQt::GetPageThumbnailData(const GURL& url) +scoped_ptr<net::StreamListenSocket> DevToolsHttpHandlerDelegateQt::CreateSocketForTethering(net::StreamListenSocket::Delegate* delegate, std::string* name) { - return std::string(); + return scoped_ptr<net::StreamListenSocket>(); +} + +base::DictionaryValue* DevToolsManagerDelegateQt::HandleCommand(DevToolsAgentHost *, base::DictionaryValue *) { + return 0; } -scoped_ptr<DevToolsTarget> DevToolsHttpHandlerDelegateQt::CreateNewTarget(const GURL&) +std::string DevToolsManagerDelegateQt::GetPageThumbnailData(const GURL& url) { - return scoped_ptr<DevToolsTarget>(); + return std::string(); } -void DevToolsHttpHandlerDelegateQt::EnumerateTargets(TargetCallback callback) +scoped_ptr<DevToolsTarget> DevToolsManagerDelegateQt::CreateNewTarget(const GURL &) { - callback.Run(TargetList()); + return scoped_ptr<DevToolsTarget>(); } -scoped_ptr<net::StreamListenSocket> DevToolsHttpHandlerDelegateQt::CreateSocketForTethering(net::StreamListenSocket::Delegate* delegate, std::string* name) +void DevToolsManagerDelegateQt::EnumerateTargets(TargetCallback callback) { - return scoped_ptr<net::StreamListenSocket>(); + TargetList targets; + for (const auto& agent_host : DevToolsAgentHost::GetOrCreateAll()) { + targets.push_back(new Target(agent_host)); + } + callback.Run(targets); } diff --git a/src/core/dev_tools_http_handler_delegate_qt.h b/src/core/dev_tools_http_handler_delegate_qt.h index 06b690ae9..8a8a658a6 100644 --- a/src/core/dev_tools_http_handler_delegate_qt.h +++ b/src/core/dev_tools_http_handler_delegate_qt.h @@ -38,7 +38,9 @@ #define DEV_TOOLS_HTTP_HANDLER_DELEGATE_QT_H #include "content/public/browser/devtools_http_handler_delegate.h" +#include "content/public/browser/devtools_manager_delegate.h" +#include <QString> #include <QtCore/qcompilerdetection.h> // needed for Q_DECL_OVERRIDE namespace net { @@ -54,23 +56,32 @@ class RenderViewHost; class DevToolsHttpHandlerDelegateQt : public content::DevToolsHttpHandlerDelegate { public: - explicit DevToolsHttpHandlerDelegateQt(content::BrowserContext* browser_context); + DevToolsHttpHandlerDelegateQt(); virtual ~DevToolsHttpHandlerDelegateQt(); // content::DevToolsHttpHandlerDelegate Overrides + virtual void Initialized(const net::IPEndPoint &ip_address) Q_DECL_OVERRIDE; 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 scoped_ptr<content::DevToolsTarget> CreateNewTarget(const GURL&) Q_DECL_OVERRIDE; // Requests the list of all inspectable targets. // The caller gets the ownership of the returned targets. - virtual void EnumerateTargets(TargetCallback callback) Q_DECL_OVERRIDE; - virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(net::StreamListenSocket::Delegate* delegate, std::string* name) Q_DECL_OVERRIDE; + virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(net::StreamListenSocket::Delegate *delegate, std::string *name) Q_DECL_OVERRIDE; private: - content::BrowserContext* m_browserContext; - content::DevToolsHttpHandler* m_devtoolsHttpHandler; + content::DevToolsHttpHandler *m_devtoolsHttpHandler; + QString m_bindAddress; + int m_port; +}; + +class DevToolsManagerDelegateQt : public content::DevToolsManagerDelegate { +public: + void Inspect(content::BrowserContext *browser_context, content::DevToolsAgentHost *agent_host) Q_DECL_OVERRIDE { } + void DevToolsAgentStateChanged(content::DevToolsAgentHost *agent_host, bool attached) Q_DECL_OVERRIDE { } + base::DictionaryValue *HandleCommand(content::DevToolsAgentHost *agent_host, base::DictionaryValue *command) Q_DECL_OVERRIDE; + scoped_ptr<content::DevToolsTarget> CreateNewTarget(const GURL &url) Q_DECL_OVERRIDE; + void EnumerateTargets(TargetCallback callback) Q_DECL_OVERRIDE; + std::string GetPageThumbnailData(const GURL &url) Q_DECL_OVERRIDE; }; #endif // DEV_TOOLS_HTTP_HANDLER_DELEGATE_QT_H diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 3df03ffa3..3ef8cc9af 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -36,6 +36,7 @@ #include "download_manager_delegate_qt.h" +#include "content/public/browser/download_manager.h" #include "content/public/browser/download_item.h" #include "content/public/browser/save_page_type.h" #include "content/public/browser/web_contents.h" @@ -46,115 +47,26 @@ #include <QMap> #include <QStandardPaths> +#include "browser_context_adapter.h" +#include "browser_context_adapter_client.h" +#include "browser_context_qt.h" #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)) - { +ASSERT_ENUMS_MATCH(content::DownloadItem::IN_PROGRESS, BrowserContextAdapterClient::DownloadInProgress) +ASSERT_ENUMS_MATCH(content::DownloadItem::COMPLETE, BrowserContextAdapterClient::DownloadCompleted) +ASSERT_ENUMS_MATCH(content::DownloadItem::CANCELLED, BrowserContextAdapterClient::DownloadCancelled) +ASSERT_ENUMS_MATCH(content::DownloadItem::INTERRUPTED, BrowserContextAdapterClient::DownloadInterrupted) - } - 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(toFilePathString("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()) +DownloadManagerDelegateQt::DownloadManagerDelegateQt(BrowserContextAdapter *contextAdapter) + : m_contextAdapter(contextAdapter) , m_currentId(0) { - + Q_ASSERT(m_contextAdapter); } DownloadManagerDelegateQt::~DownloadManagerDelegateQt() { - delete m_targetHelper; -} - - -void DownloadManagerDelegateQt::Shutdown() -{ - QT_NOT_YET_IMPLEMENTED } void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& callback) @@ -162,24 +74,17 @@ void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& cal 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) +void DownloadManagerDelegateQt::cancelDownload(const content::DownloadTargetCallback& callback) { - QT_NOT_YET_IMPLEMENTED - return true; + callback.Run(base::FilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, base::FilePath()); } -bool DownloadManagerDelegateQt::ShouldOpenDownload(content::DownloadItem* item, - const content::DownloadOpenDelayedCallback& callback) +void DownloadManagerDelegateQt::cancelDownload(quint32 downloadId) { - QT_NOT_YET_IMPLEMENTED - return false; + content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_contextAdapter->browserContext()); + content::DownloadItem *download = dlm->GetDownload(downloadId); + if (download) + download->Cancel(/* user_cancel */ true); } bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* item, @@ -194,41 +99,63 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i return true; } - // Let the target helper determine the download target path. - return m_targetHelper->determineDownloadTarget(item, callback); -} + std::string suggestedFilename = item->GetSuggestedFilename(); -bool DownloadManagerDelegateQt::GenerateFileHash() -{ - QT_NOT_YET_IMPLEMENTED - return false; -} + if (suggestedFilename.empty()) + suggestedFilename = item->GetTargetFilePath().AsUTF8Unsafe(); -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 -} + if (suggestedFilename.empty()) + suggestedFilename = item->GetURL().ExtractFileName(); -void DownloadManagerDelegateQt::OpenDownload(content::DownloadItem* download) -{ - QT_NOT_YET_IMPLEMENTED -} + if (suggestedFilename.empty()) + suggestedFilename = "qwe_download"; -void DownloadManagerDelegateQt::ShowDownloadInShell(content::DownloadItem* download) -{ - QT_NOT_YET_IMPLEMENTED -} + QDir defaultDownloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); -void DownloadManagerDelegateQt::CheckForFileExistence( - content::DownloadItem* download, - const content::CheckForFileExistenceCallback& callback) -{ - QT_NOT_YET_IMPLEMENTED + QFileInfo suggestedFile(defaultDownloadDirectory.absoluteFilePath(QString::fromStdString(suggestedFilename))); + QString suggestedFilePath = suggestedFile.absoluteFilePath(); + QString tmpFileBase = QString("%1%2%3").arg(suggestedFile.absolutePath()).arg(QDir::separator()).arg(suggestedFile.baseName()); + + for (int i = 1; QFileInfo::exists(suggestedFilePath); ++i) { + suggestedFilePath = QString("%1(%2).%3").arg(tmpFileBase).arg(i).arg(suggestedFile.completeSuffix()); + if (i >= 99) { + suggestedFilePath = suggestedFile.absoluteFilePath(); + break; + } + } + + item->AddObserver(this); + if (m_contextAdapter->client()) { + BrowserContextAdapterClient::DownloadItemInfo info = { + item->GetId(), + toQt(item->GetURL()), + item->GetState(), + item->GetTotalBytes(), + item->GetReceivedBytes(), + suggestedFilePath, + false /* accepted */ + }; + m_contextAdapter->client()->downloadRequested(info); + + suggestedFile.setFile(info.path); + + if (info.accepted && !suggestedFile.absoluteDir().mkpath(suggestedFile.absolutePath())) { + qWarning("Creating download path failed, download cancelled: %s", suggestedFile.absolutePath().toUtf8().data()); + info.accepted = false; + } + + if (!info.accepted) { + cancelDownload(callback); + return true; + } + + base::FilePath filePathForCallback(toFilePathString(suggestedFile.absoluteFilePath())); + callback.Run(filePathForCallback, content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, filePathForCallback.AddExtension(toFilePathString("download"))); + } else + cancelDownload(callback); + + return true; } void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_context, @@ -242,4 +169,24 @@ void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_cont *skip_dir_check = true; } +void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *download) +{ + if (m_contextAdapter->client()) { + BrowserContextAdapterClient::DownloadItemInfo info = { + download->GetId(), + toQt(download->GetURL()), + download->GetState(), + download->GetTotalBytes(), + download->GetReceivedBytes(), + QString(), + true /* accepted */ + }; + m_contextAdapter->client()->downloadUpdated(info); + } +} +void DownloadManagerDelegateQt::OnDownloadDestroyed(content::DownloadItem *download) +{ + download->RemoveObserver(this); + download->Cancel(/* user_cancel */ false); +} diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h index 4c838363f..007f2e580 100644 --- a/src/core/download_manager_delegate_qt.h +++ b/src/core/download_manager_delegate_qt.h @@ -39,7 +39,7 @@ #include "content/public/browser/download_manager_delegate.h" -#include <qglobal.h> +#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE namespace base { class FilePath; @@ -51,46 +51,38 @@ class DownloadItem; class WebContents; } -class DownloadTargetHelper; - -class DownloadManagerDelegateQt : public content::DownloadManagerDelegate +class BrowserContextAdapter; +class DownloadManagerDelegateInstance; +class DownloadManagerDelegateQt + : public content::DownloadManagerDelegate + , public content::DownloadItem::Observer { public: - DownloadManagerDelegateQt(); - virtual ~DownloadManagerDelegateQt(); - - void Shutdown() Q_DECL_OVERRIDE; + DownloadManagerDelegateQt(BrowserContextAdapter *contextAdapter); + ~DownloadManagerDelegateQt(); 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; + void cancelDownload(quint32 downloadId); + + // Inherited from content::DownloadItem::Observer + void OnDownloadUpdated(content::DownloadItem *download) Q_DECL_OVERRIDE; + void OnDownloadDestroyed(content::DownloadItem *download) Q_DECL_OVERRIDE; + private: - DownloadTargetHelper* m_targetHelper; + void cancelDownload(const content::DownloadTargetCallback& callback); + BrowserContextAdapter *m_contextAdapter; + uint64 m_currentId; + + friend class DownloadManagerDelegateInstance; DISALLOW_COPY_AND_ASSIGN(DownloadManagerDelegateQt); }; diff --git a/src/core/location_provider_qt.cpp b/src/core/location_provider_qt.cpp new file mode 100644 index 000000000..cdc9f1a44 --- /dev/null +++ b/src/core/location_provider_qt.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "location_provider_qt.h" + +#include <math.h> + +#include "type_conversion.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QThread> +#include <QtPositioning/QGeoPositionInfoSource> + +#include "base/message_loop/message_loop.h" +#include "base/bind.h" +#include "content/browser/geolocation/geolocation_provider_impl.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/geolocation_provider.h" + +using content::BrowserThread; + +class QtPositioningHelper : public QObject { + Q_OBJECT +public: + QtPositioningHelper(LocationProviderQt *provider); + ~QtPositioningHelper(); + + bool start(bool highAccuracy); + void stop(); + void refresh(); + +private Q_SLOTS: + void updatePosition(const QGeoPositionInfo &); + void error(QGeoPositionInfoSource::Error positioningError); + void timeout(); + +private: + LocationProviderQt *m_locationProvider; + QGeoPositionInfoSource *m_positionInfoSource; + + void postToLocationProvider(const base::Closure &task); +}; + +QtPositioningHelper::QtPositioningHelper(LocationProviderQt *provider) + : m_locationProvider(provider) + , m_positionInfoSource(0) +{ + Q_ASSERT(provider); +} + +QtPositioningHelper::~QtPositioningHelper() +{ + m_locationProvider->m_positioningHelper = 0; +} + +bool QtPositioningHelper::start(bool highAccuracy) +{ + DCHECK_CURRENTLY_ON(BrowserThread::UI); + Q_UNUSED(highAccuracy); + // FIXME: go through availableSources until one supports QGeoPositionInfoSource::SatellitePositioningMethods + // for the highAccuracy case. + m_positionInfoSource = QGeoPositionInfoSource::createDefaultSource(this); + if (!m_positionInfoSource) + return false; + + connect(m_positionInfoSource, &QGeoPositionInfoSource::positionUpdated, this, &QtPositioningHelper::updatePosition); + // disambiguate the error getter and the signal in QGeoPositionInfoSource. + connect(m_positionInfoSource, static_cast<void (QGeoPositionInfoSource::*)(QGeoPositionInfoSource::Error)>(&QGeoPositionInfoSource::error) + , this, &QtPositioningHelper::error); + connect(m_positionInfoSource, &QGeoPositionInfoSource::updateTimeout, this, &QtPositioningHelper::timeout); + + m_positionInfoSource->startUpdates(); + return true; +} + +void QtPositioningHelper::stop() +{ + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!m_positionInfoSource) + return; + m_positionInfoSource->stopUpdates(); +} + +void QtPositioningHelper::refresh() +{ + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!m_positionInfoSource) + return; + m_positionInfoSource->stopUpdates(); +} + +void QtPositioningHelper::updatePosition(const QGeoPositionInfo &pos) +{ + if (!pos.isValid()) + return; + Q_ASSERT(m_positionInfoSource->error() == QGeoPositionInfoSource::NoError); + content::Geoposition newPos; + newPos.error_code = content::Geoposition::ERROR_CODE_NONE; + newPos.error_message.clear(); + + newPos.timestamp = toTime(pos.timestamp()); + newPos.latitude = pos.coordinate().latitude(); + newPos.longitude = pos.coordinate().longitude(); + + const double altitude = pos.coordinate().altitude(); + if (!qIsNaN(altitude)) + newPos.altitude = altitude; + + // Chromium's geoposition needs a valid (as in >=0.) accuracy field. + // try and get an accuracy estimate from QGeoPositionInfo. + // If we don't have any accuracy info, 100m seems a pesimistic enough default. + if (!pos.hasAttribute(QGeoPositionInfo::VerticalAccuracy) && !pos.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + newPos.accuracy = 100; + else { + const double vAccuracy = pos.hasAttribute(QGeoPositionInfo::VerticalAccuracy) ? pos.attribute(QGeoPositionInfo::VerticalAccuracy) : 0; + const double hAccuracy = pos.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) ? pos.attribute(QGeoPositionInfo::HorizontalAccuracy) : 0; + newPos.accuracy = sqrt(vAccuracy * vAccuracy + hAccuracy * hAccuracy); + } + + // And now the "nice to have" fields (-1 means invalid). + newPos.speed = pos.hasAttribute(QGeoPositionInfo::GroundSpeed) ? pos.attribute(QGeoPositionInfo::GroundSpeed) : -1; + newPos.heading = pos.hasAttribute(QGeoPositionInfo::Direction) ? pos.attribute(QGeoPositionInfo::Direction) : -1; + + postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, base::Unretained(m_locationProvider), newPos)); +} + +void QtPositioningHelper::error(QGeoPositionInfoSource::Error positioningError) +{ + Q_ASSERT(positioningError != QGeoPositionInfoSource::NoError); + content::Geoposition newPos; + switch (positioningError) { + case QGeoPositionInfoSource::AccessError: + newPos.error_code = content::Geoposition::ERROR_CODE_PERMISSION_DENIED; + break; + case QGeoPositionInfoSource::ClosedError: + case QGeoPositionInfoSource::UnknownSourceError: // position unavailable is as good as it gets in Geoposition + default: + newPos.error_code = content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; + break; + } + postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, base::Unretained(m_locationProvider), newPos)); +} + +void QtPositioningHelper::timeout() +{ + content::Geoposition newPos; + // content::Geoposition::ERROR_CODE_TIMEOUT is not handled properly in the renderer process, and the timeout + // argument used in JS never comes all the way to the browser process. + // Let's just treat it like any other error where the position is unavailable. + newPos.error_code = content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; + postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, base::Unretained(m_locationProvider), newPos)); +} + +inline void QtPositioningHelper::postToLocationProvider(const base::Closure &task) +{ + LocationProviderQt::messageLoop()->PostTask(FROM_HERE, task); +} + +#include "location_provider_qt.moc" + +LocationProviderQt::LocationProviderQt() + : m_positioningHelper(0) +{ +} + +LocationProviderQt::~LocationProviderQt() +{ + m_positioningHelper->deleteLater(); +} + +bool LocationProviderQt::StartProvider(bool highAccuracy) +{ + DCHECK(base::MessageLoop::current() == messageLoop()); + QThread *guiThread = qApp->thread(); + if (!m_positioningHelper) { + m_positioningHelper = new QtPositioningHelper(this); + m_positioningHelper->moveToThread(guiThread); + } + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(base::IgnoreResult(&QtPositioningHelper::start) + , base::Unretained(m_positioningHelper), highAccuracy)); + return true; +} + +void LocationProviderQt::StopProvider() +{ + DCHECK(base::MessageLoop::current() == messageLoop()); + if (m_positioningHelper) + BrowserThread::PostTask(BrowserThread::UI,FROM_HERE, base::Bind(&QtPositioningHelper::stop + , base::Unretained(m_positioningHelper))); +} + +void LocationProviderQt::RequestRefresh() +{ + DCHECK(base::MessageLoop::current() == messageLoop()); + if (m_positioningHelper) + BrowserThread::PostTask(BrowserThread::UI,FROM_HERE, base::Bind(&QtPositioningHelper::refresh + , base::Unretained(m_positioningHelper))); +} + +void LocationProviderQt::OnPermissionGranted() +{ + RequestRefresh(); +} + +void LocationProviderQt::updatePosition(const content::Geoposition &position) +{ + DCHECK(base::MessageLoop::current() == messageLoop()); + m_lastKnownPosition = position; + NotifyCallback(position); +} + +base::MessageLoop *LocationProviderQt::messageLoop() +{ + return static_cast<content::GeolocationProviderImpl*>(content::GeolocationProvider::GetInstance())->message_loop(); +} diff --git a/src/core/location_provider_qt.h b/src/core/location_provider_qt.h new file mode 100644 index 000000000..c3e462092 --- /dev/null +++ b/src/core/location_provider_qt.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LOCATION_PROVIDER_QT_H +#define LOCATION_PROVIDER_QT_H + +#include <QtCore/qcompilerdetection.h> + +#include "content/browser/geolocation/location_provider_base.h" +#include "content/public/common/geoposition.h" + +QT_FORWARD_DECLARE_CLASS(QThread) +class QtPositioningHelper; + +namespace base { +class MessageLoop; +} + +class LocationProviderQt : public content::LocationProviderBase +{ +public: + LocationProviderQt(); + virtual ~LocationProviderQt(); + + // LocationProviderBase + virtual bool StartProvider(bool highAccuracy) Q_DECL_OVERRIDE; + virtual void StopProvider() Q_DECL_OVERRIDE; + virtual void GetPosition(content::Geoposition *position) Q_DECL_OVERRIDE { *position = m_lastKnownPosition; } + virtual void RequestRefresh() Q_DECL_OVERRIDE; + virtual void OnPermissionGranted() Q_DECL_OVERRIDE; + +private: + friend class QtPositioningHelper; + + static base::MessageLoop *messageLoop(); + void updatePosition(const content::Geoposition &); + + content::Geoposition m_lastKnownPosition; + QtPositioningHelper *m_positioningHelper; +}; +//#define QT_USE_POSITIONING 1 + +#endif // LOCATION_PROVIDER_QT_H diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index a8e964b4d..5d65a3391 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -254,14 +254,20 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content:: return; } - // The extension name that the stream is registered with. - std::string originalExtensionName; - // Resolve DesktopMediaID for the specified device id. - content::DesktopMediaID mediaId = - getDesktopStreamsRegistry()->RequestMediaForStreamId( - request.requested_video_device_id, request.render_process_id, - request.render_view_id, request.security_origin, - &originalExtensionName); + content::WebContents* const web_contents_for_stream = content::WebContents::FromRenderFrameHost( + content::RenderFrameHost::FromID(request.render_process_id, request.render_frame_id)); + content::RenderFrameHost* const main_frame = web_contents_for_stream ? web_contents_for_stream->GetMainFrame() : NULL; + + content::DesktopMediaID mediaId; + if (main_frame) { + // The extension name that the stream is registered with. + std::string originalExtensionName; + // Resolve DesktopMediaID for the specified device id. + mediaId = getDesktopStreamsRegistry()->RequestMediaForStreamId( + request.requested_video_device_id, main_frame->GetProcess()->GetID(), + main_frame->GetRoutingID(), request.security_origin, + &originalExtensionName); + } // Received invalid device id. if (mediaId.type == content::DesktopMediaID::TYPE_NONE) { @@ -391,37 +397,36 @@ DesktopStreamsRegistry *MediaCaptureDevicesDispatcher::getDesktopStreamsRegistry return m_desktopStreamsRegistry.get(); } -void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged(int renderProcessId, int renderViewId, int pageRequestId, const GURL& securityOrigin - , const content::MediaStreamDevice &device, content::MediaRequestState state) +void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged(int render_process_id, int render_frame_id, int page_request_id, const GURL& security_origin, content::MediaStreamType stream_type, content::MediaRequestState state) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind( &MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread, - base::Unretained(this), renderProcessId, renderViewId, - pageRequestId, device, state)); + base::Unretained(this), render_process_id, render_frame_id, + page_request_id, security_origin, stream_type, state)); } -void MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread(int renderProcessId, int renderViewId, int pageRequestId - , const content::MediaStreamDevice &device, content::MediaRequestState state) +void MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread(int render_process_id, int render_frame_id, int page_request_id + , const GURL& security_origin, content::MediaStreamType stream_type, content::MediaRequestState state) { // Track desktop capture sessions. Tracking is necessary to avoid unbalanced // session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE, // but they will all reach MEDIA_REQUEST_STATE_CLOSING. - if (device.type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { + if (stream_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) { if (state == content::MEDIA_REQUEST_STATE_DONE) { - DesktopCaptureSession session = { renderProcessId, renderViewId, - pageRequestId }; + DesktopCaptureSession session = { render_process_id, render_frame_id, + page_request_id }; m_desktopCaptureSessions.push_back(session); } else if (state == content::MEDIA_REQUEST_STATE_CLOSING) { for (DesktopCaptureSessions::iterator it = m_desktopCaptureSessions.begin(); it != m_desktopCaptureSessions.end(); ++it) { - if (it->render_process_id == renderProcessId && - it->render_view_id == renderViewId && - it->page_request_id == pageRequestId) { + if (it->render_process_id == render_process_id && + it->render_view_id == render_frame_id && + it->page_request_id == page_request_id) { m_desktopCaptureSessions.erase(it); break; } @@ -437,9 +442,9 @@ void MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread(int render RequestsQueue &queue = rqs_it->second; for (RequestsQueue::iterator it = queue.begin(); it != queue.end(); ++it) { - if (it->request.render_process_id == renderProcessId && - it->request.render_view_id == renderViewId && - it->request.page_request_id == pageRequestId) { + if (it->request.render_process_id == render_process_id && + it->request.render_frame_id == render_frame_id && + it->request.page_request_id == page_request_id) { queue.erase(it); found = true; break; diff --git a/src/core/media_capture_devices_dispatcher.h b/src/core/media_capture_devices_dispatcher.h index 2c2988857..e0d6cff1d 100644 --- a/src/core/media_capture_devices_dispatcher.h +++ b/src/core/media_capture_devices_dispatcher.h @@ -75,12 +75,9 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, // Overridden from content::MediaObserver: virtual void OnAudioCaptureDevicesChanged() Q_DECL_OVERRIDE { } virtual void OnVideoCaptureDevicesChanged() Q_DECL_OVERRIDE { } - virtual void OnMediaRequestStateChanged(int renderProcessId, int renderViewId, int pageRequestId, const GURL &securityOrigin, const content::MediaStreamDevice &device - , content::MediaRequestState state) Q_DECL_OVERRIDE; + virtual void OnMediaRequestStateChanged(int render_process_id, int render_frame_id, int page_request_id, const GURL& security_origin, content::MediaStreamType stream_type, content::MediaRequestState state) Q_DECL_OVERRIDE; virtual void OnCreatingAudioStream(int /*render_process_id*/, int /*render_frame_id*/) Q_DECL_OVERRIDE { } - virtual void OnAudioStreamPlaying(int /*render_process_id*/, int /*render_frame_id*/, int /*stream_id*/, const ReadPowerAndClipCallback& /*power_read_callback*/) Q_DECL_OVERRIDE { } - virtual void OnAudioStreamStopped(int /*render_process_id*/, int /*render_frame_id*/, int /*stream_id*/) Q_DECL_OVERRIDE { } DesktopStreamsRegistry *getDesktopStreamsRegistry(); @@ -112,8 +109,7 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, void ProcessQueuedAccessRequest(content::WebContents *); // Called by the MediaObserver() functions, executed on UI thread. - void updateMediaRequestStateOnUIThread(int renderProcessId, int renderViewId, int pageRequestId, const content::MediaStreamDevice & - , content::MediaRequestState); + void updateMediaRequestStateOnUIThread(int render_process_id, int render_frame_id, int page_request_id, const GURL& security_origin, content::MediaStreamType stream_type, content::MediaRequestState state); RequestsQueues m_pendingRequests; diff --git a/src/core/native_web_keyboard_event_qt.cpp b/src/core/native_web_keyboard_event_qt.cpp new file mode 100644 index 000000000..072b4dd9d --- /dev/null +++ b/src/core/native_web_keyboard_event_qt.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/public/browser/native_web_keyboard_event.h" +#include <QKeyEvent> + +namespace { + +// We need to copy |os_event| in NativeWebKeyboardEvent because it is +// queued in RenderWidgetHost and may be passed and used +// RenderViewHostDelegate::HandledKeybardEvent after the original aura +// event is destroyed. +gfx::NativeEvent CopyEvent(gfx::NativeEvent event) +{ + return event ? reinterpret_cast<gfx::NativeEvent>(new QKeyEvent(*reinterpret_cast<QKeyEvent*>(event))) : 0; +} + +void DestroyEvent(gfx::NativeEvent event) +{ + delete reinterpret_cast<QKeyEvent*>(event); +} + +} // namespace + +using blink::WebKeyboardEvent; + +namespace content { + +NativeWebKeyboardEvent::NativeWebKeyboardEvent() + : os_event(0), + skip_in_browser(false) +{ +} + +NativeWebKeyboardEvent::NativeWebKeyboardEvent(gfx::NativeEvent native_event) + : os_event(CopyEvent(native_event)), + skip_in_browser(false) +{ +} + +NativeWebKeyboardEvent::NativeWebKeyboardEvent(const NativeWebKeyboardEvent& other) + : WebKeyboardEvent(other), + os_event(CopyEvent(other.os_event)), + skip_in_browser(other.skip_in_browser) +{ +} + +NativeWebKeyboardEvent& NativeWebKeyboardEvent::operator=(const NativeWebKeyboardEvent& other) { + WebKeyboardEvent::operator=(other); + DestroyEvent(os_event); + os_event = CopyEvent(other.os_event); + skip_in_browser = other.skip_in_browser; + return *this; +} + +NativeWebKeyboardEvent::~NativeWebKeyboardEvent() { + DestroyEvent(os_event); +} + +} // namespace content diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp index f14d2cb39..79af93e06 100644 --- a/src/core/network_delegate_qt.cpp +++ b/src/core/network_delegate_qt.cpp @@ -40,7 +40,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/resource_request_details.h" #include "content/public/browser/resource_request_info.h" -#include "content/public/common/page_transition_types.h" +#include "ui/base/page_transition_types.h" #include "net/base/load_flags.h" #include "net/url_request/url_request.h" #include "type_conversion.h" @@ -49,23 +49,23 @@ namespace { -int pageTransitionToNavigationType(content::PageTransition transition) +int pageTransitionToNavigationType(ui::PageTransition transition) { - int32 qualifier = content::PageTransitionGetQualifier(transition); + int32 qualifier = ui::PageTransitionGetQualifier(transition); - if (qualifier & content::PAGE_TRANSITION_FORWARD_BACK) + if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK) return WebContentsAdapterClient::BackForwardNavigation; - content::PageTransition stippedTransition = content::PageTransitionStripQualifier(transition); + ui::PageTransition stippedTransition = ui::PageTransitionStripQualifier(transition); switch (stippedTransition) { - case content::PAGE_TRANSITION_LINK: + case ui::PAGE_TRANSITION_LINK: return WebContentsAdapterClient::LinkClickedNavigation; - case content::PAGE_TRANSITION_TYPED: + case ui::PAGE_TRANSITION_TYPED: return WebContentsAdapterClient::TypedNavigation; - case content::PAGE_TRANSITION_FORM_SUBMIT: + case ui::PAGE_TRANSITION_FORM_SUBMIT: return WebContentsAdapterClient::FormSubmittedNavigation; - case content::PAGE_TRANSITION_RELOAD: + case ui::PAGE_TRANSITION_RELOAD: return WebContentsAdapterClient::ReloadNavigation; default: return WebContentsAdapterClient::OtherNavigation; @@ -78,15 +78,14 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::C { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); const content::ResourceRequestInfo *info = content::ResourceRequestInfo::ForRequest(request); + if (!info) + return net::OK; + + content::ResourceType resourceType = info->GetResourceType(); int renderProcessId; int renderFrameId; - if (!info || !info->GetRenderFrameForRequest(request, &renderProcessId, &renderFrameId)) - // Abort the request if it has no associated render info / render view. - return net::ERR_ABORTED; - - ResourceType::Type resourceType = info->GetResourceType(); - // Only intercept MAIN_FRAME and SUB_FRAME. - if (!ResourceType::IsFrame(resourceType)) + // Only intercept MAIN_FRAME and SUB_FRAME with an associated render frame. + if (!content::IsResourceTypeFrame(resourceType) || !info->GetRenderFrameForRequest(request, &renderProcessId, &renderFrameId)) return net::OK; // Track active requests since |callback| and |new_url| are valid @@ -97,7 +96,7 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::C RequestParams params = { toQt(request->url()), - resourceType == ResourceType::MAIN_FRAME, + info->IsMainFrame(), navigationType, renderProcessId, renderFrameId diff --git a/src/core/ozone_platform_eglfs.cpp b/src/core/ozone_platform_eglfs.cpp index b6b367aeb..8f1d9870f 100644 --- a/src/core/ozone_platform_eglfs.cpp +++ b/src/core/ozone_platform_eglfs.cpp @@ -36,6 +36,8 @@ #include "ozone_platform_eglfs.h" +#if defined(USE_OZONE) + #include "media/ozone/media_ozone_platform.h" #include "ui/events/ozone/device/device_manager.h" #include "ui/ozone/ozone_platform.h" @@ -43,7 +45,6 @@ #include "ui/ozone/public/gpu_platform_support.h" #include "ui/ozone/public/gpu_platform_support_host.h" -#if defined(USE_OZONE) namespace media { diff --git a/src/core/ozone_platform_eglfs.h b/src/core/ozone_platform_eglfs.h index 9d96688a5..a976d1c63 100644 --- a/src/core/ozone_platform_eglfs.h +++ b/src/core/ozone_platform_eglfs.h @@ -37,13 +37,13 @@ #ifndef UI_OZONE_PLATFORM_EGLFS_OZONE_PLATFORM_EGLFS_H_ #define UI_OZONE_PLATFORM_EGLFS_OZONE_PLATFORM_EGLFS_H_ +#if defined(USE_OZONE) + #include "ui/events/ozone/evdev/event_factory_evdev.h" #include "ui/ozone/ozone_platform.h" #include "surface_factory_qt.h" -#if defined(USE_OZONE) - namespace ui { class OzonePlatformEglfs : public OzonePlatform { diff --git a/src/core/qtwebengine.gypi b/src/core/qtwebengine.gypi index 17287669f..79eb6d45b 100644 --- a/src/core/qtwebengine.gypi +++ b/src/core/qtwebengine.gypi @@ -8,6 +8,7 @@ 'dependencies': [ '<(chromium_src_dir)/base/base.gyp:base', '<(chromium_src_dir)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', + '<(chromium_src_dir)/components/components.gyp:error_page_renderer', '<(chromium_src_dir)/components/components.gyp:visitedlink_browser', '<(chromium_src_dir)/components/components.gyp:visitedlink_renderer', '<(chromium_src_dir)/content/content.gyp:content', @@ -17,8 +18,7 @@ '<(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)/content/app/resources/content_resources.gyp:content_resources', '<(chromium_src_dir)/ipc/ipc.gyp:ipc', '<(chromium_src_dir)/media/media.gyp:media', '<(chromium_src_dir)/net/net.gyp:net', @@ -102,7 +102,7 @@ }, }, # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 'msvs_disabled_warnings': [ 4267, ], + 'msvs_disabled_warnings': [ 4267, 4996, ], }], # OS=="win" ['OS=="linux"', { 'dependencies': [ diff --git a/src/core/qtwebengine_extras.gypi b/src/core/qtwebengine_extras.gypi index f30c16401..b0e9bc697 100644 --- a/src/core/qtwebengine_extras.gypi +++ b/src/core/qtwebengine_extras.gypi @@ -15,6 +15,7 @@ ['exclude', 'clipboard/clipboard_util_win\\.(cc|h)$'], ['exclude', 'dragdrop/os_exchange_data_provider_aurax11\\.(cc|h)$'], ['exclude', 'dragdrop/os_exchange_data_provider_win\\.(cc|h)$'], + ['exclude', 'dragdrop/os_exchange_data_provider_mac\\.(mm|h)$'], ['exclude', 'resource/resource_bundle_android.cc$'], ['exclude', 'resource/resource_bundle_auralinux.cc$'], ['exclude', 'resource/resource_bundle_gtk.cc$'], @@ -26,6 +27,9 @@ ['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/native_web_keyboard_event_android.cc$'], + ['exclude', 'browser/renderer_host/native_web_keyboard_event_aura.cc$'], + ['exclude', 'browser/renderer_host/native_web_keyboard_event_mac.mm$'], ['exclude', 'browser/renderer_host/pepper/pepper_truetype_font_list_pango\\.cc$'], ['exclude', 'browser/renderer_host/render_widget_host_view_android\\.(cc|h)$'], ['exclude', 'browser/renderer_host/render_widget_host_view_aura\\.(cc|h)$'], diff --git a/src/core/qtwebenginecoreglobal.h b/src/core/qtwebenginecoreglobal.h index 9a222f43f..541406f87 100644 --- a/src/core/qtwebenginecoreglobal.h +++ b/src/core/qtwebenginecoreglobal.h @@ -57,4 +57,6 @@ # define QWEBENGINE_EXPORT #endif +#define ASSERT_ENUMS_MATCH(A, B) Q_STATIC_ASSERT_X(static_cast<int>(A) == static_cast<int>(B), "The enum values must match"); + #endif // QTWEBENGINECOREGLOBAL_H diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index c221e94e3..3741d8876 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -52,8 +52,6 @@ #include "content/browser/renderer_host/input/web_input_event_util.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/common/cursors/webcursor.h" -#include "content/common/gpu/gpu_messages.h" -#include "content/common/view_messages.h" #include "content/public/browser/browser_accessibility_state.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" @@ -62,7 +60,8 @@ #include "third_party/WebKit/public/platform/WebCursorInfo.h" #include "third_party/WebKit/public/web/WebCompositionUnderline.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" -#include "ui/events/gesture_detection/gesture_config_helper.h" +#include "ui/events/event.h" +#include "ui/events/gesture_detection/gesture_provider_config_helper.h" #include "ui/events/gesture_detection/motion_event.h" #include "ui/gfx/size_conversions.h" @@ -80,6 +79,22 @@ #include <QWindow> #include <QtGui/qaccessible.h> +static inline ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) { + ui::LatencyInfo latency_info; + // The latency number should only be added if the timestamp is valid. + if (event.timeStampSeconds) { + const int64 time_micros = static_cast<int64>( + event.timeStampSeconds * base::Time::kMicrosecondsPerSecond); + latency_info.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, + 0, + 0, + base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros), + 1); + } + return latency_info; +} + static inline Qt::InputMethodHints toQtInputMethodHints(ui::TextInputType inputType) { switch (inputType) { @@ -128,8 +143,6 @@ static inline ui::GestureProvider::Config QtGestureProviderConfig() { ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig(); // Causes an assert in CreateWebGestureEventFromGestureEventData and we don't need them in Qt. config.gesture_begin_end_types_enabled = false; - // Swipe gestures aren't forwarded, we don't use them and they abort the gesture detection. - config.scale_gesture_detector_config.gesture_detector_config.swipe_enabled = config.gesture_detector_config.swipe_enabled = false; return config; } @@ -139,12 +152,37 @@ static inline bool compareTouchPoints(const QTouchEvent::TouchPoint &lhs, const return lhs.state() < rhs.state(); } +static inline int flagsFromModifiers(Qt::KeyboardModifiers modifiers) +{ + int modifierFlags = ui::EF_NONE; +#if defined(Q_OS_OSX) + if (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + if ((modifiers & Qt::ControlModifier) != 0) + modifierFlags |= ui::EF_COMMAND_DOWN; + if ((modifiers & Qt::MetaModifier) != 0) + modifierFlags |= ui::EF_CONTROL_DOWN; + } else +#endif + { + if ((modifiers & Qt::ControlModifier) != 0) + modifierFlags |= ui::EF_CONTROL_DOWN; + if ((modifiers & Qt::MetaModifier) != 0) + modifierFlags |= ui::EF_COMMAND_DOWN; + } + if ((modifiers & Qt::ShiftModifier) != 0) + modifierFlags |= ui::EF_SHIFT_DOWN; + if ((modifiers & Qt::AltModifier) != 0) + modifierFlags |= ui::EF_ALT_DOWN; + return modifierFlags; +} + class MotionEventQt : public ui::MotionEvent { public: - MotionEventQt(const QList<QTouchEvent::TouchPoint> &touchPoints, const base::TimeTicks &eventTime, Action action, int index = -1) + MotionEventQt(const QList<QTouchEvent::TouchPoint> &touchPoints, const base::TimeTicks &eventTime, Action action, const Qt::KeyboardModifiers modifiers, int index = -1) : touchPoints(touchPoints) , eventTime(eventTime) , action(action) + , flags(flagsFromModifiers(modifiers)) , index(index) { // ACTION_DOWN and ACTION_UP must be accesssed through pointer_index 0 @@ -160,7 +198,21 @@ public: virtual float GetY(size_t pointer_index) const Q_DECL_OVERRIDE { return touchPoints.at(pointer_index).pos().y(); } virtual float GetRawX(size_t pointer_index) const Q_DECL_OVERRIDE { return touchPoints.at(pointer_index).screenPos().x(); } virtual float GetRawY(size_t pointer_index) const Q_DECL_OVERRIDE { return touchPoints.at(pointer_index).screenPos().y(); } - virtual float GetTouchMajor(size_t pointer_index) const Q_DECL_OVERRIDE { return touchPoints.at(pointer_index).rect().height(); } + virtual float GetTouchMajor(size_t pointer_index) const Q_DECL_OVERRIDE + { + QRectF touchRect = touchPoints.at(pointer_index).rect(); + return std::max(touchRect.height(), touchRect.width()); + } + virtual float GetTouchMinor(size_t pointer_index) const Q_DECL_OVERRIDE + { + QRectF touchRect = touchPoints.at(pointer_index).rect(); + return std::min(touchRect.height(), touchRect.width()); + } + virtual float GetOrientation(size_t pointer_index) const Q_DECL_OVERRIDE + { + return 0; + } + virtual int GetFlags() const Q_DECL_OVERRIDE { return flags; } virtual float GetPressure(size_t pointer_index) const Q_DECL_OVERRIDE { return touchPoints.at(pointer_index).pressure(); } virtual base::TimeTicks GetEventTime() const Q_DECL_OVERRIDE { return eventTime; } @@ -172,16 +224,11 @@ public: virtual ToolType GetToolType(size_t pointer_index) const Q_DECL_OVERRIDE { return ui::MotionEvent::TOOL_TYPE_UNKNOWN; } virtual int GetButtonState() const Q_DECL_OVERRIDE { return 0; } - virtual scoped_ptr<MotionEvent> Cancel() const Q_DECL_OVERRIDE { Q_UNREACHABLE(); return scoped_ptr<MotionEvent>(); } - - virtual scoped_ptr<MotionEvent> Clone() const Q_DECL_OVERRIDE { - return scoped_ptr<MotionEvent>(new MotionEventQt(*this)); - } - private: QList<QTouchEvent::TouchPoint> touchPoints; base::TimeTicks eventTime; Action action; + int flags; int index; }; @@ -189,7 +236,7 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget : m_host(content::RenderWidgetHostImpl::From(widget)) , m_gestureProvider(QtGestureProviderConfig(), this) , m_sendMotionActionDown(false) - , m_frameNodeData(new DelegatedFrameNodeData) + , m_chromiumCompositorData(new ChromiumCompositorData) , m_needsDelegatedFrameAck(false) , m_didFirstVisuallyNonEmptyLayout(false) , m_adapterClient(0) @@ -198,15 +245,18 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget , m_initPending(false) { m_host->SetView(this); - +#ifndef QT_NO_ACCESSIBILITY QAccessible::installActivationObserver(this); if (QAccessible::isActive()) content::BrowserAccessibilityStateImpl::GetInstance()->EnableAccessibility(); +#endif // QT_NO_ACCESSIBILITY } RenderWidgetHostViewQt::~RenderWidgetHostViewQt() { +#ifndef QT_NO_ACCESSIBILITY QAccessible::removeActivationObserver(this); +#endif // QT_NO_ACCESSIBILITY } void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate) @@ -263,6 +313,10 @@ void RenderWidgetHostViewQt::SetBounds(const gfx::Rect& screenRect) SetSize(screenRect.size()); } +gfx::Vector2dF RenderWidgetHostViewQt::GetLastScrollOffset() const { + return m_lastScrollOffset; +} + gfx::Size RenderWidgetHostViewQt::GetPhysicalBackingSize() const { if (!m_delegate || !m_delegate->window() || !m_delegate->window()->screen()) @@ -294,15 +348,16 @@ gfx::NativeViewAccessible RenderWidgetHostViewQt::GetNativeViewAccessible() return 0; } -void RenderWidgetHostViewQt::CreateBrowserAccessibilityManagerIfNeeded() +content::BrowserAccessibilityManager* RenderWidgetHostViewQt::CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate) { - if (GetBrowserAccessibilityManager()) - return; - - SetBrowserAccessibilityManager(new content::BrowserAccessibilityManagerQt( +#ifndef QT_NO_ACCESSIBILITY + return new content::BrowserAccessibilityManagerQt( m_adapterClient->accessibilityParentObject(), content::BrowserAccessibilityManagerQt::GetEmptyDocument(), - this)); + delegate); +#else + return 0; +#endif // QT_NO_ACCESSIBILITY } // Set focus to the associated View component. @@ -352,17 +407,24 @@ gfx::Rect RenderWidgetHostViewQt::GetViewBounds() const // Return value indicates whether the mouse is locked successfully or not. bool RenderWidgetHostViewQt::LockMouse() { - QT_NOT_USED - return false; + mouse_locked_ = true; + m_lockedMousePosition = QCursor::pos(); + m_delegate->lockMouse(); + qApp->setOverrideCursor(Qt::BlankCursor); + return true; } + void RenderWidgetHostViewQt::UnlockMouse() { - QT_NOT_USED + mouse_locked_ = false; + m_delegate->unlockMouse(); + qApp->restoreOverrideCursor(); + m_host->LostMouseLock(); } void RenderWidgetHostViewQt::WasShown() { - m_host->WasShown(); + m_host->WasShown(ui::LatencyInfo()); } void RenderWidgetHostViewQt::WasHidden() @@ -483,10 +545,13 @@ void RenderWidgetHostViewQt::SetIsLoading(bool) // We use WebContentsDelegateQt::LoadingStateChanged to notify about loading state. } -void RenderWidgetHostViewQt::TextInputStateChanged(const ViewHostMsg_TextInputState_Params& params) +void RenderWidgetHostViewQt::TextInputTypeChanged(ui::TextInputType type, ui::TextInputMode mode, bool can_compose_inline, int flags) { - m_currentInputType = params.type; - m_delegate->inputMethodStateChanged(static_cast<bool>(params.type)); + Q_UNUSED(mode); + Q_UNUSED(can_compose_inline); + Q_UNUSED(flags); + m_currentInputType = type; + m_delegate->inputMethodStateChanged(static_cast<bool>(type)); } void RenderWidgetHostViewQt::ImeCancelComposition() @@ -531,14 +596,12 @@ void RenderWidgetHostViewQt::SelectionBoundsChanged(const ViewHostMsg_SelectionB 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, const SkBitmap::Config config) +void RenderWidgetHostViewQt::CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, content::CopyFromCompositingSurfaceCallback& callback, const SkColorType color_type) { NOTIMPLEMENTED(); + Q_UNUSED(src_subrect); + Q_UNUSED(dst_size); + Q_UNUSED(color_type); callback.Run(false, SkBitmap()); } @@ -553,36 +616,6 @@ bool RenderWidgetHostViewQt::CanCopyToVideoFrame() const return false; } -void RenderWidgetHostViewQt::AcceleratedSurfaceInitialized(int host_id, int route_id) -{ -} - -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); - content::RenderWidgetHostImpl::CompositorFrameDrawn(params.latency_info); -} - -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); - content::RenderWidgetHostImpl::CompositorFrameDrawn(params.latency_info); -} - -void RenderWidgetHostViewQt::AcceleratedSurfaceSuspend() -{ - QT_NOT_YET_IMPLEMENTED -} - -void RenderWidgetHostViewQt::AcceleratedSurfaceRelease() -{ - QT_NOT_YET_IMPLEMENTED -} - bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&) { return false; @@ -590,18 +623,19 @@ bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&) void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) { + m_lastScrollOffset = frame->metadata.root_scroll_offset; Q_ASSERT(!m_needsDelegatedFrameAck); m_needsDelegatedFrameAck = true; m_pendingOutputSurfaceId = output_surface_id; Q_ASSERT(frame->delegated_frame_data); - Q_ASSERT(!m_frameNodeData->frameData || m_frameNodeData->frameData->resource_list.empty()); - m_frameNodeData->frameData = frame->delegated_frame_data.Pass(); - m_frameNodeData->frameDevicePixelRatio = frame->metadata.device_scale_factor; + Q_ASSERT(!m_chromiumCompositorData->frameData || m_chromiumCompositorData->frameData->resource_list.empty()); + m_chromiumCompositorData->frameData = frame->delegated_frame_data.Pass(); + m_chromiumCompositorData->frameDevicePixelRatio = frame->metadata.device_scale_factor; // Support experimental.viewport.devicePixelRatio, see GetScreenInfo implementation below. float dpiScale = this->dpiScale(); if (dpiScale != 0 && dpiScale != 1) - m_frameNodeData->frameDevicePixelRatio /= dpiScale; + m_chromiumCompositorData->frameDevicePixelRatio /= dpiScale; m_delegate->update(); @@ -633,7 +667,7 @@ gfx::Rect RenderWidgetHostViewQt::GetBoundsInRootWindow() gfx::GLSurfaceHandle RenderWidgetHostViewQt::GetCompositingSurface() { - return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT); + return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT); } void RenderWidgetHostViewQt::SelectionChanged(const base::string16 &text, size_t offset, const gfx::Range &range) @@ -643,9 +677,7 @@ void RenderWidgetHostViewQt::SelectionChanged(const base::string16 &text, size_t #if defined(USE_X11) // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard. - ui::ScopedClipboardWriter clipboard_writer( - ui::Clipboard::GetForCurrentThread(), - ui::CLIPBOARD_TYPE_SELECTION); + ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION); clipboard_writer.WriteText(text); #endif } @@ -661,7 +693,7 @@ QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode) if (!frameNode) frameNode = new DelegatedFrameNode; - frameNode->commit(m_frameNodeData.data(), &m_resourcesToRelease); + frameNode->commit(m_chromiumCompositorData.data(), &m_resourcesToRelease, m_delegate.get()); // 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. @@ -785,8 +817,8 @@ void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEve m_gestureProvider.OnTouchEventAck(eventConsumed); return; } - - m_host->ForwardTouchEvent(content::CreateWebTouchEventFromMotionEvent(motionEvent)); + blink::WebTouchEvent touchEvent = content::CreateWebTouchEventFromMotionEvent(motionEvent); + m_host->ForwardTouchEventWithLatencyInfo(touchEvent, CreateLatencyInfo(touchEvent)); } QList<QTouchEvent::TouchPoint> RenderWidgetHostViewQt::mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints) @@ -833,16 +865,32 @@ void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) m_clickHelper.lastPressPosition = QPointF(event->pos()).toPoint(); } + if (IsMouseLocked()) { + webEvent.movementX = -(m_lockedMousePosition.x() - event->globalX()); + webEvent.movementY = -(m_lockedMousePosition.y() - event->globalY()); + QCursor::setPos(m_lockedMousePosition); + } + m_host->ForwardMouseEvent(webEvent); } void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) { + if (IsMouseLocked() && ev->key() == Qt::Key_Escape && ev->type() == QEvent::KeyRelease) + UnlockMouse(); + content::NativeWebKeyboardEvent webEvent = WebEventFactory::toWebKeyboardEvent(ev); - m_host->ForwardKeyboardEvent(webEvent); if (webEvent.type == blink::WebInputEvent::RawKeyDown && !ev->text().isEmpty()) { + // Blink won't consume the RawKeyDown, but rather the Char event in this case. + // Make sure to skip the former on the way back. The same os_event will be set on both of them. + webEvent.skip_in_browser = true; + m_host->ForwardKeyboardEvent(webEvent); + + webEvent.skip_in_browser = false; webEvent.type = blink::WebInputEvent::Char; m_host->ForwardKeyboardEvent(webEvent); + } else { + m_host->ForwardKeyboardEvent(webEvent); } } @@ -871,10 +919,12 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) QTextCharFormat textCharFormat = attribute.value.value<QTextFormat>().toCharFormat(); QColor qcolor = textCharFormat.underlineColor(); + QColor qBackgroundColor = textCharFormat.background().color(); blink::WebColor color = SkColorSetARGB(qcolor.alpha(), qcolor.red(), qcolor.green(), qcolor.blue()); + blink::WebColor backgroundColor = SkColorSetARGB(qBackgroundColor.alpha(), qBackgroundColor.red(), qBackgroundColor.green(), qBackgroundColor.blue()); int start = qMin(attribute.start, (attribute.start + attribute.length)); int end = qMax(attribute.start, (attribute.start + attribute.length)); - underlines.push_back(blink::WebCompositionUnderline(start, end, color, false)); + underlines.push_back(blink::WebCompositionUnderline(start, end, color, false, backgroundColor)); break; } case QInputMethodEvent::Cursor: @@ -905,54 +955,7 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) } } -void RenderWidgetHostViewQt::AccessibilitySetFocus(int acc_obj_id) -{ - if (!m_host) - return; - m_host->AccessibilitySetFocus(acc_obj_id); -} - -void RenderWidgetHostViewQt::AccessibilityDoDefaultAction(int acc_obj_id) -{ - if (!m_host) - return; - m_host->AccessibilityDoDefaultAction(acc_obj_id); -} - -void RenderWidgetHostViewQt::AccessibilityScrollToMakeVisible(int acc_obj_id, gfx::Rect subfocus) -{ - if (!m_host) - return; - m_host->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus); -} - -void RenderWidgetHostViewQt::AccessibilityScrollToPoint(int acc_obj_id, gfx::Point point) -{ - if (!m_host) - return; - m_host->AccessibilityScrollToPoint(acc_obj_id, point); -} - -void RenderWidgetHostViewQt::AccessibilitySetTextSelection(int acc_obj_id, int start_offset, int end_offset) -{ - if (!m_host) - return; - m_host->AccessibilitySetTextSelection(acc_obj_id, start_offset, end_offset); -} - -bool RenderWidgetHostViewQt::AccessibilityViewHasFocus() const -{ - return HasFocus(); -} - -void RenderWidgetHostViewQt::AccessibilityFatalError() -{ - if (!m_host) - return; - m_host->AccessibilityFatalError(); - SetBrowserAccessibilityManager(NULL); -} - +#ifndef QT_NO_ACCESSIBILITY void RenderWidgetHostViewQt::accessibilityActiveChanged(bool active) { if (active) @@ -960,6 +963,7 @@ void RenderWidgetHostViewQt::accessibilityActiveChanged(bool active) else content::BrowserAccessibilityStateImpl::GetInstance()->DisableAccessibility(); } +#endif // QT_NO_ACCESSIBILITY void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev) { @@ -981,7 +985,7 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) QList<QTouchEvent::TouchPoint> touchPoints = mapTouchPointIds(ev->touchPoints()); if (ev->type() == QEvent::TouchCancel) { - MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::ACTION_CANCEL); + MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::ACTION_CANCEL, ev->modifiers()); processMotionEvent(cancelEvent); return; } @@ -1014,7 +1018,7 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) continue; } - MotionEventQt motionEvent(touchPoints, eventTimestamp, action, i); + MotionEventQt motionEvent(touchPoints, eventTimestamp, action, ev->modifiers(), i); processMotionEvent(motionEvent); } } @@ -1042,16 +1046,6 @@ void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) } } -QAccessibleInterface *RenderWidgetHostViewQt::GetQtAccessible() -{ - // Assume we have a screen reader doing stuff - CreateBrowserAccessibilityManagerIfNeeded(); - content::BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected(); - content::BrowserAccessibility *acc = GetBrowserAccessibilityManager()->GetRoot(); - content::BrowserAccessibilityQt *accQt = static_cast<content::BrowserAccessibilityQt*>(acc); - return accQt; -} - void RenderWidgetHostViewQt::didFirstVisuallyNonEmptyLayout() { m_didFirstVisuallyNonEmptyLayout = true; diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index d4a3ff248..93e7e75b4 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -44,12 +44,15 @@ #include "cc/resources/transferable_resource.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "content/common/gpu/gpu_messages.h" +#include "content/common/view_messages.h" #include "ui/events/gesture_detection/filtered_gesture_provider.h" #include <QMap> #include <QPoint> #include <QRect> #include <QtGlobal> #include <QtGui/qaccessible.h> +#include <QtGui/QTouchEvent> #include "delegated_frame_node.h" @@ -59,7 +62,6 @@ class QFocusEvent; class QHoverEvent; class QKeyEvent; class QMouseEvent; -class QTouchEvent; class QVariant; class QWheelEvent; class QAccessibleInterface; @@ -91,9 +93,10 @@ class RenderWidgetHostViewQt : public content::RenderWidgetHostViewBase , public ui::GestureProviderClient , public RenderWidgetHostViewQtDelegateClient - , public content::BrowserAccessibilityDelegate , public base::SupportsWeakPtr<RenderWidgetHostViewQt> +#ifndef QT_NO_ACCESSIBILITY , public QAccessible::ActivationObserver +#endif // QT_NO_ACCESSIBILITY { public: RenderWidgetHostViewQt(content::RenderWidgetHost* widget); @@ -108,6 +111,7 @@ public: virtual content::RenderWidgetHost* GetRenderWidgetHost() const Q_DECL_OVERRIDE; virtual void SetSize(const gfx::Size& size) Q_DECL_OVERRIDE; virtual void SetBounds(const gfx::Rect&) Q_DECL_OVERRIDE; + virtual gfx::Vector2dF GetLastScrollOffset() const 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; @@ -127,22 +131,16 @@ public: virtual void Blur() Q_DECL_OVERRIDE; virtual void UpdateCursor(const content::WebCursor&) Q_DECL_OVERRIDE; virtual void SetIsLoading(bool) Q_DECL_OVERRIDE; - virtual void TextInputStateChanged(const ViewHostMsg_TextInputState_Params& params) Q_DECL_OVERRIDE; + virtual void TextInputTypeChanged(ui::TextInputType type, ui::TextInputMode mode, bool can_compose_inline, int flags) Q_DECL_OVERRIDE; virtual void ImeCancelComposition() Q_DECL_OVERRIDE; virtual void ImeCompositionRangeChanged(const gfx::Range&, const std::vector<gfx::Rect>&) Q_DECL_OVERRIDE; virtual void RenderProcessGone(base::TerminationStatus, int) Q_DECL_OVERRIDE; virtual void Destroy() Q_DECL_OVERRIDE; virtual void SetTooltipText(const base::string16 &tooltip_text) 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, const SkBitmap::Config config) Q_DECL_OVERRIDE; + virtual void CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, content::CopyFromCompositingSurfaceCallback& callback, const SkColorType color_type) 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 AcceleratedSurfaceInitialized(int host_id, int route_id) 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(blink::WebScreenInfo* results) Q_DECL_OVERRIDE; @@ -173,7 +171,6 @@ public: void handleInputMethodEvent(QInputMethodEvent*); #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 } @@ -202,21 +199,10 @@ public: #endif // defined(OS_WIN) // Overridden from content::BrowserAccessibilityDelegate - virtual void AccessibilitySetFocus(int acc_obj_id) Q_DECL_OVERRIDE; - virtual void AccessibilityDoDefaultAction(int acc_obj_id) Q_DECL_OVERRIDE; - virtual void AccessibilityShowMenu(int acc_obj_id) Q_DECL_OVERRIDE { } - virtual void AccessibilityScrollToMakeVisible(int acc_obj_id, gfx::Rect subfocus) Q_DECL_OVERRIDE; - virtual void AccessibilityScrollToPoint(int acc_obj_id, gfx::Point point) Q_DECL_OVERRIDE; - virtual void AccessibilitySetTextSelection(int acc_obj_id, int start_offset, int end_offset) Q_DECL_OVERRIDE; - virtual bool AccessibilityViewHasFocus() const Q_DECL_OVERRIDE; - virtual gfx::Rect AccessibilityGetViewBounds() const Q_DECL_OVERRIDE { return GetViewBounds(); } - virtual gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds) const Q_DECL_OVERRIDE { return gfx::Point(); } - virtual void AccessibilityHitTest(const gfx::Point& point) Q_DECL_OVERRIDE { } - virtual void AccessibilityFatalError() Q_DECL_OVERRIDE; + virtual content::BrowserAccessibilityManager* CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate) Q_DECL_OVERRIDE; +#ifndef QT_NO_ACCESSIBILITY virtual void accessibilityActiveChanged(bool active) Q_DECL_OVERRIDE; - - QAccessibleInterface *GetQtAccessible(); - +#endif // QT_NO_ACCESSIBILITY void didFirstVisuallyNonEmptyLayout(); private: @@ -226,7 +212,6 @@ private: float dpiScale() const; bool IsPopup() const; - void CreateBrowserAccessibilityManagerIfNeeded(); content::RenderWidgetHostImpl *m_host; ui::FilteredGestureProvider m_gestureProvider; @@ -235,7 +220,7 @@ private: QMap<int, int> m_touchIdMapping; scoped_ptr<RenderWidgetHostViewQtDelegate> m_delegate; - QExplicitlySharedDataPointer<DelegatedFrameNodeData> m_frameNodeData; + QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; cc::ReturnedResourceArray m_resourcesToRelease; bool m_needsDelegatedFrameAck; bool m_didFirstVisuallyNonEmptyLayout; @@ -248,8 +233,11 @@ private: QRect m_cursorRect; size_t m_anchorPositionWithinSelection; size_t m_cursorPositionWithinSelection; + QPoint m_lockedMousePosition; bool m_initPending; + + gfx::Vector2dF m_lastScrollOffset; }; #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 index 3f6d9caac..018a914d8 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -46,7 +46,10 @@ QT_BEGIN_NAMESPACE class QCursor; class QEvent; class QPainter; +class QSGImageNode; +class QSGLayer; class QSGNode; +class QSGTexture; class QVariant; class QWindow; class QInputMethodEvent; @@ -74,10 +77,15 @@ public: virtual QRectF contentsRect() const = 0; virtual void setKeyboardFocus() = 0; virtual bool hasKeyboardFocus() = 0; + virtual void lockMouse() = 0; + virtual void unlockMouse() = 0; virtual void show() = 0; virtual void hide() = 0; virtual bool isVisible() const = 0; virtual QWindow* window() const = 0; + virtual QSGTexture *createTextureFromImage(const QImage &) = 0; + virtual QSGLayer *createLayer() = 0; + virtual QSGImageNode *createImageNode() = 0; virtual void update() = 0; virtual void updateCursor(const QCursor &) = 0; virtual void resize(int width, int height) = 0; diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index bfc5c389f..f8970e7a0 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -38,6 +38,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/common/localized_error.h" +#include "components/error_page/common/error_page_params.h" #include "components/visitedlink/renderer/visitedlink_slave.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_thread.h" @@ -47,8 +48,9 @@ #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" -#include "webkit/common/webpreferences.h" +#include "content/public/common/web_preferences.h" +#include "renderer/web_channel_ipc_transport.h" #include "renderer/qt_render_view_observer.h" #include "grit/renderer_resources.h" @@ -65,14 +67,17 @@ ContentRendererClientQt::~ContentRendererClientQt() void ContentRendererClientQt::RenderThreadStarted() { + content::RenderThread *renderThread = content::RenderThread::Get(); + renderThread->RegisterExtension(WebChannelIPCTransport::getV8Extension()); m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave); - content::RenderThread::Get()->AddObserver(m_visitedLinkSlave.data()); + renderThread->AddObserver(m_visitedLinkSlave.data()); } void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view) { - // RenderViewObserver destroys itself with its RenderView. + // RenderViewObservers destroy themselves with their RenderView. new QtRenderViewObserver(render_view); + new WebChannelIPCTransport(render_view); } bool ContentRendererClientQt::HasErrorPage(int httpStatusCode, std::string *errorDomain) @@ -107,7 +112,7 @@ void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderView* ren // NetErrorHelper::GetErrorStringsForDnsProbe, but that one is harder to untangle. LocalizedError::GetStrings(error.reason, error.domain.utf8(), error.unreachableURL, isPost , error.staleCopyInCache && !isPost, locale, renderView->GetAcceptLanguages() - , scoped_ptr<LocalizedError::ErrorPageParams>(), &errorStrings); + , scoped_ptr<error_page::ErrorPageParams>(), &errorStrings); resourceId = IDR_NET_ERROR_HTML; diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp new file mode 100644 index 000000000..0491a6103 --- /dev/null +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "renderer/web_channel_ipc_transport.h" + +#include "common/qt_messages.h" + +#include "content/public/renderer/render_view.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "v8/include/v8.h" + +#include <QJsonDocument> + +static const char kWebChannelTransportExtensionName[] = "v8/WebChannelTransport"; + +static const char kWebChannelTransportApi[] = + "if (typeof(navigator) === 'undefined')" \ + " navigator = {};" \ + "if (typeof(navigator.qtWebChannelTransport) === 'undefined')" \ + " navigator.qtWebChannelTransport = {};" \ + "navigator.qtWebChannelTransport.send = function(message) {" \ + " native function NativeQtSendMessage();" \ + " NativeQtSendMessage(message);" \ + "};"; + +class WebChannelTransportExtension : public v8::Extension { +public: + static content::RenderView *GetRenderView(); + + WebChannelTransportExtension() : v8::Extension(kWebChannelTransportExtensionName, kWebChannelTransportApi) + { + } + + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(v8::Isolate* isolate, v8::Handle<v8::String> name) Q_DECL_OVERRIDE; + + static void NativeQtSendMessage(const v8::FunctionCallbackInfo<v8::Value>& args) + { + content::RenderView *renderView = GetRenderView(); + if (!renderView || args.Length() != 1) + return; + v8::Handle<v8::Value> val = args[0]; + if (!val->IsString() && !val->IsStringObject()) + return; + v8::String::Utf8Value utf8(val->ToString()); + + QByteArray valueData(*utf8, utf8.length()); + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(valueData, &error); + if (error.error != QJsonParseError::NoError) + qWarning("%s %d: Parsing error: %s",__FILE__, __LINE__, qPrintable(error.errorString())); + int size = 0; + const char *rawData = doc.rawData(&size); + renderView->Send(new WebChannelIPCTransportHost_SendMessage(renderView->GetRoutingID(), std::vector<char>(rawData, rawData + size))); + } +}; + +content::RenderView *WebChannelTransportExtension::GetRenderView() +{ + blink::WebLocalFrame *webframe = blink::WebLocalFrame::frameForCurrentContext(); + DCHECK(webframe) << "There should be an active frame since we just got a native function called."; + if (!webframe) + return 0; + + blink::WebView *webview = webframe->view(); + if (!webview) + return 0; // can happen during closing + + return content::RenderView::FromWebView(webview); +} + +v8::Handle<v8::FunctionTemplate> WebChannelTransportExtension::GetNativeFunctionTemplate(v8::Isolate *isolate, v8::Handle<v8::String> name) +{ + if (name->Equals(v8::String::NewFromUtf8(isolate, "NativeQtSendMessage"))) + return v8::FunctionTemplate::New(isolate, NativeQtSendMessage); + + return v8::Handle<v8::FunctionTemplate>(); +} + +WebChannelIPCTransport::WebChannelIPCTransport(content::RenderView *renderView) + : content::RenderViewObserver(renderView) +{ +} + +void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> &binaryJSON) +{ + blink::WebView *webView = render_view()->GetWebView(); + if (!webView) + return; + + QJsonDocument doc = QJsonDocument::fromRawData(binaryJSON.data(), binaryJSON.size(), QJsonDocument::BypassValidation); + Q_ASSERT(doc.isObject()); + QByteArray json = doc.toJson(QJsonDocument::Compact); + + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handleScope(isolate); + blink::WebFrame *frame = webView->mainFrame(); + v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); + v8::Context::Scope contextScope(context); + + v8::Handle<v8::Object> global(context->Global()); + v8::Handle<v8::Value> navigatorValue(global->Get(v8::String::NewFromUtf8(isolate, "navigator"))); + if (!navigatorValue->IsObject()) + return; + v8::Handle<v8::Value> navigatorQtValue(navigatorValue->ToObject()->Get(v8::String::NewFromUtf8(isolate, "qtWebChannelTransport"))); + if (!navigatorQtValue->IsObject()) + return; + v8::Handle<v8::Value> onmessageCallbackValue(navigatorQtValue->ToObject()->Get(v8::String::NewFromUtf8(isolate, "onmessage"))); + if (!onmessageCallbackValue->IsFunction()) { + qWarning("onmessage is not a callable property of navigator.qtWebChannelTransport. Some things might not work as expected."); + return; + } + + v8::Handle<v8::Object> messageObject(v8::Object::New(isolate)); + messageObject->ForceSet(v8::String::NewFromUtf8(isolate, "data") + , v8::String::NewFromUtf8(isolate, json.constData(), v8::String::kNormalString, json.size()) + , v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); + + v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(onmessageCallbackValue); + const int argc = 1; + v8::Handle<v8::Value> argv[argc]; + argv[0] = messageObject; + frame->callFunctionEvenIfScriptDisabled(callback, navigatorQtValue->ToObject(), argc, argv); +} + +v8::Extension *WebChannelIPCTransport::getV8Extension() +{ + return new WebChannelTransportExtension; +} + +bool WebChannelIPCTransport::OnMessageReceived(const IPC::Message &message) +{ + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(WebChannelIPCTransport, message) + IPC_MESSAGE_HANDLER(WebChannelIPCTransport_Message, dispatchWebChannelMessage) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} diff --git a/src/webengine/api/qquickwebenginesettings_p_p.h b/src/core/renderer/web_channel_ipc_transport.h index 8f3e95eea..29e819e95 100644 --- a/src/webengine/api/qquickwebenginesettings_p_p.h +++ b/src/core/renderer/web_channel_ipc_transport.h @@ -34,24 +34,26 @@ ** ****************************************************************************/ -#ifndef QQUICKWEBENGINESETTINGS_P_P_H -#define QQUICKWEBENGINESETTINGS_P_P_H +#ifndef NAVIGATOR_QT_EXTENSION_H +#define NAVIGATOR_QT_EXTENSION_H -#include "web_engine_settings.h" +#include "base/values.h" +#include "content/public/renderer/render_view_observer.h" +#include <QtCore/qcompilerdetection.h> -QT_BEGIN_NAMESPACE +namespace v8 { +class Extension; +} -class QQuickWebEngineSettingsPrivate : public WebEngineSettingsDelegate { +class WebChannelIPCTransport : public content::RenderViewObserver { public: - QQuickWebEngineSettingsPrivate(); - QQuickWebEngineSettingsPrivate(WebContentsAdapter *adapter); + static v8::Extension* getV8Extension(); - void apply() Q_DECL_OVERRIDE; - WebEngineSettings *fallbackSettings() const Q_DECL_OVERRIDE; + WebChannelIPCTransport(content::RenderView *); - QScopedPointer<WebEngineSettings> coreSettings; +private: + void dispatchWebChannelMessage(const std::vector<char> &binaryJSON); + virtual bool OnMessageReceived(const IPC::Message &message) Q_DECL_OVERRIDE; }; -QT_END_NAMESPACE - -#endif // QQUICKWEBENGINESETTINGS_P_P_H +#endif // NAVIGATOR_QT_EXTENSION_H diff --git a/src/core/resource_context_qt.h b/src/core/resource_context_qt.h index 490ef1789..e3f0292e7 100644 --- a/src/core/resource_context_qt.h +++ b/src/core/resource_context_qt.h @@ -60,9 +60,6 @@ public: 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: diff --git a/src/core/resources/devtools_discovery_page.html b/src/core/resources/devtools_discovery_page.html index 79463cc16..7aac74932 100644 --- a/src/core/resources/devtools_discovery_page.html +++ b/src/core/resources/devtools_discovery_page.html @@ -1,18 +1,55 @@ -<!-- -Copyright (c) 2013 BlackBerry Limited. All rights reserved. ---> <html> <head> -<title>QtWebEngine remote debugging</title> +<title>QtWebEngine Remote Debugging</title> <style> +body { + background-color: rgb(245, 245, 245); + font-family: Helvetica, Arial, sans-serif; + text-shadow: rgba(255, 255, 255, 0.496094) 0px 1px 0px; +} + +#caption { + color: black; + font-size: 16px; + margin-top: 30px; + margin-bottom: 0px; + margin-left: 70px; + height: 20px; + text-align: left; +} + +#items { + margin-left: 60px; + margin-right: 60px; + -webkit-box-orient: horizontal; + -webkit-box-lines: multiple; +} + +.frontend_ref { + color: black; + text-decoration: initial; +} + +.text { + background: no-repeat 0; + background-size: 16px; + font-size: 12px; + margin: 4px 0px 0px 4px; + overflow: hidden; + padding: 2px 0px 0px 20px; + text-align: left; + text-overflow: ellipsis; + white-space: nowrap; +} </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(); + var tabsListRequest = new XMLHttpRequest(); + tabsListRequest.open('GET', '/json/list', true); + tabsListRequest.onreadystatechange = onReady; + tabsListRequest.send(); } function onReady() { @@ -24,23 +61,35 @@ function onReady() { } } +function overrideFrontendUrl(item) { + if (window.location.hash) { + var overridden_url = window.location.hash.substr(1); + var ws_suffix = item.webSocketDebuggerUrl.replace('ws://', 'ws='); + if (overridden_url.indexOf('?') == -1) + return overridden_url + '?' + ws_suffix; + else + return overridden_url + '&' + ws_suffix; + } + return item.devtoolsFrontendUrl; +} + function appendItem(item_object) { var frontend_ref; if (item_object.devtoolsFrontendUrl) { frontend_ref = document.createElement('a'); - frontend_ref.href = item_object.devtoolsFrontendUrl; + frontend_ref.href = overrideFrontendUrl(item_object); frontend_ref.title = item_object.title; } else { frontend_ref = document.createElement('div'); - frontend_ref.title = 'The tab already has active debugging session'; + frontend_ref.title = 'The tab already has an active debug session'; } + frontend_ref.className = 'frontend_ref'; 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 + ')'; + text.className = 'text'; + text.innerText = item_object.description || item_object.title; + text.style.cssText = 'background-image:url(' + + item_object.faviconUrl + ')'; frontend_ref.appendChild(text); var item = document.createElement('p'); @@ -51,7 +100,9 @@ function appendItem(item_object) { </script> </head> <body onload='onLoad()'> - <div id='caption'>Inspectable WebContents</div> - <div id='items'></div> + <div id='caption'>Inspectable pages</div> + <div id='items'> + </div> + <hr> </body> </html> diff --git a/src/core/resources/repack_resources.gypi b/src/core/resources/repack_resources.gypi index 133813c60..b5d8c9d91 100644 --- a/src/core/resources/repack_resources.gypi +++ b/src/core/resources/repack_resources.gypi @@ -8,10 +8,10 @@ '<(SHARED_INTERMEDIATE_DIR)/net/net_resources.pak', '<(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak', '<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak', - '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_resources_100_percent.pak', - '<(SHARED_INTERMEDIATE_DIR)/webkit/blink_resources.pak', - '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources_100_percent.pak', - '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/webui_resources.pak', + '<(SHARED_INTERMEDIATE_DIR)/ui/resources/ui_resources_100_percent.pak', + '<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_resources.pak', + '<(SHARED_INTERMEDIATE_DIR)/content/app/resources/content_resources_100_percent.pak', + '<(SHARED_INTERMEDIATE_DIR)/ui/resources/webui_resources.pak', '<(SHARED_INTERMEDIATE_DIR)/chrome/renderer_resources_100_percent.pak', ], }, diff --git a/src/core/resources/resources.gyp b/src/core/resources/resources.gyp index 835a87cdf..5d4d83c05 100644 --- a/src/core/resources/resources.gyp +++ b/src/core/resources/resources.gyp @@ -14,8 +14,8 @@ 'qt_install_translations%': '', }, 'dependencies': [ - '<(chromium_src_dir)/webkit/webkit_resources.gyp:webkit_strings', - '<(chromium_src_dir)/webkit/webkit_resources.gyp:webkit_resources', + '<(chromium_src_dir)/content/app/strings/content_strings.gyp:content_strings', + '<(chromium_src_dir)/webkit/blink_resources.gyp:blink_resources', '<(chromium_src_dir)/content/browser/devtools/devtools_resources.gyp:devtools_resources', '../chrome_qt.gyp:chrome_resources', ], diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index 9d9cdd675..6bb755abc 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -39,16 +39,17 @@ #include <QColor> #include <QDateTime> +#include <QDir> #include <QMatrix4x4> #include <QRect> #include <QString> #include <QUrl> #include "base/files/file_path.h" #include "base/time/time.h" +#include "content/public/common/file_chooser_file_info.h" #include "third_party/skia/include/utils/SkMatrix44.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/rect.h" -#include "ui/shell_dialogs/selected_file_info.h" #include "url/gurl.h" inline QString toQt(const base::string16 &string) @@ -135,10 +136,14 @@ inline QDateTime toQt(base::Time time) return QDateTime::fromMSecsSinceEpoch(time.ToJavaTime()); } +inline base::Time toTime(const QDateTime &dateTime) { + return base::Time::FromInternalValue(dateTime.toMSecsSinceEpoch()); +} + inline base::FilePath::StringType toFilePathString(const QString &str) { #if defined(OS_WIN) - return str.toStdWString(); + return QDir::toNativeSeparators(str).toStdWString(); #else return str.toStdString(); #endif @@ -150,13 +155,16 @@ inline base::FilePath toFilePath(const QString &str) } template <typename T> -inline T fileListingHelper(const QString &) {qFatal("Specialization missing for %s.", Q_FUNC_INFO);} +inline T fileListingHelper(const QString &) {qFatal("Specialization missing for %s.", Q_FUNC_INFO); return T(); } template <> -inline ui::SelectedFileInfo fileListingHelper<ui::SelectedFileInfo>(const QString &file) +inline content::FileChooserFileInfo fileListingHelper<content::FileChooserFileInfo>(const QString &file) { - base::FilePath fp(toFilePathString(file)); - return ui::SelectedFileInfo(fp, fp); + content::FileChooserFileInfo choose_file; + base::FilePath fp(toFilePath(file)); + choose_file.file_path = fp; + choose_file.display_name = fp.BaseName().value(); + return choose_file; } template <> diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index 8ec600a85..d1f5aef5a 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -51,8 +51,8 @@ #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/channel_id_service.h" +#include "net/ssl/default_channel_id_store.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" @@ -61,125 +61,229 @@ #include "net/url_request/ftp_protocol_handler.h" #include "net/ftp/ftp_network_layer.h" -#include "network_delegate_qt.h" +#include "browser_context_adapter.h" #include "content_client_qt.h" +#include "network_delegate_qt.h" #include "qrc_protocol_handler_qt.h" +#include "type_conversion.h" static const char kQrcSchemeQt[] = "qrc"; using content::BrowserThread; -URLRequestContextGetterQt::URLRequestContextGetterQt(const base::FilePath &dataPath, const base::FilePath &cachePath, content::ProtocolHandlerMap *protocolHandlers) +URLRequestContextGetterQt::URLRequestContextGetterQt(BrowserContextAdapter *browserContext, content::ProtocolHandlerMap *protocolHandlers) : m_ignoreCertificateErrors(false) - , m_dataPath(dataPath) - , m_cachePath(cachePath) + , m_updateStorageSettings(false) + , m_updateCookieStore(false) + , m_updateHttpCache(false) + , m_browserContext(browserContext) { std::swap(m_protocolHandlers, *protocolHandlers); - // 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 + updateStorageSettings(); } net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() { if (!m_urlRequestContext) { - m_urlRequestContext.reset(new net::URLRequestContext()); - m_networkDelegate.reset(new NetworkDelegateQt); + m_networkDelegate.reset(new NetworkDelegateQt); m_urlRequestContext->set_network_delegate(m_networkDelegate.get()); - base::FilePath cookiesPath = m_dataPath.Append(FILE_PATH_LITERAL("Cookies")); - content::CookieStoreConfig cookieStoreConfig(cookiesPath, content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, NULL, NULL); - scoped_refptr<net::CookieStore> cookieStore = content::CreateCookieStore(cookieStoreConfig); + generateStorage(); + generateJobFactory(); + } + + return m_urlRequestContext.get(); +} + +void URLRequestContextGetterQt::updateStorageSettings() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + if (!m_proxyConfigService) { + // 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(). + m_proxyConfigService.reset(net::ProxyService::CreateSystemProxyConfigService( + content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)) + ); + } + if (m_storage && !m_updateStorageSettings) { + m_updateStorageSettings = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateStorage, this)); + } +} + +void URLRequestContextGetterQt::generateStorage() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_proxyConfigService); + m_updateStorageSettings = false; + + m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); + + generateCookieStore(); + generateUserAgent(); + + m_storage->set_channel_id_service(new net::ChannelIDService( + new net::DefaultChannelIDStore(NULL), + base::WorkerPool::GetTaskRunner(true))); + + 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()); + + scoped_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); + 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)); + + // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|. + m_storage->set_host_resolver(host_resolver.Pass()); + + generateHttpCache(); +} + +void URLRequestContextGetterQt::updateCookieStore() +{ + if (m_urlRequestContext && !m_updateCookieStore && !m_updateStorageSettings) { + m_updateCookieStore = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateCookieStore, this)); + } +} - 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", ContentClientQt::getUserAgent())); +void URLRequestContextGetterQt::generateCookieStore() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + m_updateCookieStore = false; - scoped_ptr<net::HostResolver> host_resolver( - net::HostResolver::CreateDefaultResolver(NULL)); + // Unset it first to get a chance to destroy and flush the old cookie store before before opening a new on possibly the same file. + m_storage->set_cookie_store(0); - m_storage->set_cert_verifier(net::CertVerifier::CreateDefault()); + net::CookieStore* cookieStore = 0; + switch (m_browserContext->persistentCookiesPolicy()) { + case BrowserContextAdapter::NoPersistentCookies: + cookieStore = + content::CreateCookieStore(content::CookieStoreConfig( + base::FilePath(), + content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES, + NULL, NULL) + ); + break; + case BrowserContextAdapter::AllowPersistentCookies: + cookieStore = + content::CreateCookieStore(content::CookieStoreConfig( + toFilePath(m_browserContext->cookiesPath()), + content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, + NULL, NULL) + ); + break; + case BrowserContextAdapter::ForcePersistentCookies: + cookieStore = + content::CreateCookieStore(content::CookieStoreConfig( + toFilePath(m_browserContext->cookiesPath()), + content::CookieStoreConfig::RESTORED_SESSION_COOKIES, + NULL, NULL) + ); + break; + } + m_storage->set_cookie_store(cookieStore); +} - m_storage->set_proxy_service(net::ProxyService::CreateUsingSystemProxyResolver(m_proxyConfigService.release(), 0, NULL)); +void URLRequestContextGetterQt::updateUserAgent() +{ + if (m_urlRequestContext && !m_updateStorageSettings) + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateUserAgent, this)); +} - m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); - m_storage->set_transport_security_state(new net::TransportSecurityState()); +void URLRequestContextGetterQt::generateUserAgent() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); - 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)); + m_storage->set_http_user_agent_settings( + new net::StaticHttpUserAgentSettings("en-us,en", m_browserContext->httpUserAgent().toStdString())); +} - base::FilePath cache_path = m_cachePath.Append(FILE_PATH_LITERAL("Cache")); - net::HttpCache::DefaultBackend* main_backend = +void URLRequestContextGetterQt::updateHttpCache() +{ + if (m_urlRequestContext && !m_updateHttpCache && !m_updateStorageSettings) { + m_updateHttpCache = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateHttpCache, this)); + } +} + +void URLRequestContextGetterQt::generateHttpCache() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + m_updateHttpCache = false; + + net::HttpCache::DefaultBackend* main_backend = 0; + switch (m_browserContext->httpCacheType()) { + case BrowserContextAdapter::MemoryHttpCache: + main_backend = + new net::HttpCache::DefaultBackend( + net::MEMORY_CACHE, + net::CACHE_BACKEND_DEFAULT, + base::FilePath(), + m_browserContext->httpCacheMaxSize(), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) + ); + break; + case BrowserContextAdapter::DiskHttpCache: + 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); - - - m_jobFactory.reset(new net::URLRequestJobFactoryImpl()); - - // Chromium has a few protocol handlers ready for us, only pick blob: and throw away the rest. - content::ProtocolHandlerMap::iterator it = m_protocolHandlers.find(url::kBlobScheme); - Q_ASSERT(it != m_protocolHandlers.end()); - m_jobFactory->SetProtocolHandler(it->first, it->second.release()); - m_protocolHandlers.clear(); - - m_jobFactory->SetProtocolHandler(url::kDataScheme, new net::DataProtocolHandler()); - m_jobFactory->SetProtocolHandler(url::kFileScheme, new net::FileProtocolHandler( - content::BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); - m_jobFactory->SetProtocolHandler(kQrcSchemeQt, new QrcProtocolHandlerQt()); - m_jobFactory->SetProtocolHandler(url::kFtpScheme, new net::FtpProtocolHandler( - new net::FtpNetworkLayer(m_urlRequestContext->host_resolver()))); - m_urlRequestContext->set_job_factory(m_jobFactory.get()); + toFilePath(m_browserContext->httpCachePath()), + m_browserContext->httpCacheMaxSize(), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) + ); + break; } - return m_urlRequestContext.get(); + 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.channel_id_service = m_urlRequestContext->channel_id_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; + network_session_params.host_resolver = m_urlRequestContext->host_resolver(); + + m_storage->set_http_transaction_factory(new net::HttpCache(network_session_params, main_backend)); } +void URLRequestContextGetterQt::generateJobFactory() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(!m_jobFactory); + m_jobFactory.reset(new net::URLRequestJobFactoryImpl()); + + // Chromium has a few protocol handlers ready for us, only pick blob: and throw away the rest. + content::ProtocolHandlerMap::iterator it = m_protocolHandlers.find(url::kBlobScheme); + Q_ASSERT(it != m_protocolHandlers.end()); + m_jobFactory->SetProtocolHandler(it->first, it->second.release()); + m_protocolHandlers.clear(); + + m_jobFactory->SetProtocolHandler(url::kDataScheme, new net::DataProtocolHandler()); + m_jobFactory->SetProtocolHandler(url::kFileScheme, new net::FileProtocolHandler( + content::BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); + m_jobFactory->SetProtocolHandler(kQrcSchemeQt, new QrcProtocolHandlerQt()); + m_jobFactory->SetProtocolHandler(url::kFtpScheme, + new net::FtpProtocolHandler(new net::FtpNetworkLayer(m_urlRequestContext->host_resolver()))); + + m_urlRequestContext->set_job_factory(m_jobFactory.get()); +} scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const { diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h index 6c9ac6d59..5f6048403 100644 --- a/src/core/url_request_context_getter_qt.h +++ b/src/core/url_request_context_getter_qt.h @@ -40,6 +40,7 @@ #include "net/url_request/url_request_context_getter.h" #include "base/files/file_path.h" +#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "content/public/browser/content_browser_client.h" @@ -50,25 +51,41 @@ #include "qglobal.h" namespace net { -class HostResolver; class MappedHostResolver; class NetworkDelegate; class ProxyConfigService; } +class BrowserContextAdapter; + class URLRequestContextGetterQt : public net::URLRequestContextGetter { public: - explicit URLRequestContextGetterQt(const base::FilePath &, const base::FilePath &, content::ProtocolHandlerMap *protocolHandlers); + explicit URLRequestContextGetterQt(BrowserContextAdapter *browserContext, content::ProtocolHandlerMap *protocolHandlers); virtual net::URLRequestContext *GetURLRequestContext() Q_DECL_OVERRIDE; virtual scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const Q_DECL_OVERRIDE; + // Called on the UI thread: + void updateStorageSettings(); + void updateUserAgent(); + void updateCookieStore(); + void updateHttpCache(); + private: virtual ~URLRequestContextGetterQt() {} + // Called on the IO thread: + void generateStorage(); + void generateCookieStore(); + void generateHttpCache(); + void generateUserAgent(); + void generateJobFactory(); + bool m_ignoreCertificateErrors; - base::FilePath m_dataPath; - base::FilePath m_cachePath; + volatile bool m_updateStorageSettings; + volatile bool m_updateCookieStore; + volatile bool m_updateHttpCache; + BrowserContextAdapter *m_browserContext; content::ProtocolHandlerMap m_protocolHandlers; scoped_ptr<net::ProxyConfigService> m_proxyConfigService; diff --git a/src/core/web_channel_ipc_transport_host.cpp b/src/core/web_channel_ipc_transport_host.cpp new file mode 100644 index 000000000..d940aeab7 --- /dev/null +++ b/src/core/web_channel_ipc_transport_host.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "web_channel_ipc_transport_host.h" + +#include "base/strings/string16.h" + +#include "common/qt_messages.h" +#include "type_conversion.h" + +#include <QJsonDocument> +#include <QJsonObject> + +WebChannelIPCTransportHost::WebChannelIPCTransportHost(content::WebContents *contents, QObject *parent) + : QWebChannelAbstractTransport(parent) + , content::WebContentsObserver(contents) +{ +} + +WebChannelIPCTransportHost::~WebChannelIPCTransportHost() +{ +} + +void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) +{ + QJsonDocument doc(message); + int size = 0; + const char *rawData = doc.rawData(&size); + Send(new WebChannelIPCTransport_Message(routing_id(), std::vector<char>(rawData, rawData + size))); +} + +void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector<char> &message) +{ + QJsonDocument doc = QJsonDocument::fromRawData(message.data(), message.size(), QJsonDocument::BypassValidation); + Q_ASSERT(doc.isObject()); + Q_EMIT messageReceived(doc.object(), this); +} + +bool WebChannelIPCTransportHost::OnMessageReceived(const IPC::Message &message) +{ + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(WebChannelIPCTransportHost, message) + IPC_MESSAGE_HANDLER(WebChannelIPCTransportHost_SendMessage, onWebChannelMessage) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} diff --git a/src/webenginewidgets/api/qwebenginesettings_p.h b/src/core/web_channel_ipc_transport_host.h index 830e8b360..d51ebba24 100644 --- a/src/webenginewidgets/api/qwebenginesettings_p.h +++ b/src/core/web_channel_ipc_transport_host.h @@ -34,31 +34,32 @@ ** ****************************************************************************/ -#ifndef QWEBENGINESETTINGS_P_H -#define QWEBENGINESETTINGS_P_H +#ifndef WEB_CHANNEL_IPC_TRANSPORT_H +#define WEB_CHANNEL_IPC_TRANSPORT_H -#include "web_engine_settings.h" -#include <QtCore/qcompilerdetection.h> -#include <QtCore/QScopedPointer> -QT_BEGIN_NAMESPACE +#include <QtWebChannel/QWebChannelAbstractTransport> +#include "content/public/browser/web_contents_observer.h" -class QWebEngineSettingsPrivate : public WebEngineSettingsDelegate { +#include "qtwebenginecoreglobal.h" +#include <QtCore/QObject> -public: - QWebEngineSettingsPrivate(); - void initDefaults(); - void apply() Q_DECL_OVERRIDE; - WebEngineSettings *fallbackSettings() const Q_DECL_OVERRIDE; +QT_FORWARD_DECLARE_CLASS(QString) - QScopedPointer<WebEngineSettings> coreSettings; +class WebChannelIPCTransportHost : public QWebChannelAbstractTransport + , public content::WebContentsObserver +{ +public: + WebChannelIPCTransportHost(content::WebContents *, QObject *parent = 0); + virtual ~WebChannelIPCTransportHost(); - // This should only contain things specific to WebEngineWidgets which we don't want exposed to the core layer. - // For instance, the icon database would most likely be implemented at that level. + // QWebChannelAbstractTransport + virtual void sendMessage(const QJsonObject &message) Q_DECL_OVERRIDE; +private: + bool OnMessageReceived(const IPC::Message& message) Q_DECL_OVERRIDE; + void onWebChannelMessage(const std::vector<char> &message); }; -QT_END_NAMESPACE - -#endif // QWEBENGINESETTINGS_P_H +#endif // WEB_CHANNEL_IPC_TRANSPORT_H diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 3f223f733..306de1a45 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -41,12 +41,15 @@ #include "web_contents_adapter.h" #include "web_contents_adapter_p.h" +#include "browser_accessibility_qt.h" +#include "browser_context_adapter.h" #include "browser_context_qt.h" #include "content_browser_client_qt.h" #include "javascript_dialog_manager_qt.h" #include "media_capture_devices_dispatcher.h" #include "qt_render_view_observer_host.h" #include "type_conversion.h" +#include "web_channel_ipc_transport_host.h" #include "web_contents_adapter_client.h" #include "web_contents_view_qt.h" #include "web_engine_context.h" @@ -65,9 +68,9 @@ #include "content/public/common/page_zoom.h" #include "content/public/common/renderer_preferences.h" #include "content/public/common/url_constants.h" +#include "content/public/common/web_preferences.h" #include "ui/shell_dialogs/selected_file_info.h" #include "third_party/WebKit/public/web/WebFindOptions.h" -#include "webkit/common/webpreferences.h" #include <QDir> #include <QGuiApplication> @@ -75,6 +78,7 @@ #include <QStyleHints> #include <QVariant> #include <QtGui/qaccessible.h> +#include <QtWebChannel/QWebChannel> static const int kTestWindowWidth = 800; static const int kTestWindowHeight = 600; @@ -175,9 +179,8 @@ static QStringList listRecursively(const QDir& dir) { return ret; } -static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient) +static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) { - 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); @@ -222,7 +225,7 @@ static void serializeNavigationHistory(const content::NavigationController &cont } } -void deserializeNavigationHistory(QDataStream &input, int *currentIndex, std::vector<content::NavigationEntry*> *entries) +static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, std::vector<content::NavigationEntry*> *entries, content::BrowserContext *browserContext) { int version; input >> version; @@ -274,11 +277,11 @@ void deserializeNavigationHistory(QDataStream &input, int *currentIndex, std::ve content::Referrer(toGurl(referrerUrl), static_cast<blink::WebReferrerPolicy>(referrerPolicy)), // Use a transition type of reload so that we don't incorrectly // increase the typed count. - content::PAGE_TRANSITION_RELOAD, + ui::PAGE_TRANSITION_RELOAD, false, // The extra headers are not sync'ed across sessions. std::string(), - ContentBrowserClientQt::Get()->browser_context()); + browserContext); entry->SetTitle(toString16(title)); entry->SetPageState(content::PageState::CreateFromEncodedData(std::string(pageState.data(), pageState.size()))); @@ -292,9 +295,35 @@ void deserializeNavigationHistory(QDataStream &input, int *currentIndex, std::ve } } +namespace { +static QList<WebContentsAdapter *> recursive_guard_loading_adapters; + +class LoadRecursionGuard { + public: + static bool isGuarded(WebContentsAdapter *adapter) + { + return recursive_guard_loading_adapters.contains(adapter); + } + LoadRecursionGuard(WebContentsAdapter *adapter) + : m_adapter(adapter) + { + recursive_guard_loading_adapters.append(adapter); + } + + ~LoadRecursionGuard() { + recursive_guard_loading_adapters.removeOne(m_adapter); + } + + private: + WebContentsAdapter *m_adapter; +}; +} // Anonymous namespace + WebContentsAdapterPrivate::WebContentsAdapterPrivate() // This has to be the first thing we create, and the last we destroy. : engineContext(WebEngineContext::current()) + , webChannel(0) + , adapterClient(0) , nextRequestId(1) , lastFindRequestId(0) { @@ -308,13 +337,13 @@ QExplicitlySharedDataPointer<WebContentsAdapter> WebContentsAdapter::createFromS { int currentIndex; std::vector<content::NavigationEntry*> entries; - deserializeNavigationHistory(input, ¤tIndex, &entries); + deserializeNavigationHistory(input, ¤tIndex, &entries, adapterClient->browserContextAdapter()->browserContext()); if (currentIndex == -1) return QExplicitlySharedDataPointer<WebContentsAdapter>(); // Unlike WebCore, Chromium only supports Restoring to a new WebContents instance. - content::WebContents* newWebContents = createBlankWebContents(adapterClient); + content::WebContents* newWebContents = createBlankWebContents(adapterClient, adapterClient->browserContextAdapter()->browserContext()); content::NavigationController &controller = newWebContents->GetController(); controller.Restore(currentIndex, content::NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY, &entries); @@ -347,10 +376,13 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) { Q_D(WebContentsAdapter); d->adapterClient = adapterClient; + // We keep a reference to browserContextAdapter to keep it alive as long as we use it. + // This is needed in case the QML WebEngineProfile is garbage collected before the WebEnginePage. + d->browserContextAdapter = adapterClient->browserContextAdapter(); // Create our own if a WebContents wasn't provided at construction. if (!d->webContents) - d->webContents.reset(createBlankWebContents(adapterClient)); + d->webContents.reset(createBlankWebContents(adapterClient, d->browserContextAdapter->browserContext())); // This might replace any adapter that has been initialized with this WebEngineSettings. adapterClient->webEngineSettings()->setWebContentsAdapter(this); @@ -421,9 +453,22 @@ void WebContentsAdapter::reload() void WebContentsAdapter::load(const QUrl &url) { + // The situation can occur when relying on the editingFinished signal in QML to set the url + // of the WebView. + // When enter is pressed, onEditingFinished fires and the url of the webview is set, which + // calls into this and focuses the webview, taking the focus from the TextField/TextInput, + // which in turn leads to editingFinished firing again. This scenario would cause a crash + // down the line when unwinding as the first RenderWidgetHostViewQtDelegateQuick instance is + // a dangling pointer by that time. + + if (LoadRecursionGuard::isGuarded(this)) + return; + LoadRecursionGuard guard(this); + Q_UNUSED(guard); + Q_D(WebContentsAdapter); content::NavigationController::LoadURLParams params(toGurl(url)); - params.transition_type = content::PageTransitionFromInt(content::PAGE_TRANSITION_TYPED | content::PAGE_TRANSITION_FROM_ADDRESS_BAR); + params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); d->webContents->GetController().LoadURLWithParams(params); d->webContents->Focus(); } @@ -623,17 +668,30 @@ qreal WebContentsAdapter::currentZoomFactor() const return content::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(d->webContents.get())); } -void WebContentsAdapter::enableInspector(bool enable) +BrowserContextQt* WebContentsAdapter::browserContext() { - ContentBrowserClientQt::Get()->enableInspector(enable); + Q_D(WebContentsAdapter); + return d->browserContextAdapter ? d->browserContextAdapter->browserContext() : d->webContents ? static_cast<BrowserContextQt*>(d->webContents->GetBrowserContext()) : 0; +} + +BrowserContextAdapter* WebContentsAdapter::browserContextAdapter() +{ + Q_D(WebContentsAdapter); + return d->browserContextAdapter ? d->browserContextAdapter.data() : d->webContents ? static_cast<BrowserContextQt*>(d->webContents->GetBrowserContext())->adapter() : 0; } +#ifndef QT_NO_ACCESSIBILITY QAccessibleInterface *WebContentsAdapter::browserAccessible() { Q_D(const WebContentsAdapter); - RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt*>(d->webContents->GetRenderWidgetHostView()); - return rwhv ? rwhv->GetQtAccessible() : Q_NULLPTR; + content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); + Q_ASSERT(rvh); + content::BrowserAccessibilityManager *manager = static_cast<content::RenderFrameHostImpl*>(rvh->GetMainFrame())->GetOrCreateBrowserAccessibilityManager(); + content::BrowserAccessibility *acc = manager->GetRoot(); + content::BrowserAccessibilityQt *accQt = static_cast<content::BrowserAccessibilityQt*>(acc); + return accQt; } +#endif // QT_NO_ACCESSIBILITY void WebContentsAdapter::runJavaScript(const QString &javaScript) { @@ -700,7 +758,7 @@ void WebContentsAdapter::stopFinding() d->webContents->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); } -void WebContentsAdapter::updateWebPreferences(const WebPreferences & webPreferences) +void WebContentsAdapter::updateWebPreferences(const content::WebPreferences & webPreferences) { Q_D(WebContentsAdapter); d->webContents->GetRenderViewHost()->UpdateWebkitPreferences(webPreferences); @@ -724,6 +782,26 @@ void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(d->webContents.get(), securityOrigin, flags); } +void WebContentsAdapter::runGeolocationRequestCallback(const QUrl &securityOrigin, bool allowed) +{ + Q_D(WebContentsAdapter); + d->webContentsDelegate->geolocationPermissionReply(securityOrigin, allowed); +} + +void WebContentsAdapter::grantMouseLockPermission(bool granted) +{ + Q_D(WebContentsAdapter); + + if (granted) { + if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(d->webContents->GetRenderWidgetHostView())) + rwhv->Focus(); + else + granted = false; + } + + d->webContents->GotResponseToLockMouseRequest(granted); +} + void WebContentsAdapter::dpiScaleChanged() { Q_D(WebContentsAdapter); @@ -734,6 +812,11 @@ void WebContentsAdapter::dpiScaleChanged() impl->NotifyScreenInfoChanged(); } +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::Open, content::FileChooserParams::Open) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::OpenMultiple, content::FileChooserParams::OpenMultiple) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::UploadFolder, content::FileChooserParams::UploadFolder) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::Save, content::FileChooserParams::Save) + void WebContentsAdapter::filesSelectedInChooser(const QStringList &fileList, WebContentsAdapterClient::FileChooserMode mode) { Q_D(WebContentsAdapter); @@ -743,5 +826,35 @@ void WebContentsAdapter::filesSelectedInChooser(const QStringList &fileList, Web if (mode == WebContentsAdapterClient::UploadFolder && !fileList.isEmpty() && QFileInfo(fileList.first()).isDir()) // Enumerate the directory files = listRecursively(QDir(fileList.first())); - rvh->FilesSelectedInChooser(toVector<ui::SelectedFileInfo>(files), static_cast<content::FileChooserParams::Mode>(mode)); + rvh->FilesSelectedInChooser(toVector<content::FileChooserFileInfo>(files), static_cast<content::FileChooserParams::Mode>(mode)); +} + +content::WebContents *WebContentsAdapter::webContents() const +{ + Q_D(const WebContentsAdapter); + return d->webContents.get(); +} + +QWebChannel *WebContentsAdapter::webChannel() const +{ + Q_D(const WebContentsAdapter); + return d->webChannel; +} + +void WebContentsAdapter::setWebChannel(QWebChannel *channel) +{ + Q_D(WebContentsAdapter); + if (d->webChannel == channel) + return; + if (!d->webChannelTransport.get()) + d->webChannelTransport.reset(new WebChannelIPCTransportHost(d->webContents.get())); + else + d->webChannel->disconnectFrom(d->webChannelTransport.get()); + + d->webChannel = channel; + if (!channel) { + d->webChannelTransport.reset(); + return; + } + channel->connectTo(d->webChannelTransport.get()); } diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 6bec50316..6ba7c4b0a 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -47,11 +47,16 @@ namespace content { class WebContents; +struct WebPreferences; } +class BrowserContextQt; +class MessagePassingInterface; class WebContentsAdapterPrivate; -struct WebPreferences; -QT_FORWARD_DECLARE_CLASS(QAccessibleInterface); +QT_BEGIN_NAMESPACE +class QAccessibleInterface; +class QWebChannel; +QT_END_NAMESPACE class QWEBENGINE_EXPORT WebContentsAdapter : public QSharedData { public: @@ -95,7 +100,6 @@ public: void serializeNavigationHistory(QDataStream &output); void setZoomFactor(qreal); qreal currentZoomFactor() const; - void enableInspector(bool); void filesSelectedInChooser(const QStringList &fileList, WebContentsAdapterClient::FileChooserMode); void runJavaScript(const QString &javaScript); quint64 runJavaScriptCallbackResult(const QString &javaScript); @@ -103,19 +107,28 @@ public: quint64 fetchDocumentInnerText(); quint64 findText(const QString &subString, bool caseSensitively, bool findBackward); void stopFinding(); - void updateWebPreferences(const WebPreferences &webPreferences); + void updateWebPreferences(const content::WebPreferences &webPreferences); void wasShown(); void wasHidden(); void grantMediaAccessPermission(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags flags); + void runGeolocationRequestCallback(const QUrl &securityOrigin, bool allowed); + void grantMouseLockPermission(bool granted); void dpiScaleChanged(); QAccessibleInterface *browserAccessible(); + BrowserContextQt* browserContext(); + BrowserContextAdapter* browserContextAdapter(); + QWebChannel *webChannel() const; + void setWebChannel(QWebChannel *); + + // meant to be used within WebEngineCore only + content::WebContents *webContents() const; private: Q_DISABLE_COPY(WebContentsAdapter); Q_DECLARE_PRIVATE(WebContentsAdapter); QScopedPointer<WebContentsAdapterPrivate> d_ptr; - friend class WebContentsDelegateQt; + }; #endif // WEB_CONTENTS_ADAPTER_H diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 8fd401fe4..26d7a03ea 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -46,9 +46,11 @@ #include <QStringList> #include <QUrl> +QT_FORWARD_DECLARE_CLASS(QKeyEvent) QT_FORWARD_DECLARE_CLASS(QVariant) +QT_FORWARD_DECLARE_CLASS(CertificateErrorController) -class CertificateErrorController; +class BrowserContextAdapter; class JavaScriptDialogController; class RenderWidgetHostViewQt; class RenderWidgetHostViewQtDelegate; @@ -153,6 +155,7 @@ public: virtual void loadVisuallyCommitted() = 0; virtual void loadFinished(bool success, const QUrl &url, int errorCode = 0, const QString &errorDescription = QString()) = 0; virtual void focusContainer() = 0; + virtual void unhandledKeyEvent(QKeyEvent *event) = 0; virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect & initialGeometry) = 0; virtual void close() = 0; virtual bool contextMenuRequested(const WebEngineContextMenuData&) = 0; @@ -168,13 +171,19 @@ public: virtual void passOnFocus(bool reverse) = 0; // returns the last QObject (QWidget/QQuickItem) based object in the accessibility // hierarchy before going into the BrowserAccessibility tree +#ifndef QT_NO_ACCESSIBILITY virtual QObject *accessibilityParentObject() = 0; +#endif // QT_NO_ACCESSIBILITY virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) = 0; virtual void authenticationRequired(const QUrl &requestUrl, const QString &realm, bool isProxy, const QString &challengingHost, QString *outUser, QString *outPassword) = 0; + virtual void runGeolocationPermissionRequest(const QUrl &securityOrigin) = 0; virtual void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) = 0; + virtual void runMouseLockPermissionRequest(const QUrl &securityOrigin) = 0; virtual WebEngineSettings *webEngineSettings() const = 0; - virtual void allowCertificateError(const QExplicitlySharedDataPointer<CertificateErrorController> &errorController) = 0; + virtual void allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) = 0; + + virtual BrowserContextAdapter* browserContextAdapter() = 0; }; diff --git a/src/core/web_contents_adapter_p.h b/src/core/web_contents_adapter_p.h index 28df0113a..dcdf97f2e 100644 --- a/src/core/web_contents_adapter_p.h +++ b/src/core/web_contents_adapter_p.h @@ -42,19 +42,27 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include <QExplicitlySharedDataPointer> + +class BrowserContextAdapter; class QtRenderViewObserverHost; +class WebChannelIPCTransportHost; class WebContentsAdapterClient; class WebContentsDelegateQt; class WebEngineContext; +QT_FORWARD_DECLARE_CLASS(QWebChannel) class WebContentsAdapterPrivate { public: WebContentsAdapterPrivate(); ~WebContentsAdapterPrivate(); scoped_refptr<WebEngineContext> engineContext; + QExplicitlySharedDataPointer<BrowserContextAdapter> browserContextAdapter; scoped_ptr<content::WebContents> webContents; scoped_ptr<WebContentsDelegateQt> webContentsDelegate; scoped_ptr<QtRenderViewObserverHost> renderViewObserverHost; + scoped_ptr<WebChannelIPCTransportHost> webChannelTransport; + QWebChannel *webChannel; WebContentsAdapterClient *adapterClient; quint64 nextRequestId; int lastFindRequestId; diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index c2cccfedb..03e03acc3 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -40,6 +40,7 @@ #include "web_contents_delegate_qt.h" +#include "browser_context_adapter.h" #include "media_capture_devices_dispatcher.h" #include "type_conversion.h" #include "web_contents_adapter_client.h" @@ -52,12 +53,13 @@ #include "content/public/browser/invalidate_type.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/favicon_url.h" #include "content/public/common/file_chooser_params.h" #include "content/public/common/frame_navigate_params.h" #include "content/public/common/url_constants.h" -#include "webkit/common/webpreferences.h" +#include "content/public/common/web_preferences.h" // Maps the LogSeverity defines in base/logging.h to the web engines message levels. static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(int32 messageLevel) { @@ -83,7 +85,7 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents if (params.disposition != CURRENT_TAB) { WebContentsAdapter *targetAdapter = createWindow(0, params.disposition, gfx::Rect(), params.user_gesture); if (targetAdapter) - target = targetAdapter->d_func()->webContents.get(); + target = targetAdapter->webContents(); } content::NavigationController::LoadURLParams load_url_params(params.url); @@ -101,7 +103,7 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents return target; } -void WebContentsDelegateQt::NavigationStateChanged(const content::WebContents* source, unsigned changed_flags) +void WebContentsDelegateQt::NavigationStateChanged(const content::WebContents* source, content::InvalidateTypes changed_flags) { if (changed_flags & content::INVALIDATE_TYPE_URL) m_viewClient->urlChanged(toQt(source->GetVisibleURL())); @@ -129,21 +131,28 @@ void WebContentsDelegateQt::LoadProgressChanged(content::WebContents* source, do m_viewClient->loadProgressChanged(qRound(progress * 100)); } -void WebContentsDelegateQt::DidStartProvisionalLoadForFrame(int64 frame_id, int64 parent_frame_id, bool is_main_frame, const GURL &validated_url, bool isErrorPage, bool, content::RenderViewHost*) +void WebContentsDelegateQt::HandleKeyboardEvent(content::WebContents *, const content::NativeWebKeyboardEvent &event) { - if (isErrorPage) { - m_loadingErrorFrameList.append(frame_id); + Q_ASSERT(!event.skip_in_browser); + if (event.os_event) + m_viewClient->unhandledKeyEvent(reinterpret_cast<QKeyEvent *>(event.os_event)); +} + +void WebContentsDelegateQt::DidStartProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host, const GURL& validated_url, bool is_error_page, bool is_iframe_srcdoc) +{ + if (is_error_page) { + m_loadingErrorFrameList.append(render_frame_host->GetRoutingID()); return; } - if (!is_main_frame) + if (render_frame_host->GetParent()) return; m_loadingErrorFrameList.clear(); m_viewClient->loadStarted(toQt(validated_url)); } -void WebContentsDelegateQt::DidCommitProvisionalLoadForFrame(int64 frame_id, const base::string16& frame_unique_name, bool is_main_frame, const GURL& url, content::PageTransition transition_type, content::RenderViewHost* render_view_host) +void WebContentsDelegateQt::DidCommitProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host, const GURL& url, ui::PageTransition transition_type) { // Make sure that we don't set the findNext WebFindOptions on a new frame. m_lastSearchedString = QString(); @@ -152,32 +161,32 @@ void WebContentsDelegateQt::DidCommitProvisionalLoadForFrame(int64 frame_id, con m_viewClient->loadCommitted(); } -void WebContentsDelegateQt::DidFailProvisionalLoad(int64 frame_id, const base::string16& frame_unique_name, bool is_main_frame, const GURL& validated_url, int error_code, const base::string16& error_description, content::RenderViewHost* render_view_host) +void WebContentsDelegateQt::DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description) { - DidFailLoad(frame_id, validated_url, is_main_frame, error_code, error_description, render_view_host); + DidFailLoad(render_frame_host, validated_url, error_code, error_description); } -void WebContentsDelegateQt::DidFailLoad(int64 frame_id, const GURL &validated_url, bool is_main_frame, int error_code, const base::string16 &error_description, content::RenderViewHost *rvh) +void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description) { - if (m_loadingErrorFrameList.removeOne(frame_id) || !is_main_frame) + if (m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID()) || render_frame_host->GetParent()) return; m_viewClient->loadFinished(false, toQt(validated_url), error_code, toQt(error_description)); m_viewClient->loadProgressChanged(0); } -void WebContentsDelegateQt::DidFinishLoad(int64 frame_id, const GURL &url, bool is_main_frame, content::RenderViewHost*) +void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) { - if (m_loadingErrorFrameList.removeOne(frame_id)) { - Q_ASSERT(url.is_valid() && url.spec() == content::kUnreachableWebDataURL); + if (m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID())) { + Q_ASSERT(validated_url.is_valid() && validated_url.spec() == content::kUnreachableWebDataURL); m_viewClient->iconChanged(QUrl()); return; } - if (!is_main_frame) + if (render_frame_host->GetParent()) return; - m_viewClient->loadFinished(true, toQt(url)); + m_viewClient->loadFinished(true, toQt(validated_url)); content::NavigationEntry *entry = web_contents()->GetController().GetActiveEntry(); if (!entry) @@ -222,8 +231,8 @@ bool WebContentsDelegateQt::IsFullscreenForTabOrPending(const content::WebConten return m_viewClient->isFullScreen(); } -Q_STATIC_ASSERT_X(static_cast<int>(WebContentsAdapterClient::Open) == static_cast<int>(content::FileChooserParams::Open), "Enums out of sync"); -Q_STATIC_ASSERT_X(static_cast<int>(WebContentsAdapterClient::Save) == static_cast<int>(content::FileChooserParams::Save), "Enums out of sync"); +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::Open, content::FileChooserParams::Open) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::Save, content::FileChooserParams::Save) void WebContentsDelegateQt::RunFileChooser(content::WebContents *web_contents, const content::FileChooserParams ¶ms) { @@ -259,22 +268,31 @@ void WebContentsDelegateQt::RequestMediaAccessPermission(content::WebContents *w MediaCaptureDevicesDispatcher::GetInstance()->processMediaAccessRequest(m_viewClient, web_contents, request, callback); } -void WebContentsDelegateQt::UpdateTargetURL(content::WebContents *source, int32 page_id, const GURL &url) +void WebContentsDelegateQt::UpdateTargetURL(content::WebContents* source, const GURL& url) { Q_UNUSED(source) - Q_UNUSED(page_id) m_viewClient->didUpdateTargetURL(toQt(url)); } -void WebContentsDelegateQt::DidNavigateAnyFrame(const content::LoadCommittedDetails &, const content::FrameNavigateParams ¶ms) +void WebContentsDelegateQt::DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host, const content::LoadCommittedDetails& details, const content::FrameNavigateParams& params) { - if (!params.should_update_history) + // VisistedLinksMaster asserts !IsOffTheRecord(). + if (!params.should_update_history || !m_viewClient->browserContextAdapter()->trackVisitedLinks()) return; - WebEngineContext::current()->visitedLinksManager()->addUrl(params.url); + m_viewClient->browserContextAdapter()->visitedLinksManager()->addUrl(params.url); } +void WebContentsDelegateQt::RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target) +{ + Q_UNUSED(user_gesture); -void WebContentsDelegateQt::overrideWebPreferences(content::WebContents *, WebPreferences *webPreferences) + if (last_unlocked_by_target) + web_contents->GotResponseToLockMouseRequest(true); + else + m_viewClient->runMouseLockPermissionRequest(toQt(web_contents->GetVisibleURL())); +} + +void WebContentsDelegateQt::overrideWebPreferences(content::WebContents *, content::WebPreferences *webPreferences) { m_viewClient->webEngineSettings()->overrideWebPreferences(webPreferences); } @@ -296,7 +314,30 @@ WebContentsAdapter *WebContentsDelegateQt::createWindow(content::WebContents *ne return newAdapter; } -void WebContentsDelegateQt::allowCertificateError(const QExplicitlySharedDataPointer<CertificateErrorController> &errorController) +void WebContentsDelegateQt::allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) { m_viewClient->allowCertificateError(errorController); } + +void WebContentsDelegateQt::requestGeolocationPermission(const GURL &requestingFrameOrigin, const base::Callback<void (bool)> &resultCallback) +{ + QUrl url = toQt(requestingFrameOrigin); + bool newRequest = !m_geolocationPermissionRequests.contains(url); + m_geolocationPermissionRequests[url] = resultCallback; + if (newRequest) + m_viewClient->runGeolocationPermissionRequest(url); +} + +void WebContentsDelegateQt::cancelGeolocationPermissionRequest(const GURL &requestingFrameOrigin) +{ + m_geolocationPermissionRequests.remove(toQt(requestingFrameOrigin)); + // FIXME: Tell the API layer to cancel the permission request? +} + +void WebContentsDelegateQt::geolocationPermissionReply(const QUrl &origin, bool permission) +{ + if (m_geolocationPermissionRequests.contains(origin)) { + m_geolocationPermissionRequests[origin].Run(permission); + m_geolocationPermissionRequests.remove(origin); + } +} diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 2ab5fc8cd..f3b231798 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -40,20 +40,23 @@ #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" +#include "base/callback.h" + #include "javascript_dialog_manager_qt.h" #include <QtCore/qcompilerdetection.h> +QT_FORWARD_DECLARE_CLASS(CertificateErrorController) + namespace content { class BrowserContext; class SiteInstance; class RenderViewHost; class JavaScriptDialogManager; class WebContents; + struct WebPreferences; } -struct WebPreferences; class WebContentsAdapterClient; -class CertificateErrorController; class WebContentsDelegateQt : public content::WebContentsDelegate , public content::WebContentsObserver @@ -65,17 +68,13 @@ public: void setLastSearchedString(const QString &s) { m_lastSearchedString = s; } int lastReceivedFindReply() const { return m_lastReceivedFindReply; } + // WebContentsDelegate overrides virtual content::WebContents *OpenURLFromTab(content::WebContents *source, const content::OpenURLParams ¶ms) Q_DECL_OVERRIDE; - virtual void NavigationStateChanged(const content::WebContents* source, unsigned changed_flags) Q_DECL_OVERRIDE; + virtual void NavigationStateChanged(const content::WebContents* source, content::InvalidateTypes 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 LoadProgressChanged(content::WebContents* source, double progress) Q_DECL_OVERRIDE; - virtual void DidStartProvisionalLoadForFrame(int64 frame_id, int64 parent_frame_id, bool is_main_frame, const GURL &validated_url, bool is_error_page, bool is_iframe_srcdoc, content::RenderViewHost *render_view_host) Q_DECL_OVERRIDE; - virtual void DidCommitProvisionalLoadForFrame(int64 frame_id, const base::string16& frame_unique_name, bool is_main_frame, const GURL& url, content::PageTransition transition_type, content::RenderViewHost* render_view_host) Q_DECL_OVERRIDE; - virtual void DidFailProvisionalLoad(int64 frame_id, const base::string16& frame_unique_name, bool is_main_frame, const GURL& validated_url, int error_code, const base::string16& error_description, content::RenderViewHost* render_view_host) Q_DECL_OVERRIDE; - virtual void DidFailLoad(int64 frame_id, const GURL &validated_url, bool is_main_frame, int error_code, const base::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(const std::vector<content::FaviconURL>& candidates) Q_DECL_OVERRIDE; + virtual void HandleKeyboardEvent(content::WebContents *source, const content::NativeWebKeyboardEvent &event) Q_DECL_OVERRIDE; virtual content::JavaScriptDialogManager *GetJavaScriptDialogManager() Q_DECL_OVERRIDE; virtual void ToggleFullscreenModeForTab(content::WebContents* web_contents, bool enter_fullscreen) Q_DECL_OVERRIDE; virtual bool IsFullscreenForTabOrPending(const content::WebContents* web_contents) const Q_DECL_OVERRIDE; @@ -83,15 +82,29 @@ public: virtual bool AddMessageToConsole(content::WebContents* source, int32 level, const base::string16& message, int32 line_no, const base::string16& source_id) Q_DECL_OVERRIDE; virtual void FindReply(content::WebContents *source, int request_id, int number_of_matches, const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update) Q_DECL_OVERRIDE; virtual void RequestMediaAccessPermission(content::WebContents* web_contents, const content::MediaStreamRequest& request, const content::MediaResponseCallback& callback) Q_DECL_OVERRIDE; - virtual void UpdateTargetURL(content::WebContents *source, int32 page_id, const GURL &url) Q_DECL_OVERRIDE; - virtual void DidNavigateAnyFrame(const content::LoadCommittedDetails&, const content::FrameNavigateParams& params) Q_DECL_OVERRIDE; + virtual void UpdateTargetURL(content::WebContents* source, const GURL& url) Q_DECL_OVERRIDE; + virtual void RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target) Q_DECL_OVERRIDE; - void overrideWebPreferences(content::WebContents *, WebPreferences*); - void allowCertificateError(const QExplicitlySharedDataPointer<CertificateErrorController> &) ; + // WebContentsObserver overrides + virtual void DidStartProvisionalLoadForFrame(content::RenderFrameHost *render_frame_host, const GURL &validated_url, bool is_error_page, bool is_iframe_srcdoc) Q_DECL_OVERRIDE; + virtual void DidCommitProvisionalLoadForFrame(content::RenderFrameHost *render_frame_host, const GURL &url, ui::PageTransition transition_type) Q_DECL_OVERRIDE; + virtual void DidFailProvisionalLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url, int error_code, const base::string16 &error_description) Q_DECL_OVERRIDE; + virtual void DidFailLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url, int error_code, const base::string16 &error_description) Q_DECL_OVERRIDE; + virtual void DidFinishLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url) Q_DECL_OVERRIDE; + virtual void DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) Q_DECL_OVERRIDE; + virtual void DidNavigateAnyFrame(content::RenderFrameHost *render_frame_host, const content::LoadCommittedDetails &details, const content::FrameNavigateParams ¶ms) Q_DECL_OVERRIDE; + + void overrideWebPreferences(content::WebContents *, content::WebPreferences*); + void allowCertificateError(const QSharedPointer<CertificateErrorController> &) ; + void requestGeolocationPermission(const GURL &requestingFrameOrigin, const base::Callback<void (bool)> &resultCallback); + void cancelGeolocationPermissionRequest(const GURL &requestingFrameOrigin); + void geolocationPermissionReply(const QUrl&, bool permission); private: WebContentsAdapter *createWindow(content::WebContents *new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture); + QHash<QUrl, base::Callback<void (bool)> > m_geolocationPermissionRequests; + WebContentsAdapterClient *m_viewClient; QString m_lastSearchedString; int m_lastReceivedFindReply; diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 5909ee510..af5b6dd19 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -54,7 +54,7 @@ void WebContentsViewQt::initialize(WebContentsAdapterClient* client) static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())->setAdapterClient(client); } -content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForWidget(content::RenderWidgetHost* render_widget_host) +content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForWidget(content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) { RenderWidgetHostViewQt *view = new RenderWidgetHostViewQt(render_widget_host); diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index d433718a7..5e8ff0f96 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -59,12 +59,13 @@ public: : m_webContents(webContents) , m_client(0) , m_factoryClient(0) + , m_allowOtherViews(false) { } void initialize(WebContentsAdapterClient* client); WebContentsAdapterClient *client() { return m_client; } - virtual content::RenderWidgetHostViewBase *CreateViewForWidget(content::RenderWidgetHost* render_widget_host) Q_DECL_OVERRIDE; + virtual content::RenderWidgetHostViewBase *CreateViewForWidget(content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) Q_DECL_OVERRIDE; virtual void CreateView(const gfx::Size& initial_size, gfx::NativeView context) Q_DECL_OVERRIDE; @@ -100,9 +101,6 @@ public: 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 StartDragging(const content::DropData& drop_data, blink::WebDragOperationsMask allowed_ops, const gfx::ImageSkia& image, const gfx::Vector2d& image_offset, const content::DragEventSourceInfo& event_info) Q_DECL_OVERRIDE; virtual void ShowContextMenu(content::RenderFrameHost *, const content::ContextMenuParams ¶ms) Q_DECL_OVERRIDE; @@ -110,9 +108,9 @@ public: virtual void TakeFocus(bool reverse) Q_DECL_OVERRIDE; #if defined(OS_MACOSX) - virtual void SetAllowOverlappingViews(bool overlapping) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual void SetAllowOtherViews(bool allow) Q_DECL_OVERRIDE { m_allowOtherViews = allow; } + virtual bool GetAllowOtherViews() const Q_DECL_OVERRIDE { return m_allowOtherViews; } 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; } virtual void SetOverlayView(WebContentsView* overlay, const gfx::Point& offset) { QT_NOT_YET_IMPLEMENTED } virtual void RemoveOverlayView() { QT_NOT_YET_IMPLEMENTED } @@ -122,6 +120,7 @@ private: content::WebContents *m_webContents; WebContentsAdapterClient *m_client; WebContentsAdapterClient *m_factoryClient; + bool m_allowOtherViews; }; #endif // WEB_CONTENTS_VIEW_QT_H diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 446f0e92c..df649606c 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -66,15 +66,17 @@ #include "content/public/app/startup_helper_win.h" #endif // OS_WIN +#include "browser_context_adapter.h" #include "content_browser_client_qt.h" #include "content_client_qt.h" #include "content_main_delegate_qt.h" +#include "dev_tools_http_handler_delegate_qt.h" #include "gl_context_qt.h" #include "media_capture_devices_dispatcher.h" #include "type_conversion.h" #include "surface_factory_qt.h" #include "web_engine_library_info.h" -#include "web_engine_visited_links_manager.h" +#include <QFileInfo> #include <QGuiApplication> #include <QOpenGLContext> #include <QStringList> @@ -90,6 +92,46 @@ void destroyContext() sContext = 0; } +bool usingANGLE() +{ +#if defined(Q_OS_WIN) + return QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES; +#else + return false; +#endif +} + +bool usingSoftwareDynamicGL() +{ +#if defined(Q_OS_WIN) + HMODULE handle = static_cast<HMODULE>(QOpenGLContext::openGLModuleHandle()); + wchar_t path[MAX_PATH]; + DWORD size = GetModuleFileName(handle, path, MAX_PATH); + QFileInfo openGLModule(QString::fromWCharArray(path, size)); + return openGLModule.fileName() == QLatin1String("opengl32sw.dll"); +#else + return false; +#endif +} + +bool usingQtQuick2DRenderer() +{ + const QStringList args = QGuiApplication::arguments(); + QString device; + for (int index = 0; index < args.count(); ++index) { + if (args.at(index).startsWith(QLatin1String("--device="))) { + device = args.at(index).mid(9); + break; + } + } + + if (device.isEmpty()) + device = QString::fromLocal8Bit(qgetenv("QMLSCENE_DEVICE")); + + // This assumes that the plugin is installed and is going to be used by QtQuick. + return device == QLatin1String("softwarecontext"); +} + } // namespace WebEngineContext::~WebEngineContext() @@ -103,7 +145,7 @@ WebEngineContext::~WebEngineContext() scoped_refptr<WebEngineContext> WebEngineContext::current() { - if (!sContext) { + if (!sContext.get()) { sContext = new WebEngineContext(); // Make sure that we ramp down Chromium before QApplication destroys its X connection, etc. qAddPostRoutine(destroyContext); @@ -111,9 +153,18 @@ scoped_refptr<WebEngineContext> WebEngineContext::current() return sContext; } -WebEngineVisitedLinksManager *WebEngineContext::visitedLinksManager() +BrowserContextAdapter* WebEngineContext::defaultBrowserContext() +{ + if (!m_defaultBrowserContext) + m_defaultBrowserContext = new BrowserContextAdapter(QStringLiteral("Default")); + return m_defaultBrowserContext.data(); +} + +BrowserContextAdapter* WebEngineContext::offTheRecordBrowserContext() { - return m_visitedLinksManager.get(); + if (!m_offTheRecordBrowserContext) + m_offTheRecordBrowserContext = new BrowserContextAdapter(true); + return m_offTheRecordBrowserContext.data(); } #ifndef CHROMIUM_VERSION @@ -142,16 +193,6 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kEnableDelegatedRenderer); parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); parsedCommandLine->AppendSwitch(switches::kInProcessGPU); - parsedCommandLine->AppendSwitch(switches::kDisableDesktopNotifications); - -#if defined(OS_WIN) - parsedCommandLine->AppendSwitch(switches::kDisableD3D11); - // ANGLE doesn't support multi-threading, doing texture upload from the GPU thread - // hasn't been causing problems yet but doing rendering there is conflicting with - // Qt's rendering of the scene graph. - parsedCommandLine->AppendSwitch(switches::kDisableExperimentalWebGL); - parsedCommandLine->AppendSwitch(switches::kDisableAccelerated2dCanvas); -#endif #if defined(QTWEBENGINE_MOBILE_SWITCHES) // Inspired from the Android port's default switches @@ -180,16 +221,20 @@ WebEngineContext::WebEngineContext() GLContextHelper::initialize(); - const char *glType; - switch (QOpenGLContext::currentContext()->openGLModuleType()) { - case QOpenGLContext::LibGL: - glType = gfx::kGLImplementationDesktopName; - break; - case QOpenGLContext::LibGLES: - glType = gfx::kGLImplementationEGLName; - break; + if (usingANGLE() || usingSoftwareDynamicGL() || usingQtQuick2DRenderer()) { + parsedCommandLine->AppendSwitch(switches::kDisableGpu); + } else { + const char *glType = 0; + switch (QOpenGLContext::openGLModuleType()) { + case QOpenGLContext::LibGL: + glType = gfx::kGLImplementationDesktopName; + break; + case QOpenGLContext::LibGLES: + glType = gfx::kGLImplementationEGLName; + break; + } + parsedCommandLine->AppendSwitchASCII(switches::kUseGL, glType); } - parsedCommandLine->AppendSwitchASCII(switches::kUseGL, glType); content::UtilityProcessHostImpl::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread); content::RenderProcessHostImpl::RegisterRendererMainThreadFactory(content::CreateInProcessRendererThread); @@ -209,11 +254,9 @@ WebEngineContext::WebEngineContext() m_runLoop.reset(new base::RunLoop); m_runLoop->BeforeRun(); + m_devtools.reset(new DevToolsHttpHandlerDelegateQt); // Force the initialization of MediaCaptureDevicesDispatcher on the UI // thread to avoid a thread check assertion in its constructor when it // first gets referenced on the IO thread. MediaCaptureDevicesDispatcher::GetInstance(); - - // Ensure we have a VisitedLinksMaster instance up and running - m_visitedLinksManager.reset(new WebEngineVisitedLinksManager); } diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index d1cd9a7a5..80ce65507 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -40,6 +40,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include <QExplicitlySharedDataPointer> + namespace base { class RunLoop; } @@ -49,15 +51,17 @@ class BrowserMainRunner; class ContentMainRunner; } +class BrowserContextAdapter; class ContentMainDelegateQt; +class DevToolsHttpHandlerDelegateQt; class SurfaceFactoryQt; -class WebEngineVisitedLinksManager; class WebEngineContext : public base::RefCounted<WebEngineContext> { public: static scoped_refptr<WebEngineContext> current(); - WebEngineVisitedLinksManager *visitedLinksManager(); + BrowserContextAdapter *defaultBrowserContext(); + BrowserContextAdapter *offTheRecordBrowserContext(); private: friend class base::RefCounted<WebEngineContext>; @@ -71,7 +75,9 @@ private: #if defined(OS_ANDROID) scoped_ptr<SurfaceFactoryQt> m_surfaceFactory; #endif - scoped_ptr<WebEngineVisitedLinksManager> m_visitedLinksManager; + QExplicitlySharedDataPointer<BrowserContextAdapter> m_defaultBrowserContext; + QExplicitlySharedDataPointer<BrowserContextAdapter> m_offTheRecordBrowserContext; + scoped_ptr<DevToolsHttpHandlerDelegateQt> m_devtools; }; #endif // WEB_ENGINE_CONTEXT_H diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index 2d72dd5a2..110c9ae6a 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -38,7 +38,7 @@ #include "web_engine_library_info.h" #include "base/base_paths.h" -#include "base/file_util.h" +#include "base/files/file_util.h" #include "content/public/common/content_paths.h" #include "ui/base/ui_base_paths.h" #include "type_conversion.h" @@ -78,7 +78,7 @@ QString location(QLibraryInfo::LibraryLocation path) switch (path) { case QLibraryInfo::TranslationsPath: if (!webEnginePath.isEmpty()) - return webEnginePath % QDir::separator() % QLatin1String("translations"); + return webEnginePath % QLatin1String("/translations"); break; case QLibraryInfo::DataPath: if (!webEnginePath.isEmpty()) @@ -148,7 +148,7 @@ QString subProcessPath() % QStringLiteral("/Helpers/" QTWEBENGINEPROCESS_NAME ".app/Contents/MacOS/" QTWEBENGINEPROCESS_NAME)); #else static QString processPath (location(QLibraryInfo::LibraryExecutablesPath) - % QDir::separator() % processBinary); + % QLatin1Char('/') % processBinary); #endif if (!initialized) { // Allow overriding at runtime for the time being. @@ -157,7 +157,7 @@ QString subProcessPath() processPath = QString::fromLatin1(fromEnv); if (!QFileInfo(processPath).exists()) { qWarning("QtWebEngineProcess not found at location %s. Trying fallback path...", qPrintable(processPath)); - processPath = QCoreApplication::applicationDirPath() % QDir::separator() % processBinary; + processPath = QCoreApplication::applicationDirPath() % QLatin1Char('/') % processBinary; } if (!QFileInfo(processPath).exists()) qFatal("QtWebEngineProcess not found at location %s. Try setting the QTWEBENGINEPROCESS_PATH environment variable.", qPrintable(processPath)); @@ -172,7 +172,7 @@ QString pluginsPath() #if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD) return getPath(frameworkBundle()) % QLatin1String("/Libraries"); #else - return location(QLibraryInfo::PluginsPath) % QDir::separator() % QLatin1String("qtwebengine"); + return location(QLibraryInfo::PluginsPath) % QLatin1String("/qtwebengine"); #endif } @@ -186,7 +186,7 @@ QString localesPath() } QString fallbackDir() { - static QString directory = QDir::homePath() % QDir::separator() % QChar::fromLatin1('.') % QCoreApplication::applicationName(); + static QString directory = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName(); return directory; } diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 9b070d3b2..0aaa09814 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -38,7 +38,7 @@ #include "web_contents_adapter.h" #include "type_conversion.h" -#include "webkit/common/webpreferences.h" +#include "content/public/common/web_preferences.h" #include <QFont> #include <QTimer> @@ -67,7 +67,6 @@ private: WebEngineSettings *m_settings; }; -#include "web_engine_settings.moc" static inline bool isTouchScreenAvailable() { static bool initialized = false; @@ -85,19 +84,26 @@ static inline bool isTouchScreenAvailable() { } -WebEngineSettings::WebEngineSettings(WebEngineSettingsDelegate *delegate) +WebEngineSettings::WebEngineSettings(WebEngineSettings *_parentSettings) : m_adapter(0) - , m_delegate(delegate) , m_batchTimer(new BatchTimer(this)) + , parentSettings(_parentSettings) { - Q_ASSERT(delegate); + if (parentSettings) + parentSettings->childSettings.insert(this); } WebEngineSettings::~WebEngineSettings() { + if (parentSettings) + parentSettings->childSettings.remove(this); + // In QML the profile and its settings may be garbage collected before the page and its settings. + Q_FOREACH (WebEngineSettings *settings, childSettings) { + settings->parentSettings = 0; + } } -void WebEngineSettings::overrideWebPreferences(WebPreferences *prefs) +void WebEngineSettings::overrideWebPreferences(content::WebPreferences *prefs) { // Apply our settings on top of those. applySettingsToWebPreferences(prefs); @@ -105,100 +111,92 @@ void WebEngineSettings::overrideWebPreferences(WebPreferences *prefs) // as the host process already overides some of the default WebPreferences values // before we get here (e.g. number_of_cpu_cores). if (webPreferences.isNull()) - webPreferences.reset(new WebPreferences(*prefs)); + webPreferences.reset(new content::WebPreferences(*prefs)); } void WebEngineSettings::setAttribute(WebEngineSettings::Attribute attr, bool on) { m_attributes.insert(attr, on); - m_delegate->apply(); + scheduleApplyRecursively(); } bool WebEngineSettings::testAttribute(WebEngineSettings::Attribute attr) const { - WebEngineSettings *fallback = m_delegate->fallbackSettings(); - Q_ASSERT(fallback); - if (this == fallback) { + if (!parentSettings) { Q_ASSERT(m_attributes.contains(attr)); return m_attributes.value(attr); } - return m_attributes.value(attr, fallback->testAttribute(attr)); + return m_attributes.value(attr, parentSettings->testAttribute(attr)); } void WebEngineSettings::resetAttribute(WebEngineSettings::Attribute attr) { - if (this == m_delegate->fallbackSettings()) + if (!parentSettings) // FIXME: Set initial defaults. return; m_attributes.remove(attr); - m_delegate->apply(); + scheduleApplyRecursively(); } void WebEngineSettings::setFontFamily(WebEngineSettings::FontFamily which, const QString &family) { m_fontFamilies.insert(which, family); - m_delegate->apply(); + scheduleApplyRecursively(); } QString WebEngineSettings::fontFamily(WebEngineSettings::FontFamily which) { - WebEngineSettings *fallback = m_delegate->fallbackSettings(); - Q_ASSERT(fallback); - if (this == fallback) { + if (!parentSettings) { Q_ASSERT(m_fontFamilies.contains(which)); return m_fontFamilies.value(which); } - return m_fontFamilies.value(which, fallback->fontFamily(which)); + return m_fontFamilies.value(which, parentSettings->fontFamily(which)); } void WebEngineSettings::resetFontFamily(WebEngineSettings::FontFamily which) { - if (this == m_delegate->fallbackSettings()) + if (!parentSettings) // FIXME: Set initial defaults. return; m_fontFamilies.remove(which); - m_delegate->apply(); + scheduleApplyRecursively(); } void WebEngineSettings::setFontSize(WebEngineSettings::FontSize type, int size) { m_fontSizes.insert(type, size); - m_delegate->apply(); + scheduleApplyRecursively(); } int WebEngineSettings::fontSize(WebEngineSettings::FontSize type) const { - WebEngineSettings *fallback = m_delegate->fallbackSettings(); - Q_ASSERT(fallback); - if (this == fallback) { + if (!parentSettings) { Q_ASSERT(m_fontSizes.contains(type)); return m_fontSizes.value(type); } - return m_fontSizes.value(type, fallback->fontSize(type)); + return m_fontSizes.value(type, parentSettings->fontSize(type)); } void WebEngineSettings::resetFontSize(WebEngineSettings::FontSize type) { - if (this == m_delegate->fallbackSettings()) + if (!parentSettings) // FIXME: Set initial defaults. return; m_fontSizes.remove(type); - m_delegate->apply(); + scheduleApplyRecursively(); } void WebEngineSettings::setDefaultTextEncoding(const QString &encoding) { m_defaultEncoding = encoding; - m_delegate->apply(); + scheduleApplyRecursively(); } QString WebEngineSettings::defaultTextEncoding() const { - WebEngineSettings *fallback = m_delegate->fallbackSettings(); - Q_ASSERT(fallback); - if (this == fallback) + if (!parentSettings) return m_defaultEncoding; - return m_defaultEncoding.isEmpty()? fallback->defaultTextEncoding() : m_defaultEncoding; + return m_defaultEncoding.isEmpty()? parentSettings->defaultTextEncoding() : m_defaultEncoding; } -void WebEngineSettings::initDefaults() +void WebEngineSettings::initDefaults(bool offTheRecord) { // Initialize the default settings. m_attributes.insert(AutoLoadImages, true); @@ -206,7 +204,7 @@ void WebEngineSettings::initDefaults() m_attributes.insert(JavascriptCanOpenWindows, true); m_attributes.insert(JavascriptCanAccessClipboard, false); m_attributes.insert(LinksIncludedInFocusChain, true); - m_attributes.insert(LocalStorageEnabled, true); + m_attributes.insert(LocalStorageEnabled, !offTheRecord); m_attributes.insert(LocalContentCanAccessRemoteUrls, false); m_attributes.insert(XSSAuditingEnabled, false); m_attributes.insert(SpatialNavigationEnabled, false); @@ -258,7 +256,7 @@ void WebEngineSettings::doApply() m_adapter->updateWebPreferences(*webPreferences.data()); } -void WebEngineSettings::applySettingsToWebPreferences(WebPreferences *prefs) +void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *prefs) { // Override for now prefs->java_enabled = false; @@ -280,17 +278,36 @@ void WebEngineSettings::applySettingsToWebPreferences(WebPreferences *prefs) prefs->enable_error_page = testAttribute(ErrorPageEnabled); // Fonts settings. - prefs->standard_font_family_map[webkit_glue::kCommonScript] = toString16(fontFamily(StandardFont)); - prefs->fixed_font_family_map[webkit_glue::kCommonScript] = toString16(fontFamily(FixedFont)); - prefs->serif_font_family_map[webkit_glue::kCommonScript] = toString16(fontFamily(SerifFont)); - prefs->sans_serif_font_family_map[webkit_glue::kCommonScript] = toString16(fontFamily(SansSerifFont)); - prefs->cursive_font_family_map[webkit_glue::kCommonScript] = toString16(fontFamily(CursiveFont)); - prefs->fantasy_font_family_map[webkit_glue::kCommonScript] = toString16(fontFamily(FantasyFont)); + prefs->standard_font_family_map[content::kCommonScript] = toString16(fontFamily(StandardFont)); + prefs->fixed_font_family_map[content::kCommonScript] = toString16(fontFamily(FixedFont)); + prefs->serif_font_family_map[content::kCommonScript] = toString16(fontFamily(SerifFont)); + prefs->sans_serif_font_family_map[content::kCommonScript] = toString16(fontFamily(SansSerifFont)); + prefs->cursive_font_family_map[content::kCommonScript] = toString16(fontFamily(CursiveFont)); + prefs->fantasy_font_family_map[content::kCommonScript] = toString16(fontFamily(FantasyFont)); // FIXME: add pictograph? - // prefs.pictograph_font_family_map[webkit_glue::kCommonScript] = toString16(fontFamily()); + // prefs.pictograph_font_family_map[content::kCommonScript] = toString16(fontFamily()); prefs->default_font_size = fontSize(DefaultFontSize); prefs->default_fixed_font_size = fontSize(DefaultFixedFontSize); prefs->minimum_font_size = fontSize(MinimumFontSize); prefs->minimum_logical_font_size = fontSize(MinimumLogicalFontSize); prefs->default_encoding = defaultTextEncoding().toStdString(); } + +void WebEngineSettings::scheduleApplyRecursively() +{ + scheduleApply(); + Q_FOREACH (WebEngineSettings *settings, childSettings) { + settings->scheduleApply(); + } +} + +void WebEngineSettings::setParentSettings(WebEngineSettings *_parentSettings) +{ + if (parentSettings) + parentSettings->childSettings.remove(this); + parentSettings = _parentSettings; + if (parentSettings) + parentSettings->childSettings.insert(this); +} + +#include "web_engine_settings.moc" diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index c098f8ef4..8ee7d8871 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -43,19 +43,15 @@ #include <QScopedPointer> #include <QHash> #include <QUrl> +#include <QSet> class BatchTimer; class WebContentsAdapter; class WebEngineSettings; -struct WebPreferences; -class QWEBENGINE_EXPORT WebEngineSettingsDelegate { -public: - virtual ~WebEngineSettingsDelegate() {} - virtual void apply() = 0; - // Needs to be a valid pointer, the last available fallback (ex: global settings) should return itself. - virtual WebEngineSettings *fallbackSettings() const = 0; -}; +namespace content { +struct WebPreferences; +} class QWEBENGINE_EXPORT WebEngineSettings { public: @@ -95,10 +91,12 @@ public: DefaultFixedFontSize }; - WebEngineSettings(WebEngineSettingsDelegate*); - virtual ~WebEngineSettings(); + explicit WebEngineSettings(WebEngineSettings *parentSettings = 0); + ~WebEngineSettings(); - void overrideWebPreferences(WebPreferences *prefs); + void setParentSettings(WebEngineSettings *parentSettings); + + void overrideWebPreferences(content::WebPreferences *prefs); void setAttribute(Attribute, bool on); bool testAttribute(Attribute) const; @@ -115,23 +113,27 @@ public: void setDefaultTextEncoding(const QString &encoding); QString defaultTextEncoding() const; - void initDefaults(); + void initDefaults(bool offTheRecord = false); void scheduleApply(); + void scheduleApplyRecursively(); + private: void doApply(); - void applySettingsToWebPreferences(WebPreferences *); + void applySettingsToWebPreferences(content::WebPreferences *); void setWebContentsAdapter(WebContentsAdapter *adapter) { m_adapter = adapter; } WebContentsAdapter* m_adapter; - WebEngineSettingsDelegate* m_delegate; QHash<Attribute, bool> m_attributes; QHash<FontFamily, QString> m_fontFamilies; QHash<FontSize, int> m_fontSizes; QString m_defaultEncoding; - QScopedPointer<WebPreferences> webPreferences; + QScopedPointer<content::WebPreferences> webPreferences; QScopedPointer<BatchTimer> m_batchTimer; + WebEngineSettings *parentSettings; + QSet<WebEngineSettings *> childSettings; + friend class BatchTimer; friend class WebContentsAdapter; }; diff --git a/src/core/web_engine_visited_links_manager.cpp b/src/core/web_engine_visited_links_manager.cpp index 36467ca21..c5ed54f3e 100644 --- a/src/core/web_engine_visited_links_manager.cpp +++ b/src/core/web_engine_visited_links_manager.cpp @@ -36,8 +36,9 @@ #include "web_engine_visited_links_manager.h" -#include "content_browser_client_qt.h" +#include "browser_context_adapter.h" #include "browser_context_qt.h" +#include "content_browser_client_qt.h" #include "type_conversion.h" #include "base/memory/scoped_ptr.h" @@ -80,12 +81,17 @@ void WebEngineVisitedLinksManager::deleteVisitedLinkDataForUrls(const QList<QUrl m_visitedLinkMaster->DeleteURLs(&iterator); } -WebEngineVisitedLinksManager::WebEngineVisitedLinksManager() +bool WebEngineVisitedLinksManager::containsUrl(const QUrl &url) const +{ + return m_visitedLinkMaster->IsVisited(toGurl(url)); +} + +WebEngineVisitedLinksManager::WebEngineVisitedLinksManager(BrowserContextAdapter *adapter) : m_delegate(new VisitedLinkDelegateQt) { - Q_ASSERT(ContentBrowserClientQt::Get() && ContentBrowserClientQt::Get()->browser_context()); - BrowserContextQt *browserContext = ContentBrowserClientQt::Get()->browser_context(); - m_visitedLinkMaster.reset(new visitedlink::VisitedLinkMaster(browserContext, m_delegate.data(), /* persist to disk = */true)); + Q_ASSERT(adapter && adapter->browserContext()); + BrowserContextQt *browserContext = adapter->browserContext(); + m_visitedLinkMaster.reset(new visitedlink::VisitedLinkMaster(browserContext, m_delegate.data(), adapter->persistVisitedLinks())); m_visitedLinkMaster->Init(); } diff --git a/src/core/web_engine_visited_links_manager.h b/src/core/web_engine_visited_links_manager.h index aa44dd9cf..dc2a4bff2 100644 --- a/src/core/web_engine_visited_links_manager.h +++ b/src/core/web_engine_visited_links_manager.h @@ -49,6 +49,7 @@ namespace visitedlink { class VisitedLinkMaster; } +class BrowserContextAdapter; class VisitedLinkDelegateQt; class GURL; @@ -57,11 +58,13 @@ class QWEBENGINE_EXPORT WebEngineVisitedLinksManager { public: virtual~WebEngineVisitedLinksManager(); - WebEngineVisitedLinksManager(); + WebEngineVisitedLinksManager(BrowserContextAdapter*); void deleteAllVisitedLinkData(); void deleteVisitedLinkDataForUrls(const QList<QUrl> &); + bool containsUrl(const QUrl &) const; + private: void addUrl(const GURL &); friend class WebContentsDelegateQt; diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 36e96121c..eacb59011 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -64,6 +64,7 @@ #include "web_event_factory.h" #include "third_party/WebKit/Source/platform/WindowsKeyboardCodes.h" +#include <QCoreApplication> #include <QElapsedTimer> #include <QKeyEvent> #include <QMouseEvent> @@ -131,313 +132,320 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad) return VK_INSERT; // (2D) INS key case Qt::Key_Delete: return VK_DELETE; // (2E) DEL 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 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; + } 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; + } } } @@ -478,14 +486,52 @@ static unsigned mouseButtonsModifiersForEvent(const T* event) return ret; } +// If only a modifier key is pressed, Qt only reports the key code. +// But Chromium also expects the modifier being set. +static inline WebInputEvent::Modifiers modifierForKeyCode(int key) +{ + switch (key) { + case Qt::Key_Shift: + return WebInputEvent::ShiftKey; + case Qt::Key_Alt: + return WebInputEvent::AltKey; +#if defined(Q_OS_OSX) + case Qt::Key_Control: + return (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) ? WebInputEvent::MetaKey : WebInputEvent::ControlKey; + case Qt::Key_Meta: + return (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) ? WebInputEvent::ControlKey : WebInputEvent::MetaKey; +#else + case Qt::Key_Control: + return WebInputEvent::ControlKey; + case Qt::Key_Meta: + return WebInputEvent::MetaKey; +#endif + default: + return static_cast<WebInputEvent::Modifiers>(0); + } +} + static inline WebInputEvent::Modifiers modifiersForEvent(const QInputEvent* event) { unsigned result = 0; Qt::KeyboardModifiers modifiers = event->modifiers(); +#if defined(Q_OS_OSX) + if (!qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + if (modifiers & Qt::ControlModifier) + result |= WebInputEvent::MetaKey; + if (modifiers & Qt::MetaModifier) + result |= WebInputEvent::ControlKey; + } else +#endif + { + if (modifiers & Qt::ControlModifier) + result |= WebInputEvent::ControlKey; + if (modifiers & Qt::MetaModifier) + result |= WebInputEvent::MetaKey; + } + 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) @@ -503,9 +549,12 @@ static inline WebInputEvent::Modifiers modifiersForEvent(const QInputEvent* even result |= mouseButtonsModifiersForEvent(static_cast<const QWheelEvent*>(event)); break; case QEvent::KeyPress: - case QEvent::KeyRelease: - if (static_cast<const QKeyEvent*>(event)->isAutoRepeat()) + case QEvent::KeyRelease: { + const QKeyEvent *keyEvent = static_cast<const QKeyEvent*>(event); + if (keyEvent->isAutoRepeat()) result |= WebInputEvent::IsAutoRepeat; + result |= modifierForKeyCode(keyEvent->key()); + } default: break; } @@ -612,7 +661,7 @@ blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, doub content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev) { - content::NativeWebKeyboardEvent webKitEvent; + content::NativeWebKeyboardEvent webKitEvent(reinterpret_cast<gfx::NativeEvent>(ev)); webKitEvent.timeStampSeconds = currentTimeForEvent(ev); webKitEvent.modifiers = modifiersForEvent(ev); webKitEvent.type = webEventTypeForEvent(ev); diff --git a/src/webengine/api/qquickwebenginecertificateerror.cpp b/src/webengine/api/qquickwebenginecertificateerror.cpp new file mode 100644 index 000000000..37b92727a --- /dev/null +++ b/src/webengine/api/qquickwebenginecertificateerror.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qquickwebenginecertificateerror_p.h> +#include "certificate_error_controller.h" +QT_BEGIN_NAMESPACE + +class QQuickWebEngineCertificateErrorPrivate { +public: + QQuickWebEngineCertificateErrorPrivate(const QSharedPointer<CertificateErrorController> &controller) + : weakRefCertErrorController(controller), + error(static_cast<QQuickWebEngineCertificateError::Error>(static_cast<int>(controller->error()))), + description(controller->errorString()), + overridable(controller->overridable()), + async(false) + { + } + + const QWeakPointer<CertificateErrorController> weakRefCertErrorController; + QQuickWebEngineCertificateError::Error error; + QString description; + bool overridable; + bool async; +}; + + + +/*! + \qmltype WebEngineCertificateError + \instantiates QQuickWebEngineCertificateError + \inqmlmodule QtWebEngine 1.1 + \since QtWebEngine 1.1 + + \brief A utility class for accepting or denying certificate exceptions when a certificate error occurs. + + This class contains information about a certificate error that happened and provides a way to accept or + deny a certificate exception. + + \sa WebEngineView::certificateError +*/ +QQuickWebEngineCertificateError::QQuickWebEngineCertificateError(const QSharedPointer<CertificateErrorController> &controller, QObject *parent) + : QObject(parent) + , d_ptr(new QQuickWebEngineCertificateErrorPrivate(controller)) +{ +} + +QQuickWebEngineCertificateError::~QQuickWebEngineCertificateError() +{ + rejectCertificate(); +} + + +/*! + \qmlmethod void WebEngineCertificateError::defer() + + This function should be called when there is a need to postpone the decision to ignore or not the certificate error. This is useful to + wait for user input. When called it will pause the url request until WebEngineCertificateError::ignoreCertificateError() or + WebEngineCertificateError::rejectCertificate() is called. + */ +void QQuickWebEngineCertificateError::defer() +{ + Q_D(QQuickWebEngineCertificateError); + d->async = true; +} +/*! + \qmlmethod void WebEngineCertificateError::ignoreCertificateError() + + The certificate error is ignored and the WebEngineView continues to load the requested url. + */ +void QQuickWebEngineCertificateError::ignoreCertificateError() +{ + Q_D(const QQuickWebEngineCertificateError); + + QSharedPointer<CertificateErrorController> strongRefCert = d->weakRefCertErrorController.toStrongRef(); + if (strongRefCert) + strongRefCert->accept(true); +} + +/*! + \qmlmethod void WebEngineCertificateError::rejectCertificate() + + The WebEngineView stops loading the requested url. + */ +void QQuickWebEngineCertificateError::rejectCertificate() +{ + Q_D(const QQuickWebEngineCertificateError); + + QSharedPointer<CertificateErrorController> strongRefCert = d->weakRefCertErrorController.toStrongRef(); + if (strongRefCert) + strongRefCert->accept(false); +} + +/*! + \qmlproperty url WebEngineCertificateError::url + \brief The URL of the certificate error. + */ +QUrl QQuickWebEngineCertificateError::url() const +{ + Q_D(const QQuickWebEngineCertificateError); + QSharedPointer<CertificateErrorController> strongRefCert = d->weakRefCertErrorController.toStrongRef(); + if (strongRefCert) + return strongRefCert->url(); + return QUrl(); +} + +/*! + \qmlproperty enumeration WebEngineCertificateError::error +*/ +QQuickWebEngineCertificateError::Error QQuickWebEngineCertificateError::error() const +{ + Q_D(const QQuickWebEngineCertificateError); + return d->error; +} + +/*! + \qmlproperty string WebEngineCertificateError::description +*/ +QString QQuickWebEngineCertificateError::description() const +{ + Q_D(const QQuickWebEngineCertificateError); + return d->description; +} + +/*! + \qmlproperty bool WebEngineCertificateError::overridable +*/ +bool QQuickWebEngineCertificateError::overridable() const +{ + Q_D(const QQuickWebEngineCertificateError); + return d->overridable; +} + +bool QQuickWebEngineCertificateError::deferred() const +{ + Q_D(const QQuickWebEngineCertificateError); + return d->async; +} + +QT_END_NAMESPACE + diff --git a/src/webengine/api/qquickwebenginecertificateerror_p.h b/src/webengine/api/qquickwebenginecertificateerror_p.h new file mode 100644 index 000000000..735cc8705 --- /dev/null +++ b/src/webengine/api/qquickwebenginecertificateerror_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWEBENGINECERTIFICATEERROR_P_H +#define QQUICKWEBENGINECERTIFICATEERROR_P_H + +#include <QObject> +#include "qquickwebengineview_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineCertificateErrorPrivate; +class CertificateErrorController; + +class Q_WEBENGINE_EXPORT QQuickWebEngineCertificateError : public QObject { + Q_OBJECT + Q_PROPERTY(QUrl url READ url) + Q_PROPERTY(Error error READ error) + Q_PROPERTY(QString description READ description) + Q_PROPERTY(bool overridable READ overridable) + Q_ENUMS(Error) + +public: + + // Keep this identical to CertificateErrorController::CertificateError, or add mapping layer. + enum Error { + SslPinnedKeyNotInCertificateChain = -150, + CertificateCommonNameInvalid = -200, + CertificateDateInvalid = -201, + CertificateAuthorityInvalid = -202, + CertificateContainsErrors = -203, + CertificateNoRevocationMechanism = -204, + CertificateUnableToCheckRevocation = -205, + CertificateRevoked = -206, + CertificateInvalid = -207, + CertificateWeakSignatureAlgorithm = -208, + CertificateNonUniqueName = -210, + CertificateWeakKey = -211, + CertificateNameConstraintViolation = -212, + }; + + QQuickWebEngineCertificateError(const QSharedPointer<CertificateErrorController> &controller, QObject *parent = 0); + ~QQuickWebEngineCertificateError(); + + Q_INVOKABLE void defer(); + Q_INVOKABLE void ignoreCertificateError(); + Q_INVOKABLE void rejectCertificate(); + QUrl url() const; + Error error() const; + QString description() const; + bool overridable() const; + bool deferred() const; + +private: + Q_DISABLE_COPY(QQuickWebEngineCertificateError) + Q_DECLARE_PRIVATE(QQuickWebEngineCertificateError) + QScopedPointer<QQuickWebEngineCertificateErrorPrivate> d_ptr; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickWebEngineCertificateError) + +#endif // QQUICKWEBENGINECERTIFICATEERROR_P_H diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp new file mode 100644 index 000000000..6ee00d9a0 --- /dev/null +++ b/src/webengine/api/qquickwebenginedownloaditem.cpp @@ -0,0 +1,272 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickwebenginedownloaditem_p.h" +#include "qquickwebenginedownloaditem_p_p.h" + +QT_BEGIN_NAMESPACE + +static inline QQuickWebEngineDownloadItem::DownloadState toDownloadState(int state) { + switch (state) { + case BrowserContextAdapterClient::DownloadInProgress: + return QQuickWebEngineDownloadItem::DownloadInProgress; + case BrowserContextAdapterClient::DownloadCompleted: + return QQuickWebEngineDownloadItem::DownloadCompleted; + case BrowserContextAdapterClient::DownloadCancelled: + return QQuickWebEngineDownloadItem::DownloadCancelled; + case BrowserContextAdapterClient::DownloadInterrupted: + return QQuickWebEngineDownloadItem::DownloadInterrupted; + default: + Q_UNREACHABLE(); + return QQuickWebEngineDownloadItem::DownloadCancelled; + } +} + +QQuickWebEngineDownloadItemPrivate::QQuickWebEngineDownloadItemPrivate(QQuickWebEngineProfilePrivate *p) + : profile(p) + , downloadId(-1) + , downloadState(QQuickWebEngineDownloadItem::DownloadCancelled) +{ +} + +QQuickWebEngineDownloadItemPrivate::~QQuickWebEngineDownloadItemPrivate() +{ + profile->downloadDestroyed(downloadId); +} + +/*! + \qmltype WebEngineDownloadItem + \instantiates QQuickWebEngineDownloadItem + \inqmlmodule QtWebEngine 1.1 + \since QtWebEngine 1.1 + \brief A WebEngineDownloadItem provides information about a download. + + WebEngineDownloadItem stores the state of a download to be used to manage requested downloads. + + By default the download is rejected unless the user explicitly accepts it with + WebEngineDownloadItem::accept(). +*/ + +void QQuickWebEngineDownloadItemPrivate::update(const BrowserContextAdapterClient::DownloadItemInfo &info) +{ + Q_Q(QQuickWebEngineDownloadItem); + + updateState(toDownloadState(info.state)); + + if (info.receivedBytes != receivedBytes) { + receivedBytes = info.receivedBytes; + Q_EMIT q->receivedBytesChanged(); + } + + if (info.totalBytes != totalBytes) { + totalBytes = info.totalBytes; + Q_EMIT q->totalBytesChanged(); + } +} + +void QQuickWebEngineDownloadItemPrivate::updateState(QQuickWebEngineDownloadItem::DownloadState newState) +{ + Q_Q(QQuickWebEngineDownloadItem); + + if (downloadState != newState) { + downloadState = newState; + Q_EMIT q->stateChanged(); + } +} + +/*! + \qmlmethod void WebEngineDownloadItem::accept() + + Accepts the download request, which will start the download. + + \sa WebEngineDownloadItem::cancel() +*/ + +void QQuickWebEngineDownloadItem::accept() +{ + Q_D(QQuickWebEngineDownloadItem); + + if (d->downloadState != QQuickWebEngineDownloadItem::DownloadRequested) + return; + + d->updateState(QQuickWebEngineDownloadItem::DownloadInProgress); +} + +/*! + \qmlmethod void WebEngineDownloadItem::cancel() + + Cancels the download. +*/ + +void QQuickWebEngineDownloadItem::cancel() +{ + Q_D(QQuickWebEngineDownloadItem); + + QQuickWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (state == QQuickWebEngineDownloadItem::DownloadCompleted + || state == QQuickWebEngineDownloadItem::DownloadCancelled) + return; + + d->updateState(QQuickWebEngineDownloadItem::DownloadCancelled); + + // We directly cancel the download if the user cancels before + // it even started, so no need to notify the profile here. + if (state == QQuickWebEngineDownloadItem::DownloadInProgress) + d->profile->cancelDownload(d->downloadId); +} + +/*! + \qmlproperty quint32 WebEngineDownloadItem::id + + The download item's id. +*/ + +quint32 QQuickWebEngineDownloadItem::id() const +{ + Q_D(const QQuickWebEngineDownloadItem); + return d->downloadId; +} + +/*! + \qmlproperty enumeration WebEngineDownloadItem::state + + This property describes the state in which the download is in. + + The state can be one of: + + \table + + \header + \li Constant + \li Description + + \row + \li DownloadRequested + \li The download has been requested, but has not been accepted yet. + + \row + \li DownloadInProgress + \li The download is in progress. + + \row + \li DownloadCompleted + \li The download completed successfully. + + \row + \li DownloadInterrupted + \li The download has been interrupted (by the server or because of lost connectivity). + + \endtable +*/ + +QQuickWebEngineDownloadItem::DownloadState QQuickWebEngineDownloadItem::state() const +{ + Q_D(const QQuickWebEngineDownloadItem); + return d->downloadState; +} + +/*! + \qmlproperty int WebEngineDownloadItem::totalBytes + + The download's total size in bytes. + + -1 means the total size is unknown. +*/ + +qint64 QQuickWebEngineDownloadItem::totalBytes() const +{ + Q_D(const QQuickWebEngineDownloadItem); + return d->totalBytes; +} + +/*! + \qmlproperty int WebEngineDownloadItem::receivedBytes + + The download's bytes that have been received so far. +*/ + +qint64 QQuickWebEngineDownloadItem::receivedBytes() const +{ + Q_D(const QQuickWebEngineDownloadItem); + return d->receivedBytes; +} + +/*! + \qmlproperty QString WebEngineDownloadItem::path + + The download item's full target path where it is being downloaded to. + + The path includes the file name. The default suggested path is the standard + download location and file name is deduced not to overwrite already existing files. + + The download path can only be set in the \c WebEngineProfile.onDownloadRequested + handler before the download is accepted. + + \sa WebEngineProfile::downloadRequested(WebEngineDownloadItem download), WebEngineDownloadItem::accept() +*/ + +QString QQuickWebEngineDownloadItem::path() const +{ + Q_D(const QQuickWebEngineDownloadItem); + return d->downloadPath; +} + +void QQuickWebEngineDownloadItem::setPath(QString path) +{ + Q_D(QQuickWebEngineDownloadItem); + if (d->downloadState != QQuickWebEngineDownloadItem::DownloadRequested) { + qWarning("Setting the download path is not allowed after the download has been accepted."); + return; + } + if (d->downloadPath != path) { + d->downloadPath = path; + Q_EMIT pathChanged(); + } +} + +QQuickWebEngineDownloadItem::QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate *p, QObject *parent) + : QObject(parent) + , d_ptr(p) +{ + p->q_ptr = this; +} + +QQuickWebEngineDownloadItem::~QQuickWebEngineDownloadItem() +{ +} + +QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebenginedownloaditem_p.h b/src/webengine/api/qquickwebenginedownloaditem_p.h new file mode 100644 index 000000000..ea12c9c94 --- /dev/null +++ b/src/webengine/api/qquickwebenginedownloaditem_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWEBENGINEDOWNLOADITEM_P_H +#define QQUICKWEBENGINEDOWNLOADITEM_P_H + +#include <private/qtwebengineglobal_p.h> +#include <QObject> +#include <QScopedPointer> +#include <QString> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineDownloadItemPrivate; +class QQuickWebEngineProfilePrivate; + +class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineDownloadItem: public QObject { + Q_OBJECT +public: + ~QQuickWebEngineDownloadItem(); + enum DownloadState { + DownloadRequested, + DownloadInProgress, + DownloadCompleted, + DownloadCancelled, + DownloadInterrupted + }; + Q_ENUMS(DownloadState) + + Q_PROPERTY(quint32 id READ id() CONSTANT FINAL) + Q_PROPERTY(DownloadState state READ state NOTIFY stateChanged) + Q_PROPERTY(qint64 totalBytes READ totalBytes NOTIFY totalBytesChanged) + Q_PROPERTY(qint64 receivedBytes READ receivedBytes NOTIFY receivedBytesChanged) + Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) + + Q_INVOKABLE void accept(); + Q_INVOKABLE void cancel(); + + quint32 id() const; + DownloadState state() const; + qint64 totalBytes() const; + qint64 receivedBytes() const; + QString path() const; + void setPath(QString path); + +Q_SIGNALS: + void stateChanged(); + void receivedBytesChanged(); + void totalBytesChanged(); + void pathChanged(); + +private: + QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate*, QObject *parent = 0); + Q_DISABLE_COPY(QQuickWebEngineDownloadItem) + Q_DECLARE_PRIVATE(QQuickWebEngineDownloadItem) + friend class QQuickWebEngineProfilePrivate; + + QScopedPointer<QQuickWebEngineDownloadItemPrivate> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEDOWNLOADITEM_P_H diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h new file mode 100644 index 000000000..0250a8faa --- /dev/null +++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWEBENGINEDOWNLOADITEM_P_P_H +#define QQUICKWEBENGINEDOWNLOADITEM_P_P_H + +#include "qquickwebenginedownloaditem_p.h" +#include "qquickwebengineprofile_p_p.h" +#include <private/qtwebengineglobal_p.h> +#include <QString> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineDownloadItemPrivate { + QQuickWebEngineDownloadItem *q_ptr; + QQuickWebEngineProfilePrivate* profile; + friend class QQuickWebEngineProfilePrivate; +public: + Q_DECLARE_PUBLIC(QQuickWebEngineDownloadItem) + QQuickWebEngineDownloadItemPrivate(QQuickWebEngineProfilePrivate *p); + ~QQuickWebEngineDownloadItemPrivate(); + + quint32 downloadId; + QQuickWebEngineDownloadItem::DownloadState downloadState; + qint64 totalBytes; + qint64 receivedBytes; + QString downloadPath; + + void update(const BrowserContextAdapterClient::DownloadItemInfo &info); + void updateState(QQuickWebEngineDownloadItem::DownloadState newState); +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEDOWNLOADITEM_P_P_H diff --git a/src/webengine/api/qquickwebenginehistory.cpp b/src/webengine/api/qquickwebenginehistory.cpp index ffb857791..7924dbc5e 100644 --- a/src/webengine/api/qquickwebenginehistory.cpp +++ b/src/webengine/api/qquickwebenginehistory.cpp @@ -63,6 +63,8 @@ QQuickWebEngineBackHistoryListModelPrivate::QQuickWebEngineBackHistoryListModelP int QQuickWebEngineBackHistoryListModelPrivate::count() const { + if (!adapter()) + return -1; return adapter()->currentNavigationEntryIndex(); } @@ -79,6 +81,8 @@ QQuickWebEngineForwardHistoryListModelPrivate::QQuickWebEngineForwardHistoryList int QQuickWebEngineForwardHistoryListModelPrivate::count() const { + if (!adapter()) + return -1; return adapter()->navigationEntryCount() - adapter()->currentNavigationEntryIndex() - 1; } diff --git a/src/webengine/api/qquickwebenginenewviewrequest.cpp b/src/webengine/api/qquickwebenginenewviewrequest.cpp index f2a361f55..053fcd2f6 100644 --- a/src/webengine/api/qquickwebenginenewviewrequest.cpp +++ b/src/webengine/api/qquickwebenginenewviewrequest.cpp @@ -39,6 +39,18 @@ #include "qquickwebengineview_p_p.h" #include "web_contents_adapter.h" +/*! + \qmltype WebEngineNewViewRequest + \instantiates QQuickWebEngineNewViewRequest + \inqmlmodule QtWebEngine 1.1 + \since QtWebEngine 1.1 + + \brief A utility class for the WebEngineView::newViewRequested signal. + + This class contains information about the request of a page to open a new window. + + \sa WebEngineView::newViewRequested +*/ QQuickWebEngineNewViewRequest::QQuickWebEngineNewViewRequest() { } @@ -47,20 +59,48 @@ QQuickWebEngineNewViewRequest::~QQuickWebEngineNewViewRequest() { } +/*! + \qmlproperty WebEngineView::NewViewDestination WebEngineNewViewRequest::destination + \brief The type of view that is requested by the page. + */ QQuickWebEngineView::NewViewDestination QQuickWebEngineNewViewRequest::destination() const { return m_destination; } +/*! + \qmlproperty bool WebEngineNewViewRequest::isUserInitiated + \brief Whether this window request was directly triggered as the result of a keyboard or mouse event. + + Use this property to block possibly unwanted "popups". + */ bool QQuickWebEngineNewViewRequest::isUserInitiated() const { return m_isUserInitiated; } +/*! + \qmlmethod WebEngineNewViewRequest::openIn(WebEngineView view) + + Call this method to fulfill the request and determine which WebEngineView + should be used to contain the new page. Any state, history or loaded page + within \a view will be lost as result of this. + + \sa WebEngineView::newViewRequested + */ void QQuickWebEngineNewViewRequest::openIn(QQuickWebEngineView *view) { - if (view) { - view->d_func()->adoptWebContents(m_adapter.data()); - m_adapter.reset(); + if (!m_adapter) { + qWarning("Trying to open an empty request, it was either already used or was invalidated." + "\nYou must complete the request synchronously within the newViewRequested signal handler." + " If a view hasn't been adopted before returning, the request will be invalidated."); + return; + } + + if (!view) { + qWarning("Trying to open a WebEngineNewViewRequest in an invalid WebEngineView."); + return; } + view->d_func()->adoptWebContents(m_adapter.data()); + m_adapter.reset(); } diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp new file mode 100644 index 000000000..5905fb3d9 --- /dev/null +++ b/src/webengine/api/qquickwebengineprofile.cpp @@ -0,0 +1,410 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickwebengineprofile_p.h" + +#include "qquickwebenginedownloaditem_p.h" +#include "qquickwebenginedownloaditem_p_p.h" +#include "qquickwebengineprofile_p_p.h" +#include "qquickwebenginesettings_p.h" + +#include <QQmlEngine> + +#include "browser_context_adapter.h" +#include "web_engine_settings.h" + +QT_BEGIN_NAMESPACE + +QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(BrowserContextAdapter* browserContext, bool ownsContext) + : m_settings(new QQuickWebEngineSettings()) + , m_browserContext(browserContext) +{ + if (ownsContext) + m_browserContextRef = browserContext; + + m_browserContext->setClient(this); + m_settings->d_ptr->initDefaults(browserContext->isOffTheRecord()); +} + +QQuickWebEngineProfilePrivate::~QQuickWebEngineProfilePrivate() +{ + m_browserContext->setClient(0); + + Q_FOREACH (QQuickWebEngineDownloadItem* download, m_ongoingDownloads) { + if (download) + download->cancel(); + } + + m_ongoingDownloads.clear(); +} + +void QQuickWebEngineProfilePrivate::cancelDownload(quint32 downloadId) +{ + m_browserContext->cancelDownload(downloadId); +} + +void QQuickWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId) +{ + m_ongoingDownloads.remove(downloadId); +} + +void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) +{ + Q_Q(QQuickWebEngineProfile); + + Q_ASSERT(!m_ongoingDownloads.contains(info.id)); + QQuickWebEngineDownloadItemPrivate *itemPrivate = new QQuickWebEngineDownloadItemPrivate(this); + itemPrivate->downloadId = info.id; + itemPrivate->downloadState = QQuickWebEngineDownloadItem::DownloadRequested; + itemPrivate->downloadPath = info.path; + + QQuickWebEngineDownloadItem *download = new QQuickWebEngineDownloadItem(itemPrivate, q); + + m_ongoingDownloads.insert(info.id, download); + + QQmlEngine::setObjectOwnership(download, QQmlEngine::JavaScriptOwnership); + Q_EMIT q->downloadRequested(download); + + QQuickWebEngineDownloadItem::DownloadState state = download->state(); + info.path = download->path(); + info.accepted = state != QQuickWebEngineDownloadItem::DownloadCancelled + && state != QQuickWebEngineDownloadItem::DownloadRequested; +} + +void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info) +{ + if (!m_ongoingDownloads.contains(info.id)) + return; + + Q_Q(QQuickWebEngineProfile); + + QQuickWebEngineDownloadItem* download = m_ongoingDownloads.value(info.id).data(); + + if (!download) { + downloadDestroyed(info.id); + return; + } + + download->d_func()->update(info); + + if (info.state != BrowserContextAdapterClient::DownloadInProgress) { + Q_EMIT q->downloadFinished(download); + m_ongoingDownloads.remove(info.id); + } +} + +/*! + \qmltype WebEngineProfile + \instantiates QQuickWebEngineProfile + \inqmlmodule QtWebEngine 1.1 + \since QtWebEngine 1.1 + \brief A WebEngineProfile contains common settings for multiple WebEngineView. + + WebEngineProfile contains settings and history shared by all WebEngineView that belong + to the profile. + + A default profile is built-in that all web pages not specifically created with another profile + belongs to. +*/ + +/*! + \qmlsignal WebEngineProfile::downloadRequested(WebEngineDownloadItem download) + + This signal is emitted whenever a download has been triggered. + The \a download argument holds the state of the download. + The \a download has to be explicitly accepted with WebEngineDownloadItem::accept(), + else the download will be cancelled by default. +*/ + +/*! + \qmlsignal WebEngineProfile::downloadFinished(WebEngineDownloadItem download) + + This signal is emitted whenever a download finishes downloading. + This can be due to the download finishing successfully, being cancelled or + interrupted by lost connectivity for example. + The \a download argument holds the state of the finished download instance. +*/ + +QQuickWebEngineProfile::QQuickWebEngineProfile() + : d_ptr(new QQuickWebEngineProfilePrivate(new BrowserContextAdapter(false), true)) +{ + d_ptr->q_ptr = this; +} + +QQuickWebEngineProfile::QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *privatePtr) + : d_ptr(privatePtr) +{ + d_ptr->q_ptr = this; +} + +QQuickWebEngineProfile::~QQuickWebEngineProfile() +{ +} + +/*! + \qmlproperty QString WebEngineProfile::storageName + + The storage name is used to give each profile that uses the disk separate subdirectories for persistent data and cache. +*/ + +QString QQuickWebEngineProfile::storageName() const +{ + const Q_D(QQuickWebEngineProfile); + return d->browserContext()->storageName(); +} + +void QQuickWebEngineProfile::setStorageName(const QString &name) +{ + Q_D(QQuickWebEngineProfile); + if (d->browserContext()->storageName() == name) + return; + BrowserContextAdapter::HttpCacheType oldCacheType = d->browserContext()->httpCacheType(); + BrowserContextAdapter::PersistentCookiesPolicy oldPolicy = d->browserContext()->persistentCookiesPolicy(); + d->browserContext()->setStorageName(name); + emit storageNameChanged(); + emit persistentStoragePathChanged(); + emit cachePathChanged(); + if (d->browserContext()->httpCacheType() != oldCacheType) + emit httpCacheTypeChanged(); + if (d->browserContext()->persistentCookiesPolicy() != oldPolicy) + emit persistentCookiesPolicyChanged(); +} + +/*! + \qmlproperty bool WebEngineProfile::offTheRecord + + An offTheRecord profile forces cookies and HTTP cache to be in memory, but also force + all other normally persistent data to be stored in memory. +*/ +bool QQuickWebEngineProfile::isOffTheRecord() const +{ + const Q_D(QQuickWebEngineProfile); + return d->browserContext()->isOffTheRecord(); +} + +void QQuickWebEngineProfile::setOffTheRecord(bool offTheRecord) +{ + Q_D(QQuickWebEngineProfile); + if (d->browserContext()->isOffTheRecord() == offTheRecord) + return; + BrowserContextAdapter::HttpCacheType oldCacheType = d->browserContext()->httpCacheType(); + BrowserContextAdapter::PersistentCookiesPolicy oldPolicy = d->browserContext()->persistentCookiesPolicy(); + d->browserContext()->setOffTheRecord(offTheRecord); + emit offTheRecordChanged(); + if (d->browserContext()->httpCacheType() != oldCacheType) + emit httpCacheTypeChanged(); + if (d->browserContext()->persistentCookiesPolicy() != oldPolicy) + emit persistentCookiesPolicyChanged(); +} + +/*! + \qmlproperty QString WebEngineProfile::persistentStoragePath + + The persistent storage path is where persistent data for the browser and web content is stored. + Persistent data includes persistent cookies, HTML5 local storage and visited links. + + By default this is below QStandardPaths::writableLocation(QStandardPaths::DataLocation) in a storageName specific directory. +*/ +QString QQuickWebEngineProfile::persistentStoragePath() const +{ + const Q_D(QQuickWebEngineProfile); + return d->browserContext()->dataPath(); +} + +void QQuickWebEngineProfile::setPersistentStoragePath(const QString &path) +{ + Q_D(QQuickWebEngineProfile); + if (persistentStoragePath() == path) + return; + d->browserContext()->setDataPath(path); + emit persistentStoragePathChanged(); +} + +/*! + \qmlproperty QString WebEngineProfile::cachePath + + By default this is below QStandardPaths::writableLocation(QStandardPaths::CacheLocation) in a storageName specific directory. +*/ +QString QQuickWebEngineProfile::cachePath() const +{ + const Q_D(QQuickWebEngineProfile); + return d->browserContext()->cachePath(); +} + +void QQuickWebEngineProfile::setCachePath(const QString &path) +{ + Q_D(QQuickWebEngineProfile); + if (cachePath() == path) + return; + d->browserContext()->setCachePath(path); + emit cachePathChanged(); +} + +/*! + \qmlproperty QString WebEngineProfile::httpUserAgent + + The user-agent string send with HTTP to identify the browser. +*/ +QString QQuickWebEngineProfile::httpUserAgent() const +{ + const Q_D(QQuickWebEngineProfile); + return d->browserContext()->httpUserAgent(); +} + +void QQuickWebEngineProfile::setHttpUserAgent(const QString &userAgent) +{ + Q_D(QQuickWebEngineProfile); + if (d->browserContext()->httpUserAgent() == userAgent) + return; + d->browserContext()->setHttpUserAgent(userAgent); + emit httpUserAgentChanged(); +} + + +/*! + \qmlproperty enumeration WebEngineProfile::httpCacheType + + The type of the HTTP cache. + + \table + + \header + \li Constant + \li Description + + \row + \li MemoryHttpCache + \li Use a in-memory cache. This is the only setting possible if offTheRecord is set or no cachePath is available. + + \row + \li DiskHttpCache + \li DiskHttpCache Use a disk cache. This is the default. + + \endtable +*/ + +QQuickWebEngineProfile::HttpCacheType QQuickWebEngineProfile::httpCacheType() const +{ + const Q_D(QQuickWebEngineProfile); + return QQuickWebEngineProfile::HttpCacheType(d->browserContext()->httpCacheType()); +} + +void QQuickWebEngineProfile::setHttpCacheType(QQuickWebEngineProfile::HttpCacheType httpCacheType) +{ + Q_D(QQuickWebEngineProfile); + BrowserContextAdapter::HttpCacheType oldCacheType = d->browserContext()->httpCacheType(); + d->browserContext()->setHttpCacheType(BrowserContextAdapter::HttpCacheType(httpCacheType)); + if (d->browserContext()->httpCacheType() != oldCacheType) + emit httpCacheTypeChanged(); +} + +/*! + \qmlproperty enumeration WebEngineProfile::persistentCookiesPolicy + + The policy of cookie persistency. + + \table + + \header + \li Constant + \li Description + + \row + \li NoPersistentCookies + \li Both session and persistent cookies are stored in memory. This is the only setting possible if offTheRecord is set or no persistentStoragePath is available. + + \row + \li AllowPersistentCookies + \li Cookies marked persistent are save and restored from disk, session cookies are only stored to disk for crash recovery. This is the default setting. + + \row + \li ForcePersistentCookies + \li Both session and persistent cookies are save and restored from disk. + + \endtable +*/ + +QQuickWebEngineProfile::PersistentCookiesPolicy QQuickWebEngineProfile::persistentCookiesPolicy() const +{ + const Q_D(QQuickWebEngineProfile); + return QQuickWebEngineProfile::PersistentCookiesPolicy(d->browserContext()->persistentCookiesPolicy()); +} + +void QQuickWebEngineProfile::setPersistentCookiesPolicy(QQuickWebEngineProfile::PersistentCookiesPolicy newPersistentCookiesPolicy) +{ + Q_D(QQuickWebEngineProfile); + BrowserContextAdapter::PersistentCookiesPolicy oldPolicy = d->browserContext()->persistentCookiesPolicy(); + d->browserContext()->setPersistentCookiesPolicy(BrowserContextAdapter::PersistentCookiesPolicy(newPersistentCookiesPolicy)); + if (d->browserContext()->persistentCookiesPolicy() != oldPolicy) + emit persistentCookiesPolicyChanged(); +} + +/*! + \qmlproperty int WebEngineProfile::httpCacheMaximumSize + + The maximum size of the HTTP cache. If 0 it means the size will be controlled automatically by QtWebEngine. + The default value is 0. + + \sa httpCacheType +*/ +int QQuickWebEngineProfile::httpCacheMaximumSize() const +{ + const Q_D(QQuickWebEngineProfile); + return d->browserContext()->httpCacheMaxSize(); +} + +void QQuickWebEngineProfile::setHttpCacheMaximumSize(int maximumSize) +{ + Q_D(QQuickWebEngineProfile); + if (d->browserContext()->httpCacheMaxSize() == maximumSize) + return; + d->browserContext()->setHttpCacheMaxSize(maximumSize); + emit httpCacheMaximumSizeChanged(); +} + +QQuickWebEngineProfile *QQuickWebEngineProfile::defaultProfile() +{ + static QQuickWebEngineProfile profile(new QQuickWebEngineProfilePrivate(BrowserContextAdapter::defaultContext(), false)); + return &profile; +} + +QQuickWebEngineSettings *QQuickWebEngineProfile::settings() const +{ + const Q_D(QQuickWebEngineProfile); + return d->settings(); +} + +QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h new file mode 100644 index 000000000..f3e0f5c33 --- /dev/null +++ b/src/webengine/api/qquickwebengineprofile_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWEBENGINEPROFILE_P_H +#define QQUICKWEBENGINEPROFILE_P_H + +#include <private/qtwebengineglobal_p.h> + +#include <QObject> +#include <QScopedPointer> +#include <QString> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineDownloadItem; +class QQuickWebEngineProfilePrivate; +class QQuickWebEngineSettings; + +class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineProfile : public QObject { + Q_OBJECT + Q_ENUMS(HttpCacheType); + Q_ENUMS(PersistentCookiesPolicy); + Q_PROPERTY(QString storageName READ storageName WRITE setStorageName NOTIFY storageNameChanged FINAL) + Q_PROPERTY(bool offTheRecord READ isOffTheRecord WRITE setOffTheRecord NOTIFY offTheRecordChanged FINAL) + Q_PROPERTY(QString persistentStoragePath READ persistentStoragePath WRITE setPersistentStoragePath NOTIFY persistentStoragePathChanged FINAL) + Q_PROPERTY(QString cachePath READ cachePath WRITE setCachePath NOTIFY cachePathChanged FINAL) + Q_PROPERTY(QString httpUserAgent READ httpUserAgent WRITE setHttpUserAgent NOTIFY httpUserAgentChanged FINAL) + Q_PROPERTY(HttpCacheType httpCacheType READ httpCacheType WRITE setHttpCacheType NOTIFY httpCacheTypeChanged FINAL) + Q_PROPERTY(PersistentCookiesPolicy persistentCookiesPolicy READ persistentCookiesPolicy WRITE setPersistentCookiesPolicy NOTIFY persistentCookiesPolicyChanged FINAL) + Q_PROPERTY(int httpCacheMaximumSize READ httpCacheMaximumSize WRITE setHttpCacheMaximumSize NOTIFY httpCacheMaximumSizeChanged FINAL) +public: + QQuickWebEngineProfile(); + ~QQuickWebEngineProfile(); + + enum HttpCacheType { + MemoryHttpCache, + DiskHttpCache + }; + + enum PersistentCookiesPolicy { + NoPersistentCookies, + AllowPersistentCookies, + ForcePersistentCookies + }; + + QString storageName() const; + void setStorageName(const QString &name); + + bool isOffTheRecord() const; + void setOffTheRecord(bool offTheRecord); + + QString persistentStoragePath() const; + void setPersistentStoragePath(const QString &path); + + QString cachePath() const; + void setCachePath(const QString &path); + + QString httpUserAgent() const; + void setHttpUserAgent(const QString &userAgent); + + HttpCacheType httpCacheType() const; + void setHttpCacheType(QQuickWebEngineProfile::HttpCacheType); + + PersistentCookiesPolicy persistentCookiesPolicy() const; + void setPersistentCookiesPolicy(QQuickWebEngineProfile::PersistentCookiesPolicy); + + int httpCacheMaximumSize() const; + void setHttpCacheMaximumSize(int maxSize); + + static QQuickWebEngineProfile *defaultProfile(); + +signals: + void storageNameChanged(); + void offTheRecordChanged(); + void persistentStoragePathChanged(); + void cachePathChanged(); + void httpUserAgentChanged(); + void httpCacheTypeChanged(); + void persistentCookiesPolicyChanged(); + void httpCacheMaximumSizeChanged(); + + void downloadRequested(QQuickWebEngineDownloadItem *download); + void downloadFinished(QQuickWebEngineDownloadItem *download); + +private: + Q_DECLARE_PRIVATE(QQuickWebEngineProfile) + QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *); + QQuickWebEngineSettings *settings() const; + + friend class QQuickWebEngineSettings; + friend class QQuickWebEngineSingleton; + friend class QQuickWebEngineViewPrivate; + QScopedPointer<QQuickWebEngineProfilePrivate> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEPROFILE_P_H diff --git a/src/webengine/api/qquickwebengineprofile_p_p.h b/src/webengine/api/qquickwebengineprofile_p_p.h new file mode 100644 index 000000000..6b6026abb --- /dev/null +++ b/src/webengine/api/qquickwebengineprofile_p_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWEBENGINEPROFILE_P_P_H +#define QQUICKWEBENGINEPROFILE_P_P_H + +class BrowserContextAdapter; + +#include "browser_context_adapter_client.h" +#include "qquickwebengineprofile_p.h" + +#include <QExplicitlySharedDataPointer> +#include <QMap> +#include <QPointer> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineDownloadItem; +class QQuickWebEngineSettings; + +class QQuickWebEngineProfilePrivate : public BrowserContextAdapterClient { +public: + Q_DECLARE_PUBLIC(QQuickWebEngineProfile) + QQuickWebEngineProfilePrivate(BrowserContextAdapter* browserContext, bool ownsContext); + ~QQuickWebEngineProfilePrivate(); + + BrowserContextAdapter *browserContext() const { return m_browserContext; } + QQuickWebEngineSettings *settings() const { return m_settings.data(); } + + void cancelDownload(quint32 downloadId); + void downloadDestroyed(quint32 downloadId); + + void downloadRequested(DownloadItemInfo &info) Q_DECL_OVERRIDE; + void downloadUpdated(const DownloadItemInfo &info) Q_DECL_OVERRIDE; + +private: + friend class QQuickWebEngineViewPrivate; + QQuickWebEngineProfile *q_ptr; + QScopedPointer<QQuickWebEngineSettings> m_settings; + BrowserContextAdapter *m_browserContext; + QExplicitlySharedDataPointer<BrowserContextAdapter> m_browserContextRef; + QMap<quint32, QPointer<QQuickWebEngineDownloadItem> > m_ongoingDownloads; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEPROFILE_P_P_H diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp index 743d22d81..f4c9a656d 100644 --- a/src/webengine/api/qquickwebenginesettings.cpp +++ b/src/webengine/api/qquickwebenginesettings.cpp @@ -35,238 +35,184 @@ ****************************************************************************/ #include "qquickwebenginesettings_p.h" -#include "qquickwebenginesettings_p_p.h" + +#include "qquickwebengineprofile_p.h" +#include "web_engine_settings.h" #include <QtCore/QList> QT_BEGIN_NAMESPACE -Q_GLOBAL_STATIC(QList<QQuickWebEngineSettingsPrivate*>, allSettings) - -QQuickWebEngineSettingsPrivate::QQuickWebEngineSettingsPrivate() - : coreSettings(new WebEngineSettings(this)) -{ - allSettings->append(this); -} - -void QQuickWebEngineSettingsPrivate::apply() -{ - coreSettings->scheduleApply(); - QQuickWebEngineSettingsPrivate *globals = QQuickWebEngineSettings::globalSettings()->d_func(); - Q_ASSERT((this == globals) != (allSettings->contains(this))); - if (this == globals) - Q_FOREACH (QQuickWebEngineSettingsPrivate *settings, *allSettings) - settings->coreSettings->scheduleApply(); -} - -WebEngineSettings *QQuickWebEngineSettingsPrivate::fallbackSettings() const -{ - return QQuickWebEngineSettings::globalSettings()->d_func()->coreSettings.data(); -} - - -QQuickWebEngineSettings *QQuickWebEngineSettings::globalSettings() -{ - static QQuickWebEngineSettings *globals = 0; - if (!globals) { - globals = new QQuickWebEngineSettings; - allSettings->removeAll(globals->d_func()); - globals->d_func()->coreSettings->initDefaults(); - } - return globals; -} +QQuickWebEngineSettings::QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings) + : d_ptr(new WebEngineSettings(parentSettings ? parentSettings->d_ptr.data() : 0)) +{ } QQuickWebEngineSettings::~QQuickWebEngineSettings() -{ - allSettings->removeAll(this->d_func()); -} +{ } bool QQuickWebEngineSettings::autoLoadImages() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::AutoLoadImages); + return d_ptr->testAttribute(WebEngineSettings::AutoLoadImages); } bool QQuickWebEngineSettings::javascriptEnabled() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::JavascriptEnabled); + return d_ptr->testAttribute(WebEngineSettings::JavascriptEnabled); } bool QQuickWebEngineSettings::javascriptCanOpenWindows() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::JavascriptCanOpenWindows); + return d_ptr->testAttribute(WebEngineSettings::JavascriptCanOpenWindows); } bool QQuickWebEngineSettings::javascriptCanAccessClipboard() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard); + return d_ptr->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard); } bool QQuickWebEngineSettings::linksIncludedInFocusChain() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::LinksIncludedInFocusChain); + return d_ptr->testAttribute(WebEngineSettings::LinksIncludedInFocusChain); } bool QQuickWebEngineSettings::localStorageEnabled() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::LocalStorageEnabled); + return d_ptr->testAttribute(WebEngineSettings::LocalStorageEnabled); } bool QQuickWebEngineSettings::localContentCanAccessRemoteUrls() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::LocalContentCanAccessRemoteUrls); + return d_ptr->testAttribute(WebEngineSettings::LocalContentCanAccessRemoteUrls); } bool QQuickWebEngineSettings::spatialNavigationEnabled() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::SpatialNavigationEnabled); + return d_ptr->testAttribute(WebEngineSettings::SpatialNavigationEnabled); } bool QQuickWebEngineSettings::localContentCanAccessFileUrls() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::LocalContentCanAccessFileUrls); + return d_ptr->testAttribute(WebEngineSettings::LocalContentCanAccessFileUrls); } bool QQuickWebEngineSettings::hyperlinkAuditingEnabled() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::HyperlinkAuditingEnabled); + return d_ptr->testAttribute(WebEngineSettings::HyperlinkAuditingEnabled); } bool QQuickWebEngineSettings::errorPageEnabled() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->testAttribute(WebEngineSettings::ErrorPageEnabled); + return d_ptr->testAttribute(WebEngineSettings::ErrorPageEnabled); } QString QQuickWebEngineSettings::defaultTextEncoding() const { - Q_D(const QQuickWebEngineSettings); - return d->coreSettings->defaultTextEncoding(); + return d_ptr->defaultTextEncoding(); } void QQuickWebEngineSettings::setAutoLoadImages(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::AutoLoadImages); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::AutoLoadImages); // Set unconditionally as it sets the override for the current settings while the current setting // could be from the fallback and is prone to changing later on. - d->coreSettings->setAttribute(WebEngineSettings::AutoLoadImages, on); - if (wasOn ^ on) - Q_EMIT autoLoadImagesChanged(on); + d_ptr->setAttribute(WebEngineSettings::AutoLoadImages, on); + if (wasOn != on) + Q_EMIT autoLoadImagesChanged(); } void QQuickWebEngineSettings::setJavascriptEnabled(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::JavascriptEnabled); - d->coreSettings->setAttribute(WebEngineSettings::JavascriptEnabled, on); - if (wasOn ^ on) - Q_EMIT javascriptEnabledChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::JavascriptEnabled); + d_ptr->setAttribute(WebEngineSettings::JavascriptEnabled, on); + if (wasOn != on) + Q_EMIT javascriptEnabledChanged(); } void QQuickWebEngineSettings::setJavascriptCanOpenWindows(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::JavascriptCanOpenWindows); - d->coreSettings->setAttribute(WebEngineSettings::JavascriptCanOpenWindows, on); - if (wasOn ^ on) - Q_EMIT javascriptCanOpenWindowsChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::JavascriptCanOpenWindows); + d_ptr->setAttribute(WebEngineSettings::JavascriptCanOpenWindows, on); + if (wasOn != on) + Q_EMIT javascriptCanOpenWindowsChanged(); } void QQuickWebEngineSettings::setJavascriptCanAccessClipboard(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard); - d->coreSettings->setAttribute(WebEngineSettings::JavascriptCanAccessClipboard, on); - if (wasOn ^ on) - Q_EMIT javascriptCanAccessClipboardChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard); + d_ptr->setAttribute(WebEngineSettings::JavascriptCanAccessClipboard, on); + if (wasOn != on) + Q_EMIT javascriptCanAccessClipboardChanged(); } void QQuickWebEngineSettings::setLinksIncludedInFocusChain(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::LinksIncludedInFocusChain); - d->coreSettings->setAttribute(WebEngineSettings::LinksIncludedInFocusChain, on); - if (wasOn ^ on) - Q_EMIT linksIncludedInFocusChainChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::LinksIncludedInFocusChain); + d_ptr->setAttribute(WebEngineSettings::LinksIncludedInFocusChain, on); + if (wasOn != on) + Q_EMIT linksIncludedInFocusChainChanged(); } void QQuickWebEngineSettings::setLocalStorageEnabled(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::LocalStorageEnabled); - d->coreSettings->setAttribute(WebEngineSettings::LocalStorageEnabled, on); - if (wasOn ^ on) - Q_EMIT localStorageEnabledChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::LocalStorageEnabled); + d_ptr->setAttribute(WebEngineSettings::LocalStorageEnabled, on); + if (wasOn != on) + Q_EMIT localStorageEnabledChanged(); } void QQuickWebEngineSettings::setLocalContentCanAccessRemoteUrls(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::LocalContentCanAccessRemoteUrls); - d->coreSettings->setAttribute(WebEngineSettings::LocalContentCanAccessRemoteUrls, on); - if (wasOn ^ on) - Q_EMIT localContentCanAccessRemoteUrlsChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::LocalContentCanAccessRemoteUrls); + d_ptr->setAttribute(WebEngineSettings::LocalContentCanAccessRemoteUrls, on); + if (wasOn != on) + Q_EMIT localContentCanAccessRemoteUrlsChanged(); } void QQuickWebEngineSettings::setSpatialNavigationEnabled(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::SpatialNavigationEnabled); - d->coreSettings->setAttribute(WebEngineSettings::SpatialNavigationEnabled, on); - if (wasOn ^ on) - Q_EMIT spatialNavigationEnabledChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::SpatialNavigationEnabled); + d_ptr->setAttribute(WebEngineSettings::SpatialNavigationEnabled, on); + if (wasOn != on) + Q_EMIT spatialNavigationEnabledChanged(); } void QQuickWebEngineSettings::setLocalContentCanAccessFileUrls(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::LocalContentCanAccessFileUrls); - d->coreSettings->setAttribute(WebEngineSettings::LocalContentCanAccessFileUrls, on); - if (wasOn ^ on) - Q_EMIT localContentCanAccessFileUrlsChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::LocalContentCanAccessFileUrls); + d_ptr->setAttribute(WebEngineSettings::LocalContentCanAccessFileUrls, on); + if (wasOn != on) + Q_EMIT localContentCanAccessFileUrlsChanged(); } void QQuickWebEngineSettings::setHyperlinkAuditingEnabled(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::HyperlinkAuditingEnabled); - d->coreSettings->setAttribute(WebEngineSettings::HyperlinkAuditingEnabled, on); - if (wasOn ^ on) - Q_EMIT hyperlinkAuditingEnabledChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::HyperlinkAuditingEnabled); + d_ptr->setAttribute(WebEngineSettings::HyperlinkAuditingEnabled, on); + if (wasOn != on) + Q_EMIT hyperlinkAuditingEnabledChanged(); } void QQuickWebEngineSettings::setErrorPageEnabled(bool on) { - Q_D(QQuickWebEngineSettings); - bool wasOn = d->coreSettings->testAttribute(WebEngineSettings::ErrorPageEnabled); - d->coreSettings->setAttribute(WebEngineSettings::ErrorPageEnabled, on); - if (wasOn ^ on) - Q_EMIT errorPageEnabledChanged(on); + bool wasOn = d_ptr->testAttribute(WebEngineSettings::ErrorPageEnabled); + d_ptr->setAttribute(WebEngineSettings::ErrorPageEnabled, on); + if (wasOn != on) + Q_EMIT errorPageEnabledChanged(); } void QQuickWebEngineSettings::setDefaultTextEncoding(QString encoding) { - Q_D(QQuickWebEngineSettings); - const QString oldDefaultTextEncoding = d->coreSettings->defaultTextEncoding(); - d->coreSettings->setDefaultTextEncoding(encoding); + const QString oldDefaultTextEncoding = d_ptr->defaultTextEncoding(); + d_ptr->setDefaultTextEncoding(encoding); if (oldDefaultTextEncoding.compare(encoding)) - Q_EMIT defaultTextEncodingChanged(encoding); + Q_EMIT defaultTextEncodingChanged(); } -QQuickWebEngineSettings::QQuickWebEngineSettings() - : d_ptr(new QQuickWebEngineSettingsPrivate) +void QQuickWebEngineSettings::setParentSettings(QQuickWebEngineSettings *parentSettings) { + d_ptr->setParentSettings(parentSettings->d_ptr.data()); + d_ptr->scheduleApplyRecursively(); } QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h index 4a7c2f834..6e8bfa219 100644 --- a/src/webengine/api/qquickwebenginesettings_p.h +++ b/src/webengine/api/qquickwebenginesettings_p.h @@ -41,9 +41,9 @@ #include <QObject> #include <QScopedPointer> -QT_BEGIN_NAMESPACE +class WebEngineSettings; -class QQuickWebEngineSettingsPrivate; +QT_BEGIN_NAMESPACE class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject { Q_OBJECT @@ -61,8 +61,6 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject { Q_PROPERTY(QString defaultTextEncoding READ defaultTextEncoding WRITE setDefaultTextEncoding NOTIFY defaultTextEncodingChanged) public: - static QQuickWebEngineSettings *globalSettings(); - ~QQuickWebEngineSettings(); bool autoLoadImages() const; @@ -92,26 +90,28 @@ public: void setDefaultTextEncoding(QString encoding); signals: - void autoLoadImagesChanged(bool on); - void javascriptEnabledChanged(bool on); - void javascriptCanOpenWindowsChanged(bool on); - void javascriptCanAccessClipboardChanged(bool on); - void linksIncludedInFocusChainChanged(bool on); - void localStorageEnabledChanged(bool on); - void localContentCanAccessRemoteUrlsChanged(bool on); - void spatialNavigationEnabledChanged(bool on); - void localContentCanAccessFileUrlsChanged(bool on); - void hyperlinkAuditingEnabledChanged(bool on); - void errorPageEnabledChanged(bool on); - void defaultTextEncodingChanged(QString encoding); + void autoLoadImagesChanged(); + void javascriptEnabledChanged(); + void javascriptCanOpenWindowsChanged(); + void javascriptCanAccessClipboardChanged(); + void linksIncludedInFocusChainChanged(); + void localStorageEnabledChanged(); + void localContentCanAccessRemoteUrlsChanged(); + void spatialNavigationEnabledChanged(); + void localContentCanAccessFileUrlsChanged(); + void hyperlinkAuditingEnabledChanged(); + void errorPageEnabledChanged(); + void defaultTextEncodingChanged(); private: - QQuickWebEngineSettings(); + explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = 0); Q_DISABLE_COPY(QQuickWebEngineSettings) - Q_DECLARE_PRIVATE(QQuickWebEngineSettings) + friend class QQuickWebEngineProfilePrivate; friend class QQuickWebEngineViewPrivate; - QScopedPointer<QQuickWebEngineSettingsPrivate> d_ptr; + void setParentSettings(QQuickWebEngineSettings *parentSettings); + + QScopedPointer<WebEngineSettings> d_ptr; }; QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebenginesingleton.cpp b/src/webengine/api/qquickwebenginesingleton.cpp index bf4951f3b..4f1bd32f2 100644 --- a/src/webengine/api/qquickwebenginesingleton.cpp +++ b/src/webengine/api/qquickwebenginesingleton.cpp @@ -37,12 +37,18 @@ #include "qquickwebenginesingleton_p.h" #include "qquickwebenginesettings_p.h" +#include "qquickwebengineprofile_p.h" QT_BEGIN_NAMESPACE QQuickWebEngineSettings *QQuickWebEngineSingleton::settings() const { - return QQuickWebEngineSettings::globalSettings(); + return defaultProfile()->settings(); +} + +QQuickWebEngineProfile *QQuickWebEngineSingleton::defaultProfile() const +{ + return QQuickWebEngineProfile::defaultProfile(); } QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebenginesingleton_p.h b/src/webengine/api/qquickwebenginesingleton_p.h index 23205e2df..f983d0ffb 100644 --- a/src/webengine/api/qquickwebenginesingleton_p.h +++ b/src/webengine/api/qquickwebenginesingleton_p.h @@ -41,14 +41,16 @@ #include <qtwebengineglobal_p.h> QT_BEGIN_NAMESPACE +class QQuickWebEngineProfile; class QQuickWebEngineSettings; - class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSingleton : public QObject { Q_OBJECT Q_PROPERTY(QQuickWebEngineSettings* settings READ settings CONSTANT FINAL) + Q_PROPERTY(QQuickWebEngineProfile* defaultProfile READ defaultProfile CONSTANT FINAL REVISION 1) public: QQuickWebEngineSettings *settings() const; + QQuickWebEngineProfile *defaultProfile() const; }; QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 3497c16ad..a47defb7c 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -37,14 +37,17 @@ #include "qquickwebengineview_p.h" #include "qquickwebengineview_p_p.h" +#include "browser_context_adapter.h" #include "certificate_error_controller.h" #include "javascript_dialog_controller.h" #include "qquickwebenginehistory_p.h" +#include "qquickwebenginecertificateerror_p.h" #include "qquickwebengineloadrequest_p.h" #include "qquickwebenginenavigationrequest_p.h" #include "qquickwebenginenewviewrequest_p.h" +#include "qquickwebengineprofile_p.h" +#include "qquickwebengineprofile_p_p.h" #include "qquickwebenginesettings_p.h" -#include "qquickwebenginesettings_p_p.h" #include "render_widget_host_view_qt_delegate_quick.h" #include "render_widget_host_view_qt_delegate_quickwindow.h" #include "ui_delegates_manager.h" @@ -58,29 +61,34 @@ #include <QQmlContext> #include <QQmlEngine> #include <QQmlProperty> +#include <QQmlWebChannel> #include <QScreen> #include <QStringBuilder> #include <QUrl> +#ifndef QT_NO_ACCESSIBILITY #include <private/qquickaccessibleattached_p.h> +#endif // QT_NO_ACCESSIBILITY QT_BEGIN_NAMESPACE +#ifndef QT_NO_ACCESSIBILITY static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *object) { if (QQuickWebEngineView *v = qobject_cast<QQuickWebEngineView*>(object)) return new QQuickWebEngineViewAccessible(v); return 0; } +#endif // QT_NO_ACCESSIBILITY QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() - : adapter(new WebContentsAdapter) + : adapter(0) , e(new QQuickWebEngineViewExperimental(this)) , v(new QQuickWebEngineViewport(this)) , m_history(new QQuickWebEngineHistory(this)) - , m_settings(new QQuickWebEngineSettings) + , m_profile(QQuickWebEngineProfile::defaultProfile()) + , m_settings(new QQuickWebEngineSettings(m_profile->settings())) , contextMenuExtraItems(0) , loadProgress(0) - , inspectable(false) , m_isFullScreen(false) , isLoading(false) , devicePixelRatio(QGuiApplication::primaryScreen()->devicePixelRatio()) @@ -102,7 +110,9 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() // 1x, 2x, 3x etc assets that fit an integral number of pixels. setDevicePixelRatio(qMax(1, qRound(webPixelRatio))); } +#ifndef QT_NO_ACCESSIBILITY QAccessible::installFactory(&webAccessibleFactory); +#endif // QT_NO_ACCESSIBILITY } QQuickWebEngineViewPrivate::~QQuickWebEngineViewPrivate() @@ -211,10 +221,21 @@ void QQuickWebEngineViewPrivate::javascriptDialog(QSharedPointer<JavaScriptDialo ui()->showDialog(dialog); } -void QQuickWebEngineViewPrivate::allowCertificateError(const QExplicitlySharedDataPointer<CertificateErrorController> &errorController) +void QQuickWebEngineViewPrivate::allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) { - // ### Implement a way to export this to QML - Q_UNUSED(errorController); + Q_Q(QQuickWebEngineView); + + m_certificateErrorController = errorController; + QQuickWebEngineCertificateError *quickController = new QQuickWebEngineCertificateError(errorController); + QQmlEngine::setObjectOwnership(quickController, QQmlEngine::JavaScriptOwnership); + Q_EMIT q->certificateError(quickController); + if (!quickController->deferred()) + quickController->rejectCertificate(); +} + +void QQuickWebEngineViewPrivate::runGeolocationPermissionRequest(const QUrl &url) +{ + Q_EMIT e->featurePermissionRequested(url, QQuickWebEngineViewExperimental::Geolocation); } void QQuickWebEngineViewPrivate::runFileChooser(FileChooserMode mode, const QString &defaultFileName, const QStringList &acceptedMimeTypes) @@ -333,8 +354,16 @@ void QQuickWebEngineViewPrivate::focusContainer() q->forceActiveFocus(); } +void QQuickWebEngineViewPrivate::unhandledKeyEvent(QKeyEvent *event) +{ + Q_Q(QQuickWebEngineView); + if (q->parentItem()) + q->window()->sendEvent(q->parentItem(), event); +} + void QQuickWebEngineViewPrivate::adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &) { + Q_Q(QQuickWebEngineView); QQuickWebEngineNewViewRequest request; // This increases the ref-count of newWebContents and will tell Chromium // to start loading it and possibly return it to its parent page window.open(). @@ -343,9 +372,11 @@ void QQuickWebEngineViewPrivate::adoptNewWindow(WebContentsAdapter *newWebConten switch (disposition) { case WebContentsAdapterClient::NewForegroundTabDisposition: - case WebContentsAdapterClient::NewBackgroundTabDisposition: request.m_destination = QQuickWebEngineView::NewViewInTab; break; + case WebContentsAdapterClient::NewBackgroundTabDisposition: + request.m_destination = QQuickWebEngineView::NewViewInBackgroundTab; + break; case WebContentsAdapterClient::NewPopupDisposition: request.m_destination = QQuickWebEngineView::NewViewInDialog; break; @@ -356,7 +387,7 @@ void QQuickWebEngineViewPrivate::adoptNewWindow(WebContentsAdapter *newWebConten Q_UNREACHABLE(); } - emit e->newViewRequested(&request); + Q_EMIT q->newViewRequested(&request); } void QQuickWebEngineViewPrivate::close() @@ -387,23 +418,39 @@ void QQuickWebEngineViewPrivate::runMediaAccessPermissionRequest(const QUrl &sec return; QQuickWebEngineViewExperimental::Feature feature; if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) - feature = QQuickWebEngineViewExperimental::MediaAudioVideoDevices; + feature = QQuickWebEngineViewExperimental::MediaAudioVideoCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) - feature = QQuickWebEngineViewExperimental::MediaAudioDevices; + feature = QQuickWebEngineViewExperimental::MediaAudioCapture; else // WebContentsAdapterClient::MediaVideoCapture - feature = QQuickWebEngineViewExperimental::MediaVideoDevices; + feature = QQuickWebEngineViewExperimental::MediaVideoCapture; Q_EMIT e->featurePermissionRequested(securityOrigin, feature); } +void QQuickWebEngineViewPrivate::runMouseLockPermissionRequest(const QUrl &securityOrigin) +{ + + Q_UNUSED(securityOrigin); + + // TODO: Add mouse lock support + adapter->grantMouseLockPermission(false); +} + +#ifndef QT_NO_ACCESSIBILITY QObject *QQuickWebEngineViewPrivate::accessibilityParentObject() { Q_Q(QQuickWebEngineView); return q; } +#endif // QT_NO_ACCESSIBILITY + +BrowserContextAdapter *QQuickWebEngineViewPrivate::browserContextAdapter() +{ + return m_profile->d_ptr->browserContext(); +} WebEngineSettings *QQuickWebEngineViewPrivate::webEngineSettings() const { - return m_settings->d_func()->coreSettings.data(); + return m_settings->d_ptr.data(); } void QQuickWebEngineViewPrivate::setDevicePixelRatio(qreal devicePixelRatio) @@ -414,6 +461,7 @@ void QQuickWebEngineViewPrivate::setDevicePixelRatio(qreal devicePixelRatio) m_dpiScale = devicePixelRatio / screen->devicePixelRatio(); } +#ifndef QT_NO_ACCESSIBILITY QQuickWebEngineViewAccessible::QQuickWebEngineViewAccessible(QQuickWebEngineView *o) : QAccessibleObject(o) {} @@ -460,6 +508,7 @@ QAccessible::State QQuickWebEngineViewAccessible::state() const QAccessible::State s; return s; } +#endif // QT_NO_ACCESSIBILITY void QQuickWebEngineViewPrivate::adoptWebContents(WebContentsAdapter *webContents) { @@ -470,6 +519,11 @@ void QQuickWebEngineViewPrivate::adoptWebContents(WebContentsAdapter *webContent return; } + if (browserContextAdapter() != webContents->browserContextAdapter()) { + qWarning("Can not adopt content from a different WebEngineProfile."); + return; + } + Q_Q(QQuickWebEngineView); // This throws away the WebContentsAdapter that has been used until now. // All its states, particularly the loading URL, are replaced by the adopted WebContentsAdapter. @@ -493,22 +547,33 @@ QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) { Q_D(QQuickWebEngineView); d->e->q_ptr = d->q_ptr = this; - d->adapter->initialize(d); this->setActiveFocusOnTab(true); this->setFlag(QQuickItem::ItemIsFocusScope); +#ifndef QT_NO_ACCESSIBILITY QQuickAccessibleAttached *accessible = QQuickAccessibleAttached::qmlAttachedProperties(this); accessible->setRole(QAccessible::Grouping); +#endif // QT_NO_ACCESSIBILITY } QQuickWebEngineView::~QQuickWebEngineView() { } +void QQuickWebEngineViewPrivate::ensureContentsAdapter() +{ + if (!adapter) { + adapter = new WebContentsAdapter(); + adapter->initialize(this); + if (explicitUrl.isValid()) + adapter->load(explicitUrl); + } +} + QUrl QQuickWebEngineView::url() const { Q_D(const QQuickWebEngineView); - return d->explicitUrl.isValid() ? d->explicitUrl : d->adapter->activeUrl(); + return d->explicitUrl.isValid() ? d->explicitUrl : (d->adapter ? d->adapter->activeUrl() : QUrl()); } void QQuickWebEngineView::setUrl(const QUrl& url) @@ -518,7 +583,10 @@ void QQuickWebEngineView::setUrl(const QUrl& url) Q_D(QQuickWebEngineView); d->explicitUrl = url; - d->adapter->load(url); + if (d->adapter) + d->adapter->load(url); + if (!qmlEngine(this)) + d->ensureContentsAdapter(); } QUrl QQuickWebEngineView::icon() const @@ -530,33 +598,93 @@ QUrl QQuickWebEngineView::icon() const void QQuickWebEngineView::loadHtml(const QString &html, const QUrl &baseUrl) { Q_D(QQuickWebEngineView); - d->adapter->setContent(html.toUtf8(), QStringLiteral("text/html;charset=UTF-8"), baseUrl); + d->explicitUrl = QUrl(); + if (!qmlEngine(this)) + d->ensureContentsAdapter(); + if (d->adapter) + d->adapter->setContent(html.toUtf8(), QStringLiteral("text/html;charset=UTF-8"), baseUrl); } void QQuickWebEngineView::goBack() { Q_D(QQuickWebEngineView); + if (!d->adapter) + return; d->adapter->navigateToOffset(-1); } void QQuickWebEngineView::goForward() { Q_D(QQuickWebEngineView); + if (!d->adapter) + return; d->adapter->navigateToOffset(1); } void QQuickWebEngineView::reload() { Q_D(QQuickWebEngineView); + if (!d->adapter) + return; d->adapter->reload(); } void QQuickWebEngineView::stop() { Q_D(QQuickWebEngineView); + if (!d->adapter) + return; d->adapter->stop(); } +void QQuickWebEngineView::setZoomFactor(qreal arg) +{ + Q_D(QQuickWebEngineView); + if (!d->adapter) + return; + qreal oldFactor = d->adapter->currentZoomFactor(); + d->adapter->setZoomFactor(arg); + if (qFuzzyCompare(oldFactor, d->adapter->currentZoomFactor())) + return; + + emit zoomFactorChanged(arg); +} + +QQuickWebEngineProfile *QQuickWebEngineView::profile() const +{ + Q_D(const QQuickWebEngineView); + return d->m_profile; +} + +void QQuickWebEngineView::setProfile(QQuickWebEngineProfile *profile) +{ + Q_D(QQuickWebEngineView); + d->setProfile(profile); +} + +QQuickWebEngineSettings *QQuickWebEngineView::settings() const +{ + Q_D(const QQuickWebEngineView); + return d->m_settings.data(); +} + +void QQuickWebEngineViewPrivate::setProfile(QQuickWebEngineProfile *profile) +{ + if (profile == m_profile) + return; + m_profile = profile; + m_settings->setParentSettings(profile->settings()); + + if (adapter && adapter->browserContext() != browserContextAdapter()->browserContext()) { + // When the profile changes we need to create a new WebContentAdapter and reload the active URL. + QUrl activeUrl = adapter->activeUrl(); + adapter = 0; + ensureContentsAdapter(); + if (!explicitUrl.isValid() && activeUrl.isValid()) + adapter->load(activeUrl); + } +} + void QQuickWebEngineViewPrivate::didRunJavaScript(quint64 requestId, const QVariant &result) { Q_Q(QQuickWebEngineView); @@ -589,24 +717,32 @@ int QQuickWebEngineView::loadProgress() const QString QQuickWebEngineView::title() const { Q_D(const QQuickWebEngineView); + if (!d->adapter) + return QString(); return d->adapter->pageTitle(); } bool QQuickWebEngineView::canGoBack() const { Q_D(const QQuickWebEngineView); + if (!d->adapter) + return false; return d->adapter->canGoBack(); } bool QQuickWebEngineView::canGoForward() const { Q_D(const QQuickWebEngineView); + if (!d->adapter) + return false; return d->adapter->canGoForward(); } void QQuickWebEngineView::runJavaScript(const QString &script, const QJSValue &callback) { Q_D(QQuickWebEngineView); + if (!d->adapter) + return; if (!callback.isUndefined()) { quint64 requestId = d_ptr->adapter->runJavaScriptCallbackResult(script); d->m_callbacks.insert(requestId, callback); @@ -620,17 +756,12 @@ QQuickWebEngineViewExperimental *QQuickWebEngineView::experimental() const return d->e.data(); } -bool QQuickWebEngineViewExperimental::inspectable() const +qreal QQuickWebEngineView::zoomFactor() const { Q_D(const QQuickWebEngineView); - return d->inspectable; -} - -void QQuickWebEngineViewExperimental::setInspectable(bool enable) -{ - Q_D(QQuickWebEngineView); - d->inspectable = enable; - d->adapter->enableInspector(enable); + if (!d->adapter) + return 1.0; + return d->adapter->currentZoomFactor(); } void QQuickWebEngineViewExperimental::setIsFullScreen(bool fullscreen) @@ -657,24 +788,22 @@ QQmlComponent *QQuickWebEngineViewExperimental::extraContextMenuEntriesComponent return d_ptr->contextMenuExtraItems; } -QQuickWebEngineSettings *QQuickWebEngineViewExperimental::settings() const -{ - return d_ptr->m_settings.data(); -} - void QQuickWebEngineViewExperimental::findText(const QString &subString, FindFlags options, const QJSValue &callback) { + Q_D(QQuickWebEngineView); + if (!d->adapter) + return; if (subString.isEmpty()) { - d_ptr->adapter->stopFinding(); + d->adapter->stopFinding(); if (!callback.isUndefined()) { QJSValueList args; args.append(QJSValue(0)); const_cast<QJSValue&>(callback).call(args); } } else { - quint64 requestId = d_ptr->adapter->findText(subString, options & FindCaseSensitively, options & FindBackward); + quint64 requestId = d->adapter->findText(subString, options & FindCaseSensitively, options & FindBackward); if (!callback.isUndefined()) - d_ptr->m_callbacks.insert(requestId, callback); + d->m_callbacks.insert(requestId, callback); } } @@ -683,29 +812,54 @@ QQuickWebEngineHistory *QQuickWebEngineViewExperimental::navigationHistory() con return d_ptr->m_history.data(); } +QQmlWebChannel *QQuickWebEngineViewExperimental::webChannel() const +{ + d_ptr->ensureContentsAdapter(); + QQmlWebChannel *qmlWebChannel = qobject_cast<QQmlWebChannel *>(d_ptr->adapter->webChannel()); + Q_ASSERT(!d_ptr->adapter->webChannel() || qmlWebChannel); + if (!qmlWebChannel) { + qmlWebChannel = new QQmlWebChannel; + d_ptr->adapter->setWebChannel(qmlWebChannel); + } + return qmlWebChannel; +} + +void QQuickWebEngineViewExperimental::setWebChannel(QQmlWebChannel *webChannel) +{ + d_ptr->adapter->setWebChannel(webChannel); +} + void QQuickWebEngineViewExperimental::grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineViewExperimental::Feature feature, bool granted) { - if (!granted && feature >= MediaAudioDevices && feature <= MediaAudioVideoDevices) { + if (!d_ptr->adapter) + return; + if (!granted && feature >= MediaAudioCapture && feature <= MediaAudioVideoCapture) { d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaNone); return; } switch (feature) { - case MediaAudioDevices: + case MediaAudioCapture: d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaAudioCapture); break; - case MediaVideoDevices: + case MediaVideoCapture: d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaVideoCapture); break; - case MediaAudioVideoDevices: - d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaRequestFlags(WebContentsAdapterClient::MediaAudioCapture - | WebContentsAdapterClient::MediaVideoCapture)); + case MediaAudioVideoCapture: + d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaRequestFlags(WebContentsAdapterClient::MediaAudioCapture | WebContentsAdapterClient::MediaVideoCapture)); break; + case Geolocation: + d_ptr->adapter->runGeolocationRequestCallback(securityOrigin, granted); + break; + default: + Q_UNREACHABLE(); } } void QQuickWebEngineViewExperimental::goBackTo(int index) { + if (!d_ptr->adapter) + return; int count = d_ptr->adapter->currentNavigationEntryIndex(); if (index < 0 || index >= count) return; @@ -715,6 +869,8 @@ void QQuickWebEngineViewExperimental::goBackTo(int index) void QQuickWebEngineViewExperimental::goForwardTo(int index) { + if (!d_ptr->adapter) + return; int count = d_ptr->adapter->navigationEntryCount() - d_ptr->adapter->currentNavigationEntryIndex() - 1; if (index < 0 || index >= count) return; @@ -734,7 +890,7 @@ void QQuickWebEngineView::geometryChanged(const QRectF &newGeometry, const QRect void QQuickWebEngineView::itemChange(ItemChange change, const ItemChangeData &value) { Q_D(QQuickWebEngineView); - if (change == ItemSceneChange || change == ItemVisibleHasChanged) { + if (d->adapter && (change == ItemSceneChange || change == ItemVisibleHasChanged)) { if (window() && isVisible()) d->adapter->wasShown(); else @@ -743,6 +899,13 @@ void QQuickWebEngineView::itemChange(ItemChange change, const ItemChangeData &va QQuickItem::itemChange(change, value); } +void QQuickWebEngineView::componentComplete() +{ + Q_D(QQuickWebEngineView); + QQuickItem::componentComplete(); + d->ensureContentsAdapter(); +} + QQuickWebEngineViewExperimental::QQuickWebEngineViewExperimental(QQuickWebEngineViewPrivate *viewPrivate) : q_ptr(0) , d_ptr(viewPrivate) @@ -774,6 +937,8 @@ void QQuickWebEngineViewport::setDevicePixelRatio(qreal devicePixelRatio) if (d->devicePixelRatio == devicePixelRatio) return; d->setDevicePixelRatio(devicePixelRatio); + if (!d->adapter) + return; d->adapter->dpiScaleChanged(); Q_EMIT devicePixelRatioChanged(); } diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 22713ee22..56a1b47ab 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -42,10 +42,14 @@ QT_BEGIN_NAMESPACE -class QQuickWebEngineViewExperimental; -class QQuickWebEngineViewPrivate; +class QQuickWebEngineCertificateError; class QQuickWebEngineLoadRequest; class QQuickWebEngineNavigationRequest; +class QQuickWebEngineNewViewRequest; +class QQuickWebEngineProfile; +class QQuickWebEngineSettings; +class QQuickWebEngineViewExperimental; +class QQuickWebEngineViewPrivate; class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem { Q_OBJECT @@ -56,6 +60,9 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem { Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY urlChanged) Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY urlChanged) + Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor NOTIFY zoomFactorChanged REVISION 1) + Q_PROPERTY(QQuickWebEngineProfile *profile READ profile WRITE setProfile FINAL REVISION 1) + Q_PROPERTY(QQuickWebEngineSettings *settings READ settings REVISION 1) Q_ENUMS(NavigationRequestAction); Q_ENUMS(NavigationType); Q_ENUMS(LoadStatus); @@ -75,6 +82,8 @@ public: QString title() const; bool canGoBack() const; bool canGoForward() const; + qreal zoomFactor() const; + void setZoomFactor(qreal arg); QQuickWebEngineViewExperimental *experimental() const; @@ -116,7 +125,8 @@ public: enum NewViewDestination { NewViewInWindow, NewViewInTab, - NewViewInDialog + NewViewInDialog, + NewViewInBackgroundTab }; // must match WebContentsAdapterClient::JavaScriptConsoleMessageLevel @@ -126,6 +136,14 @@ public: ErrorMessageLevel }; + // QmlParserStatus + virtual void componentComplete() Q_DECL_OVERRIDE; + + QQuickWebEngineProfile *profile() const; + void setProfile(QQuickWebEngineProfile *); + + QQuickWebEngineSettings *settings() const; + public Q_SLOTS: void runJavaScript(const QString&, const QJSValue & = QJSValue()); void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()); @@ -143,6 +161,9 @@ Q_SIGNALS: void linkHovered(const QUrl &hoveredUrl); void navigationRequested(QQuickWebEngineNavigationRequest *request); void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID); + Q_REVISION(1) void certificateError(QQuickWebEngineCertificateError *error); + Q_REVISION(1) void newViewRequested(QQuickWebEngineNewViewRequest *request); + Q_REVISION(1) void zoomFactorChanged(qreal arg); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); @@ -155,7 +176,9 @@ private: friend class QQuickWebEngineViewExperimental; friend class QQuickWebEngineViewExperimentalExtension; friend class QQuickWebEngineNewViewRequest; +#ifndef QT_NO_ACCESSIBILITY friend class QQuickWebEngineViewAccessible; +#endif // QT_NO_ACCESSIBILITY }; QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 6662f1f02..d7785092f 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -51,11 +51,11 @@ class UIDelegatesManager; QT_BEGIN_NAMESPACE class QQuickWebEngineHistory; -class QQuickWebEngineNewViewRequest; class QQuickWebEngineView; class QQmlComponent; class QQmlContext; class QQuickWebEngineSettings; +class QQmlWebChannel; class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineViewport : public QObject { Q_OBJECT @@ -79,18 +79,18 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineViewExperimental : public QObjec Q_OBJECT Q_PROPERTY(QQuickWebEngineViewport *viewport READ viewport) Q_PROPERTY(QQmlComponent *extraContextMenuEntriesComponent READ extraContextMenuEntriesComponent WRITE setExtraContextMenuEntriesComponent NOTIFY extraContextMenuEntriesComponentChanged) - Q_PROPERTY(bool inspectable READ inspectable WRITE setInspectable) Q_PROPERTY(bool isFullScreen READ isFullScreen WRITE setIsFullScreen NOTIFY isFullScreenChanged) Q_PROPERTY(QQuickWebEngineHistory *navigationHistory READ navigationHistory CONSTANT FINAL) - Q_PROPERTY(QQuickWebEngineSettings *settings READ settings) + Q_PROPERTY(QQmlWebChannel *webChannel READ webChannel WRITE setWebChannel) Q_ENUMS(Feature) Q_FLAGS(FindFlags) public: enum Feature { - MediaAudioDevices, - MediaVideoDevices, - MediaAudioVideoDevices + MediaAudioCapture, + MediaVideoCapture, + MediaAudioVideoCapture, + Geolocation }; enum FindFlag { @@ -99,8 +99,6 @@ public: }; Q_DECLARE_FLAGS(FindFlags, FindFlag) - bool inspectable() const; - void setInspectable(bool); void setIsFullScreen(bool fullscreen); bool isFullScreen() const; QQuickWebEngineViewport *viewport() const; @@ -108,6 +106,8 @@ public: QQmlComponent *extraContextMenuEntriesComponent() const; QQuickWebEngineHistory *navigationHistory() const; QQuickWebEngineSettings *settings() const; + QQmlWebChannel *webChannel() const; + void setWebChannel(QQmlWebChannel *); public Q_SLOTS: void goBackTo(int index); @@ -116,7 +116,6 @@ public Q_SLOTS: void grantFeaturePermission(const QUrl &securityOrigin, Feature, bool granted); Q_SIGNALS: - void newViewRequested(QQuickWebEngineNewViewRequest *request); void fullScreenRequested(bool fullScreen); void isFullScreenChanged(); void extraContextMenuEntriesComponentChanged(); @@ -159,6 +158,7 @@ public: virtual void loadVisuallyCommitted() Q_DECL_OVERRIDE; virtual void loadFinished(bool success, const QUrl &url, int errorCode = 0, const QString &errorDescription = QString()) Q_DECL_OVERRIDE; virtual void focusContainer() Q_DECL_OVERRIDE; + virtual void unhandledKeyEvent(QKeyEvent *event) Q_DECL_OVERRIDE; virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &) Q_DECL_OVERRIDE; virtual void close() Q_DECL_OVERRIDE; virtual void requestFullScreen(bool) Q_DECL_OVERRIDE; @@ -175,33 +175,43 @@ public: virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE; virtual void authenticationRequired(const QUrl&, const QString&, bool, const QString&, QString*, QString*) Q_DECL_OVERRIDE { } virtual void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) Q_DECL_OVERRIDE; + virtual void runMouseLockPermissionRequest(const QUrl &securityOrigin) Q_DECL_OVERRIDE; +#ifndef QT_NO_ACCESSIBILITY virtual QObject *accessibilityParentObject() Q_DECL_OVERRIDE; +#endif // QT_NO_ACCESSIBILITY virtual WebEngineSettings *webEngineSettings() const Q_DECL_OVERRIDE; - virtual void allowCertificateError(const QExplicitlySharedDataPointer<CertificateErrorController> &errorController); + virtual void allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController); + virtual void runGeolocationPermissionRequest(QUrl const&) Q_DECL_OVERRIDE; + + virtual BrowserContextAdapter *browserContextAdapter() Q_DECL_OVERRIDE; void setDevicePixelRatio(qreal); void adoptWebContents(WebContentsAdapter *webContents); + void setProfile(QQuickWebEngineProfile *profile); + void ensureContentsAdapter(); QExplicitlySharedDataPointer<WebContentsAdapter> adapter; QScopedPointer<QQuickWebEngineViewExperimental> e; QScopedPointer<QQuickWebEngineViewport> v; QScopedPointer<QQuickWebEngineHistory> m_history; + QQuickWebEngineProfile *m_profile; QScopedPointer<QQuickWebEngineSettings> m_settings; QQmlComponent *contextMenuExtraItems; QUrl explicitUrl; QUrl icon; int loadProgress; - bool inspectable; bool m_isFullScreen; bool isLoading; qreal devicePixelRatio; QMap<quint64, QJSValue> m_callbacks; + QSharedPointer<CertificateErrorController> m_certificateErrorController; private: QScopedPointer<UIDelegatesManager> m_uIDelegatesManager; qreal m_dpiScale; }; +#ifndef QT_NO_ACCESSIBILITY class QQuickWebEngineViewAccessible : public QAccessibleObject { public: @@ -217,7 +227,7 @@ public: private: QQuickWebEngineView *engineView() const { return static_cast<QQuickWebEngineView*>(object()); } }; - +#endif // QT_NO_ACCESSIBILITY QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickWebEngineViewExperimental) diff --git a/src/webengine/doc/qtwebengine.qdocconf b/src/webengine/doc/qtwebengine.qdocconf index e5abeafd6..ad6898440 100644 --- a/src/webengine/doc/qtwebengine.qdocconf +++ b/src/webengine/doc/qtwebengine.qdocconf @@ -33,7 +33,7 @@ depends += qtcore qtgui qtquick qtquickcontrols qtdoc headerdirs += . ../api sourcedirs += . ../api -exampledirs += ../../../examples/webengine +exampledirs += ../../../examples/webengine . navigation.landingpage = "Qt WebEngine" navigation.qmltypespage = "Qt WebEngine QML Types" diff --git a/src/webengine/doc/snippets/qtwebengine_webengineview_newviewrequested.qml b/src/webengine/doc/snippets/qtwebengine_webengineview_newviewrequested.qml new file mode 100644 index 000000000..6c5497145 --- /dev/null +++ b/src/webengine/doc/snippets/qtwebengine_webengineview_newviewrequested.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Window 2.1 +import QtWebEngine 1.1 + +//! [0] +QtObject { + id: windowParent + // Create the initial browsing windows and open the startup page. + Component.onCompleted: { + var firstWindow = windowComponent.createObject(windowParent) + firstWindow.webView.loadHtml('<input type="button" value="Click!" onclick="window.open("http://qt.io")">') + } + + property Component windowComponent: Window { + // Destroy on close to release the Window's QML resources. + // Because it was created with a parent, it won't be garbage-collected. + onClosing: destroy() + visible: true + + property WebEngineView webView: webView_ + WebEngineView { + id: webView_ + anchors.fill: parent + + // Handle the signal. Dynamically create the window and + // use its WebEngineView as the destination of our request. + onNewViewRequested: { + var newWindow = windowComponent.createObject(windowParent) + request.openIn(newWindow.webView) + } + } + } +} +//! [0] diff --git a/src/webengine/doc/src/qquickwebengineview_lgpl.qdoc b/src/webengine/doc/src/qquickwebengineview_lgpl.qdoc index 379c45e1c..24341d745 100644 --- a/src/webengine/doc/src/qquickwebengineview_lgpl.qdoc +++ b/src/webengine/doc/src/qquickwebengineview_lgpl.qdoc @@ -258,6 +258,26 @@ */ /*! + \qmlsignal WebEngineView::newViewRequested(request) + + This signal is emitted when a page load is requested to happen in a separate + WebEngineView. This can either be because the current page requested it explicitly + through a JavaScript call to window.open, or because the user clicked on a link + while holding Shift, Ctrl or a built-in combination that triggers the page to open + in a new window. + + If this signal isn't handled the requested load will fail. + + An example implementation: + + \snippet snippets/qtwebengine_webengineview_newviewrequested.qml 0 + + The corresponding handler is onNewViewRequested. + + \sa WebEngineNewViewRequest, WebEngineView::NewViewDestination, {WebEngine Quick Nano Browser} +*/ + +/*! \qmlproperty enumeration WebEngineView::ErrorDomain This enumeration details various high-level error types. @@ -328,3 +348,20 @@ \endtable */ + +/*! + \qmlproperty enumeration WebEngineView::NewViewDestination + + This enumeration details the format in which a new view request should be opened. + + \value WebEngineView::NewViewInWindow + The page expects to be opened in a separate Window. + \value WebEngineView::NewViewInTab + The page expects to be opened in a tab of the same window. + \value WebEngineView::NewViewInDialog + The page expects to be opened in a Window without any tab, tool or URL bar. + \value WebEngineView::NewViewInBackgroundTab + The page expects to be opened in a tab of the same window, without hiding the currently visible WebEngineView. + + \sa WebEngineNewViewRequest::destination +*/ diff --git a/src/webengine/plugin/experimental/plugin.cpp b/src/webengine/plugin/experimental/plugin.cpp index 883ebc598..4d00a4d3d 100644 --- a/src/webengine/plugin/experimental/plugin.cpp +++ b/src/webengine/plugin/experimental/plugin.cpp @@ -37,18 +37,11 @@ #include <QtQml/qqmlextensionplugin.h> #include "qquickwebenginehistory_p.h" -#include "qquickwebenginesettings_p.h" -#include "qquickwebenginesingleton_p.h" #include "qquickwebengineview_p.h" #include "qquickwebengineview_p_p.h" QT_BEGIN_NAMESPACE -static QObject *webEngineSingletonProvider(QQmlEngine *, QJSEngine *) -{ - return new QQuickWebEngineSingleton; -} - class QQuickWebEngineViewExperimentalExtension : public QObject { Q_OBJECT Q_PROPERTY(QQuickWebEngineViewExperimental* experimental READ experimental CONSTANT FINAL) @@ -78,9 +71,9 @@ public: QObject::tr("Cannot create a separate instance of NavigationHistory")); qmlRegisterUncreatableType<QQuickWebEngineHistoryListModel>(uri, 1, 0, "NavigationHistoryListModel", QObject::tr("Cannot create a separate instance of NavigationHistory")); - qmlRegisterUncreatableType<QQuickWebEngineSettings>(uri, 1, 0, "WebEngineSettings", - QObject::tr("Cannot create a separate instance of WebEngineSettings")); - qmlRegisterSingletonType<QQuickWebEngineSingleton>(uri, 1, 0, "WebEngine", webEngineSingletonProvider); + + // Use the latest revision of QQuickWebEngineView when importing QtWebEngine.experimental 1.0 + qmlRegisterRevision<QQuickWebEngineView, 1>(uri, 1, 0); } }; diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp index 60e401301..b6ac8407c 100644 --- a/src/webengine/plugin/plugin.cpp +++ b/src/webengine/plugin/plugin.cpp @@ -36,17 +36,23 @@ #include <QtQml/qqmlextensionplugin.h> +#include "qquickwebenginecertificateerror_p.h" +#include "qquickwebenginedownloaditem_p.h" #include "qquickwebengineloadrequest_p.h" #include "qquickwebenginenavigationrequest_p.h" #include "qquickwebenginenewviewrequest_p.h" +#include "qquickwebengineprofile_p.h" +#include "qquickwebenginesettings_p.h" +#include "qquickwebenginesingleton_p.h" #include "qquickwebengineview_p.h" #include "qtwebengineversion.h" QT_BEGIN_NAMESPACE -class QQuickWebEngineVersionBumper : public QObject { - Q_OBJECT -}; +static QObject *webEngineSingletonProvider(QQmlEngine *, QJSEngine *) +{ + return new QQuickWebEngineSingleton; +} class QtWebEnginePlugin : public QQmlExtensionPlugin { @@ -59,8 +65,16 @@ public: qmlRegisterType<QQuickWebEngineView>(uri, 1, 0, "WebEngineView"); qmlRegisterUncreatableType<QQuickWebEngineLoadRequest>(uri, 1, 0, "WebEngineLoadRequest", QObject::tr("Cannot create separate instance of WebEngineLoadRequest")); - qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 1, 0, "WebEngineNewViewRequest", QObject::tr("Cannot create separate instance of WebEngineNewViewRequest")); qmlRegisterUncreatableType<QQuickWebEngineNavigationRequest>(uri, 1, 0, "WebEngineNavigationRequest", QObject::tr("Cannot create separate instance of WebEngineNavigationRequest")); + + qmlRegisterType<QQuickWebEngineView, 1>(uri, 1, 1, "WebEngineView"); + qmlRegisterType<QQuickWebEngineProfile>(uri, 1, 1, "WebEngineProfile"); + qmlRegisterUncreatableType<QQuickWebEngineCertificateError>(uri, 1, 1, "WebEngineCertificateError", QObject::tr("Cannot create separate instance of WebEngineCertificateError")); + qmlRegisterUncreatableType<QQuickWebEngineDownloadItem>(uri, 1, 1, "WebEngineDownloadItem", + QObject::tr("Cannot create a separate instance of WebEngineDownloadItem")); + qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 1, 1, "WebEngineNewViewRequest", QObject::tr("Cannot create separate instance of WebEngineNewViewRequest")); + qmlRegisterUncreatableType<QQuickWebEngineSettings>(uri, 1, 1, "WebEngineSettings", QObject::tr("Cannot create a separate instance of WebEngineSettings")); + qmlRegisterSingletonType<QQuickWebEngineSingleton>(uri, 1, 1, "WebEngine", webEngineSingletonProvider); } }; diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp index 7c04cb8c0..663232eda 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp @@ -43,6 +43,8 @@ #include <QQuickWindow> #include <QVariant> #include <QWindow> +#include <private/qquickwindow_p.h> +#include <private/qsgcontext_p.h> RenderWidgetHostViewQtDelegateQuick::RenderWidgetHostViewQtDelegateQuick(RenderWidgetHostViewQtDelegateClient *client, bool isPopup) : m_client(client) @@ -103,6 +105,16 @@ bool RenderWidgetHostViewQtDelegateQuick::hasKeyboardFocus() return hasFocus(); } +void RenderWidgetHostViewQtDelegateQuick::lockMouse() +{ + grabMouse(); +} + +void RenderWidgetHostViewQtDelegateQuick::unlockMouse() +{ + ungrabMouse(); +} + void RenderWidgetHostViewQtDelegateQuick::show() { setVisible(true); @@ -123,6 +135,23 @@ QWindow* RenderWidgetHostViewQtDelegateQuick::window() const return QQuickItem::window(); } +QSGTexture *RenderWidgetHostViewQtDelegateQuick::createTextureFromImage(const QImage &image) +{ + return QQuickItem::window()->createTextureFromImage(image, QQuickWindow::TextureCanUseAtlas); +} + +QSGLayer *RenderWidgetHostViewQtDelegateQuick::createLayer() +{ + QSGRenderContext *renderContext = QQuickWindowPrivate::get(QQuickItem::window())->context; + return renderContext->sceneGraphContext()->createLayer(renderContext); +} + +QSGImageNode *RenderWidgetHostViewQtDelegateQuick::createImageNode() +{ + QSGRenderContext *renderContext = QQuickWindowPrivate::get(QQuickItem::window())->context; + return renderContext->sceneGraphContext()->createImageNode(); +} + void RenderWidgetHostViewQtDelegateQuick::update() { QQuickItem::update(); diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.h b/src/webengine/render_widget_host_view_qt_delegate_quick.h index ddc581289..305c14957 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.h +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.h @@ -53,10 +53,15 @@ public: virtual QRectF contentsRect() const Q_DECL_OVERRIDE; virtual void setKeyboardFocus() Q_DECL_OVERRIDE; virtual bool hasKeyboardFocus() Q_DECL_OVERRIDE; + virtual void lockMouse() Q_DECL_OVERRIDE; + virtual void unlockMouse() Q_DECL_OVERRIDE; virtual void show() Q_DECL_OVERRIDE; virtual void hide() Q_DECL_OVERRIDE; virtual bool isVisible() const Q_DECL_OVERRIDE; virtual QWindow* window() const Q_DECL_OVERRIDE; + virtual QSGTexture *createTextureFromImage(const QImage &) Q_DECL_OVERRIDE; + virtual QSGLayer *createLayer() Q_DECL_OVERRIDE; + virtual QSGImageNode *createImageNode() Q_DECL_OVERRIDE; virtual void update() Q_DECL_OVERRIDE; virtual void updateCursor(const QCursor &) Q_DECL_OVERRIDE; virtual void resize(int width, int height) Q_DECL_OVERRIDE; diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp index da8d3d806..6a0e416e0 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp @@ -95,6 +95,21 @@ QWindow *RenderWidgetHostViewQtDelegateQuickWindow::window() const return const_cast<RenderWidgetHostViewQtDelegateQuickWindow*>(this); } +QSGTexture *RenderWidgetHostViewQtDelegateQuickWindow::createTextureFromImage(const QImage &image) +{ + return m_realDelegate->createTextureFromImage(image); +} + +QSGLayer *RenderWidgetHostViewQtDelegateQuickWindow::createLayer() +{ + return m_realDelegate->createLayer(); +} + +QSGImageNode *RenderWidgetHostViewQtDelegateQuickWindow::createImageNode() +{ + return m_realDelegate->createImageNode(); +} + void RenderWidgetHostViewQtDelegateQuickWindow::update() { QQuickWindow::update(); diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h index eeab4a79a..d3e81e497 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h +++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h @@ -56,10 +56,15 @@ public: virtual QRectF contentsRect() const Q_DECL_OVERRIDE; virtual void setKeyboardFocus() Q_DECL_OVERRIDE {} virtual bool hasKeyboardFocus() Q_DECL_OVERRIDE { return false; } + virtual void lockMouse() Q_DECL_OVERRIDE {} + virtual void unlockMouse() Q_DECL_OVERRIDE {} virtual void show() Q_DECL_OVERRIDE; virtual void hide() Q_DECL_OVERRIDE; virtual bool isVisible() const Q_DECL_OVERRIDE; virtual QWindow* window() const Q_DECL_OVERRIDE; + virtual QSGTexture *createTextureFromImage(const QImage &) Q_DECL_OVERRIDE; + virtual QSGLayer *createLayer() Q_DECL_OVERRIDE; + virtual QSGImageNode *createImageNode() Q_DECL_OVERRIDE; virtual void update() Q_DECL_OVERRIDE; virtual void updateCursor(const QCursor &) Q_DECL_OVERRIDE; virtual void resize(int width, int height) Q_DECL_OVERRIDE; diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp index 9e7af3fad..a8abcfff5 100644 --- a/src/webengine/ui_delegates_manager.cpp +++ b/src/webengine/ui_delegates_manager.cpp @@ -345,7 +345,7 @@ public: FilePickerController(WebContentsAdapterClient::FileChooserMode, const QExplicitlySharedDataPointer<WebContentsAdapter> &, QObject * = 0); public Q_SLOTS: - void accepted(const QJSValue &files); + void accepted(const QVariant &files); void rejected(); private: @@ -362,14 +362,11 @@ FilePickerController::FilePickerController(WebContentsAdapterClient::FileChooser { } -void FilePickerController::accepted(const QJSValue &filesValue) +void FilePickerController::accepted(const QVariant &files) { QStringList stringList; - int length = filesValue.property(QStringLiteral("length")).toInt(); - for (int i = 0; i < length; i++) { - stringList.append(QUrl(filesValue.property(i).toString()).toLocalFile()); - } - + Q_FOREACH (const QUrl &url, files.value<QList<QUrl> >()) + stringList.append(url.toLocalFile()); m_adapter->filesSelectedInChooser(stringList, m_mode); } @@ -418,7 +415,7 @@ void UIDelegatesManager::showFilePicker(WebContentsAdapterClient::FileChooserMod CHECK_QML_SIGNAL_PROPERTY(filesPickedSignal, filePickerComponent->url()); QQmlProperty rejectSignal(filePicker, QStringLiteral("onRejected")); CHECK_QML_SIGNAL_PROPERTY(rejectSignal, filePickerComponent->url()); - static int acceptedIndex = controller->metaObject()->indexOfSlot("accepted(QJSValue)"); + static int acceptedIndex = controller->metaObject()->indexOfSlot("accepted(QVariant)"); QObject::connect(filePicker, filesPickedSignal.method(), controller, controller->metaObject()->method(acceptedIndex)); static int rejectedIndex = controller->metaObject()->indexOfSlot("rejected()"); QObject::connect(filePicker, rejectSignal.method(), controller, controller->metaObject()->method(rejectedIndex)); diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro index 4c4606690..8a6d06c10 100644 --- a/src/webengine/webengine.pro +++ b/src/webengine/webengine.pro @@ -4,17 +4,20 @@ TARGET = QtWebEngine DEFINES += QT_BUILD_WEBENGINE_LIB QT += qml quick -QT_PRIVATE += webenginecore quick-private +QT_PRIVATE += webenginecore quick-private gui-private core-private QMAKE_DOCS = $$PWD/doc/qtwebengine.qdocconf INCLUDEPATH += $$PWD api ../core SOURCES = \ + api/qquickwebenginecertificateerror.cpp \ + api/qquickwebenginedownloaditem.cpp \ api/qquickwebenginehistory.cpp \ api/qquickwebengineloadrequest.cpp \ api/qquickwebenginenavigationrequest.cpp \ api/qquickwebenginenewviewrequest.cpp \ + api/qquickwebengineprofile.cpp \ api/qquickwebenginesettings.cpp \ api/qquickwebenginesingleton.cpp \ api/qquickwebengineview.cpp \ @@ -26,12 +29,16 @@ SOURCES = \ HEADERS = \ api/qtwebengineglobal.h \ api/qtwebengineglobal_p.h \ + api/qquickwebenginecertificateerror_p.h \ + api/qquickwebenginedownloaditem_p.h \ + api/qquickwebenginedownloaditem_p_p.h \ api/qquickwebenginehistory_p.h \ api/qquickwebengineloadrequest_p.h \ api/qquickwebenginenavigationrequest_p.h \ api/qquickwebenginenewviewrequest_p.h \ + api/qquickwebengineprofile_p.h \ + api/qquickwebengineprofile_p_p.h \ api/qquickwebenginesettings_p.h \ - api/qquickwebenginesettings_p_p.h \ api/qquickwebenginesingleton_p.h \ api/qquickwebengineview_p.h \ api/qquickwebengineview_p_p.h \ diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp new file mode 100644 index 000000000..9bfe1f9fd --- /dev/null +++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp @@ -0,0 +1,302 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwebenginedownloaditem.h" + +#include "qwebenginedownloaditem_p.h" +#include "qwebengineprofile_p.h" + +QT_BEGIN_NAMESPACE + +static inline QWebEngineDownloadItem::DownloadState toDownloadState(int state) +{ + switch (state) { + case BrowserContextAdapterClient::DownloadInProgress: + return QWebEngineDownloadItem::DownloadInProgress; + case BrowserContextAdapterClient::DownloadCompleted: + return QWebEngineDownloadItem::DownloadCompleted; + case BrowserContextAdapterClient::DownloadCancelled: + return QWebEngineDownloadItem::DownloadCancelled; + case BrowserContextAdapterClient::DownloadInterrupted: + return QWebEngineDownloadItem::DownloadInterrupted; + default: + Q_UNREACHABLE(); + return QWebEngineDownloadItem::DownloadCancelled; + } +} + +/*! + \class QWebEngineDownloadItem + \brief The QWebEngineDownloadItem class provides information about a download. + + \since 5.5 + + \inmodule QtWebEngineWidgets + + QWebEngineDownloadItem stores the state of a download to be used to manage requested downloads. +*/ + +QWebEngineDownloadItemPrivate::QWebEngineDownloadItemPrivate(QWebEngineProfilePrivate *p, const QUrl &url) + : profile(p) + , downloadFinished(false) + , downloadId(-1) + , downloadState(QWebEngineDownloadItem::DownloadCancelled) + , downloadUrl(url) + , totalBytes(-1) + , receivedBytes(0) +{ +} + +QWebEngineDownloadItemPrivate::~QWebEngineDownloadItemPrivate() +{ + profile->downloadDestroyed(downloadId); +} + +void QWebEngineDownloadItemPrivate::update(const BrowserContextAdapterClient::DownloadItemInfo &info) +{ + Q_Q(QWebEngineDownloadItem); + + Q_ASSERT(downloadState != QWebEngineDownloadItem::DownloadRequested); + + if (toDownloadState(info.state) != downloadState) { + downloadState = toDownloadState(info.state); + Q_EMIT q->stateChanged(downloadState); + } + + if (info.receivedBytes != receivedBytes || info.totalBytes != totalBytes) { + receivedBytes = info.receivedBytes; + totalBytes = info.totalBytes; + Q_EMIT q->downloadProgress(receivedBytes, totalBytes); + } + + downloadFinished = downloadState != QWebEngineDownloadItem::DownloadInProgress; + + if (downloadFinished) + Q_EMIT q->finished(); +} + +/*! + Accepts the current download request, which will start the download. + + \sa finished(), stateChanged() +*/ + +void QWebEngineDownloadItem::accept() +{ + Q_D(QWebEngineDownloadItem); + + if (d->downloadState != QWebEngineDownloadItem::DownloadRequested) + return; + + d->downloadState = QWebEngineDownloadItem::DownloadInProgress; + Q_EMIT stateChanged(d->downloadState); +} + +/*! + Cancels the current download. + + \sa finished(), stateChanged() +*/ + +void QWebEngineDownloadItem::cancel() +{ + Q_D(QWebEngineDownloadItem); + + QWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (state == QWebEngineDownloadItem::DownloadCompleted + || state == QWebEngineDownloadItem::DownloadCancelled) + return; + + d->downloadState = QWebEngineDownloadItem::DownloadCancelled; + Q_EMIT stateChanged(d->downloadState); + + // We directly cancel the download request if the user cancels + // before it even started, so no need to notify the profile here. + if (state == QWebEngineDownloadItem::DownloadInProgress) + d->profile->cancelDownload(d->downloadId); +} + +/*! + Returns the download item's id. +*/ + +quint32 QWebEngineDownloadItem::id() +{ + Q_D(QWebEngineDownloadItem); + return d->downloadId; +} + +/*! + \fn QWebEngineDownloadItem::finished() + + This signal is emitted whenever the download finishes. + + \sa state(), isFinished() +*/ + +/*! + \fn QWebEngineDownloadItem::stateChanged(DownloadState state) + + This signal is emitted whenever the download's \a state changes. + + \sa state(), QWebEngineDownloadItem::DownloadState +*/ + +/*! + \fn QWebEngineDownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) + + This signal is emitted whenever the download's \a bytesReceived or + \a bytesTotal changes. + + \sa totalBytes(), receivedBytes() +*/ + +/*! + \enum QWebEngineDownloadItem::DownloadState + + This enum describes the state in which the download is in. + + \value DownloadRequested The download has been requested, but has not been accepted yet. + \value DownloadInProgress The download is in progress. + \value DownloadCompleted The download completed successfully. + \value DownloadCancelled The download has been cancelled. + \value DownloadInterrupted The download has been interrupted (by the server or because of lost connectivity). +*/ + +/*! + Returns the download item's current state. + + \sa QWebEngineDownloadItem::DownloadState +*/ + +QWebEngineDownloadItem::DownloadState QWebEngineDownloadItem::state() +{ + Q_D(QWebEngineDownloadItem); + return d->downloadState; +} + +/*! + Returns the download's total size in bytes. + + -1 means the size is unknown. +*/ + +qint64 QWebEngineDownloadItem::totalBytes() +{ + Q_D(QWebEngineDownloadItem); + return d->totalBytes; +} + +/*! + Returns the download's bytes that have been received so far. + + -1 means the size is unknown. +*/ + +qint64 QWebEngineDownloadItem::receivedBytes() +{ + Q_D(QWebEngineDownloadItem); + return d->receivedBytes; +} + +/*! + Returns the download's origin url. +*/ + +QUrl QWebEngineDownloadItem::url() +{ + Q_D(QWebEngineDownloadItem); + return d->downloadUrl; +} + +/*! + Returns the download's full target path where it is being downloaded to. + + The path includes the file name. The default suggested path is the standard download location + and file name is deduced not to overwrite already existing files. +*/ + +QString QWebEngineDownloadItem::path() +{ + Q_D(QWebEngineDownloadItem); + return d->downloadPath; +} + +/*! + Sets the download's full target path, where the file should be downloaded to. + + The \a path should also include the file name. The download path can only be set in response + to the QWebEngineProfile::downloadRequested() signal before the download is accepted. + Past that point this function has no effect on the download item's state. +*/ +void QWebEngineDownloadItem::setPath(QString path) +{ + Q_D(QWebEngineDownloadItem); + if (d->downloadState != QWebEngineDownloadItem::DownloadRequested) { + qWarning("Setting the download path is not allowed after the download has been accepted."); + return; + } + + d->downloadPath = path; +} + +/*! + Returns whether this download is finished (not in progress). + + \sa finished(), state(), +*/ + +bool QWebEngineDownloadItem::isFinished() +{ + Q_D(QWebEngineDownloadItem); + return d->downloadFinished; +} + +QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p, QObject *parent) + : QObject(parent) + , d_ptr(p) +{ + p->q_ptr = this; +} + +/*! \internal +*/ +QWebEngineDownloadItem::~QWebEngineDownloadItem() +{ +} + +QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.h b/src/webenginewidgets/api/qwebenginedownloaditem.h new file mode 100644 index 000000000..1051d686c --- /dev/null +++ b/src/webenginewidgets/api/qwebenginedownloaditem.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINEDOWNLOADITEM_H +#define QWEBENGINEDOWNLOADITEM_H + +#include "qtwebenginewidgetsglobal.h" + +#include <QObject> + +QT_BEGIN_NAMESPACE + +class QWebEngineDownloadItemPrivate; +class QWebEngineProfilePrivate; + +class QWEBENGINEWIDGETS_EXPORT QWebEngineDownloadItem : public QObject +{ + Q_OBJECT +public: + ~QWebEngineDownloadItem(); + + enum DownloadState { + DownloadRequested, + DownloadInProgress, + DownloadCompleted, + DownloadCancelled, + DownloadInterrupted + }; + Q_ENUMS(DownloadState) + + quint32 id(); + DownloadState state(); + qint64 totalBytes(); + qint64 receivedBytes(); + QUrl url(); + QString path(); + void setPath(QString path); + bool isFinished(); + +public Q_SLOTS: + void accept(); + void cancel(); + +Q_SIGNALS: + void finished(); + void stateChanged(DownloadState state); + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + +private: + Q_DISABLE_COPY(QWebEngineDownloadItem) + Q_DECLARE_PRIVATE(QWebEngineDownloadItem) + + friend class QWebEngineProfilePrivate; + + QWebEngineDownloadItem(QWebEngineDownloadItemPrivate*, QObject *parent = 0); + QScopedPointer<QWebEngineDownloadItemPrivate> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEDOWNLOADITEM_H diff --git a/src/webenginewidgets/api/qwebenginedownloaditem_p.h b/src/webenginewidgets/api/qwebenginedownloaditem_p.h new file mode 100644 index 000000000..a7e5b36e6 --- /dev/null +++ b/src/webenginewidgets/api/qwebenginedownloaditem_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINEDOWNLOADITEM_P_H +#define QWEBENGINEDOWNLOADITEM_P_H + +#include "qtwebenginewidgetsglobal.h" + +#include "qwebenginedownloaditem_p.h" +#include "qwebengineprofile_p.h" +#include <QString> + +QT_BEGIN_NAMESPACE + +class QWebEngineDownloadItemPrivate { + QWebEngineDownloadItem *q_ptr; + QWebEngineProfilePrivate* profile; + friend class QWebEngineProfilePrivate; +public: + Q_DECLARE_PUBLIC(QWebEngineDownloadItem) + QWebEngineDownloadItemPrivate(QWebEngineProfilePrivate *p, const QUrl &url); + ~QWebEngineDownloadItemPrivate(); + + bool downloadFinished; + quint32 downloadId; + QWebEngineDownloadItem::DownloadState downloadState; + QString downloadPath; + const QUrl downloadUrl; + + qint64 totalBytes; + qint64 receivedBytes; + + void update(const BrowserContextAdapterClient::DownloadItemInfo &info); +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEDOWNLOADITEM_P_H + diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 72b16f28b..a59165e8b 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -23,12 +23,14 @@ #include "qwebenginepage.h" #include "qwebenginepage_p.h" +#include "browser_context_adapter.h" #include "certificate_error_controller.h" #include "javascript_dialog_controller.h" #include "qwebenginehistory.h" #include "qwebenginehistory_p.h" +#include "qwebengineprofile.h" +#include "qwebengineprofile_p.h" #include "qwebenginesettings.h" -#include "qwebenginesettings_p.h" #include "qwebengineview.h" #include "qwebengineview_p.h" #include "render_widget_host_view_qt_delegate_widget.h" @@ -166,10 +168,11 @@ void CallbackDirectory::CallbackSharedDataPointer::doDeref() } } -QWebEnginePagePrivate::QWebEnginePagePrivate() +QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) : adapter(new WebContentsAdapter) , history(new QWebEngineHistory(new QWebEngineHistoryPrivate(this))) - , settings(new QWebEngineSettings) + , profile(_profile ? _profile : QWebEngineProfile::defaultProfile()) + , settings(new QWebEngineSettings(profile->settings())) , view(0) , isLoading(false) { @@ -267,6 +270,12 @@ void QWebEnginePagePrivate::focusContainer() view->setFocus(); } +void QWebEnginePagePrivate::unhandledKeyEvent(QKeyEvent *event) +{ + if (view && view->parentWidget()) + QGuiApplication::sendEvent(view->parentWidget(), event); +} + void QWebEnginePagePrivate::adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &initialGeometry) { Q_Q(QWebEnginePage); @@ -342,10 +351,24 @@ void QWebEnginePagePrivate::runMediaAccessPermissionRequest(const QUrl &security Q_EMIT q->featurePermissionRequested(securityOrigin, requestedFeature); } +void QWebEnginePagePrivate::runGeolocationPermissionRequest(const QUrl &securityOrigin) +{ + Q_Q(QWebEnginePage); + Q_EMIT q->featurePermissionRequested(securityOrigin, QWebEnginePage::Geolocation); +} + +void QWebEnginePagePrivate::runMouseLockPermissionRequest(const QUrl &securityOrigin) +{ + Q_Q(QWebEnginePage); + Q_EMIT q->featurePermissionRequested(securityOrigin, QWebEnginePage::MouseLock); +} + +#ifndef QT_NO_ACCESSIBILITY QObject *QWebEnginePagePrivate::accessibilityParentObject() { return view; } +#endif // QT_NO_ACCESSIBILITY void QWebEnginePagePrivate::updateAction(QWebEnginePage::WebAction action) const { @@ -410,9 +433,31 @@ void QWebEnginePagePrivate::recreateFromSerializedHistory(QDataStream &input) } } +BrowserContextAdapter *QWebEnginePagePrivate::browserContextAdapter() +{ + return profile->d_ptr->browserContext(); +} + QWebEnginePage::QWebEnginePage(QObject* parent) : QObject(parent) - , d_ptr(new QWebEnginePagePrivate) + , d_ptr(new QWebEnginePagePrivate()) +{ + Q_D(QWebEnginePage); + d->q_ptr = this; + d->adapter->initialize(d); +} + +/*! + Constructs an empty QWebEnginePage in the QWebEngineProfile \a profile with parent \a parent. + + If the profile is not the default profile the caller must ensure the profile is alive for as + long as the page is. + + \since 5.5 +*/ +QWebEnginePage::QWebEnginePage(QWebEngineProfile *profile, QObject* parent) + : QObject(parent) + , d_ptr(new QWebEnginePagePrivate(profile)) { Q_D(QWebEnginePage); d->q_ptr = this; @@ -448,6 +493,16 @@ QWidget *QWebEnginePage::view() const return d->view; } +/*! + Returns the QWebEngineProfile the page belongs to. + \since 5.5 +*/ +QWebEngineProfile *QWebEnginePage::profile() const +{ + Q_D(const QWebEnginePage); + return d->profile; +} + bool QWebEnginePage::hasSelection() const { return !selectedText().isEmpty(); @@ -624,6 +679,13 @@ bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData return true; } +void QWebEnginePagePrivate::navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) +{ + Q_Q(QWebEnginePage); + bool accepted = q->acceptNavigationRequest(url, static_cast<QWebEnginePage::NavigationType>(navigationType), isMainFrame); + navigationRequestAction = accepted ? WebContentsAdapterClient::AcceptRequest : WebContentsAdapterClient::IgnoreRequest; +} + void QWebEnginePagePrivate::javascriptDialog(QSharedPointer<JavaScriptDialogController> controller) { Q_Q(QWebEnginePage); @@ -654,7 +716,7 @@ void QWebEnginePagePrivate::javascriptDialog(QSharedPointer<JavaScriptDialogCont controller->reject(); } -void QWebEnginePagePrivate::allowCertificateError(const QExplicitlySharedDataPointer<CertificateErrorController> &controller) +void QWebEnginePagePrivate::allowCertificateError(const QSharedPointer<CertificateErrorController> &controller) { Q_Q(QWebEnginePage); bool accepted = false; @@ -743,6 +805,8 @@ QMenu *QWebEnginePage::createStandardContextMenu() void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEnginePage::Feature feature, QWebEnginePage::PermissionPolicy policy) { Q_D(QWebEnginePage); + if (policy == PermissionUnknown) + return; WebContentsAdapterClient::MediaRequestFlags flags = WebContentsAdapterClient::MediaNone; switch (feature) { case MediaAudioVideoCapture: @@ -761,6 +825,16 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine } d->adapter->grantMediaAccessPermission(securityOrigin, flags); } + d->adapter->grantMediaAccessPermission(securityOrigin, flags); + break; + case QWebEnginePage::Geolocation: + d->adapter->runGeolocationRequestCallback(securityOrigin, (policy == PermissionGrantedByUser) ? true : false); + break; + case MouseLock: + if (policy == PermissionGrantedByUser) + d->adapter->grantMouseLockPermission(true); + else + d->adapter->grantMouseLockPermission(false); break; default: break; @@ -782,7 +856,7 @@ void QWebEnginePagePrivate::runFileChooser(WebContentsAdapterClient::FileChooser WebEngineSettings *QWebEnginePagePrivate::webEngineSettings() const { - return settings->d_func()->coreSettings.data(); + return settings->d_func(); } void QWebEnginePage::load(const QUrl& url) @@ -883,8 +957,8 @@ QWebEnginePage *QWebEnginePage::createWindow(WebWindowType type) return 0; } -Q_STATIC_ASSERT_X(static_cast<int>(WebContentsAdapterClient::Open) == static_cast<int>(QWebEnginePage::FileSelectOpen), "Enums out of sync"); -Q_STATIC_ASSERT_X(static_cast<int>(WebContentsAdapterClient::OpenMultiple) == static_cast<int>(QWebEnginePage::FileSelectOpenMultiple), "Enums out of sync"); +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::Open, QWebEnginePage::FileSelectOpen) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::OpenMultiple, QWebEnginePage::FileSelectOpenMultiple) QStringList QWebEnginePage::chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes) { @@ -945,6 +1019,14 @@ bool QWebEnginePage::certificateError(const QWebEngineCertificateError &) return false; } +bool QWebEnginePage::acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) +{ + Q_UNUSED(url); + Q_UNUSED(type); + Q_UNUSED(isMainFrame); + return true; +} + QT_END_NAMESPACE #include "moc_qwebenginepage.cpp" diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index 7856b8243..a194df831 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -50,8 +50,9 @@ QT_BEGIN_NAMESPACE class QMenu; class QWebEngineHistory; class QWebEnginePage; -class QWebEngineSettings; class QWebEnginePagePrivate; +class QWebEngineProfile; +class QWebEngineSettings; namespace QtWebEnginePrivate { @@ -136,14 +137,25 @@ public: PermissionDeniedByUser }; + // must match WebContentsAdapterClient::NavigationType + enum NavigationType { + NavigationTypeLinkClicked, + NavigationTypeTyped, + NavigationTypeFormSubmitted, + NavigationTypeBackForward, + NavigationTypeReload, + NavigationTypeOther + }; + enum Feature { #ifndef Q_QDOC Notifications = 0, - Geolocation = 1, #endif + Geolocation = 1, MediaAudioCapture = 2, MediaVideoCapture, - MediaAudioVideoCapture + MediaAudioVideoCapture, + MouseLock }; // Ex-QWebFrame enum @@ -161,6 +173,7 @@ public: }; explicit QWebEnginePage(QObject *parent = 0); + QWebEnginePage(QWebEngineProfile *profile, QObject *parent = 0); ~QWebEnginePage(); QWebEngineHistory *history() const; @@ -170,6 +183,8 @@ public: bool hasSelection() const; QString selectedText() const; + QWebEngineProfile *profile() const; + #ifndef QT_NO_ACTION QAction *action(WebAction action) const; #endif @@ -248,6 +263,7 @@ protected: virtual bool javaScriptPrompt(const QUrl &securityOrigin, const QString& msg, const QString& defaultValue, QString* result); virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID); virtual bool certificateError(const QWebEngineCertificateError &certificateError); + virtual bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame); private: Q_DECLARE_PRIVATE(QWebEnginePage); @@ -258,7 +274,9 @@ private: friend class QWebEngineView; friend class QWebEngineViewPrivate; +#ifndef QT_NO_ACCESSIBILITY friend class QWebEngineViewAccessible; +#endif // QT_NO_ACCESSIBILITY }; diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 54129229f..6c6520414 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -49,6 +49,7 @@ class WebContentsAdapter; QT_BEGIN_NAMESPACE class QWebEngineHistory; class QWebEnginePage; +class QWebEngineProfile; class QWebEngineSettings; class QWebEngineView; @@ -101,7 +102,7 @@ public: Q_DECLARE_PUBLIC(QWebEnginePage) QWebEnginePage *q_ptr; - QWebEnginePagePrivate(); + QWebEnginePagePrivate(QWebEngineProfile *profile = 0); ~QWebEnginePagePrivate(); virtual RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client) Q_DECL_OVERRIDE; @@ -119,10 +120,11 @@ public: virtual void loadVisuallyCommitted() Q_DECL_OVERRIDE { } virtual void loadFinished(bool success, const QUrl &url, int errorCode = 0, const QString &errorDescription = QString()) Q_DECL_OVERRIDE; virtual void focusContainer() Q_DECL_OVERRIDE; + virtual void unhandledKeyEvent(QKeyEvent *event) Q_DECL_OVERRIDE; virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &initialGeometry) Q_DECL_OVERRIDE; virtual void close() Q_DECL_OVERRIDE; virtual bool contextMenuRequested(const WebEngineContextMenuData &data) Q_DECL_OVERRIDE; - virtual void navigationRequested(int, const QUrl &, int &, bool) Q_DECL_OVERRIDE { } + virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) Q_DECL_OVERRIDE; virtual void requestFullScreen(bool) Q_DECL_OVERRIDE { } virtual bool isFullScreen() const Q_DECL_OVERRIDE { return false; } virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) Q_DECL_OVERRIDE; @@ -135,9 +137,15 @@ public: virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE; virtual void authenticationRequired(const QUrl &requestUrl, const QString &realm, bool isProxy, const QString &challengingHost, QString *outUser, QString *outPassword) Q_DECL_OVERRIDE; virtual void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) Q_DECL_OVERRIDE; + virtual void runGeolocationPermissionRequest(const QUrl &securityOrigin) Q_DECL_OVERRIDE; + virtual void runMouseLockPermissionRequest(const QUrl &securityOrigin) Q_DECL_OVERRIDE; +#ifndef QT_NO_ACCESSIBILITY virtual QObject *accessibilityParentObject() Q_DECL_OVERRIDE; +#endif // QT_NO_ACCESSIBILITY virtual WebEngineSettings *webEngineSettings() const Q_DECL_OVERRIDE; - virtual void allowCertificateError(const QExplicitlySharedDataPointer<CertificateErrorController> &controller) Q_DECL_OVERRIDE; + virtual void allowCertificateError(const QSharedPointer<CertificateErrorController> &controller) Q_DECL_OVERRIDE; + + virtual BrowserContextAdapter *browserContextAdapter() Q_DECL_OVERRIDE; void updateAction(QWebEnginePage::WebAction) const; void updateNavigationActions(); @@ -148,6 +156,7 @@ public: QExplicitlySharedDataPointer<WebContentsAdapter> adapter; QWebEngineHistory *history; + QWebEngineProfile *profile; QWebEngineSettings *settings; QWebEngineView *view; QSize viewportSize; diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp new file mode 100644 index 000000000..afe0774c0 --- /dev/null +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -0,0 +1,456 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwebengineprofile.h" + +#include "qwebenginedownloaditem.h" +#include "qwebenginedownloaditem_p.h" +#include "qwebenginepage.h" +#include "qwebengineprofile_p.h" +#include "qwebenginesettings.h" + +#include "browser_context_adapter.h" +#include "web_engine_visited_links_manager.h" +#include "web_engine_settings.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QWebEngineProfile + \brief The QWebEngineProfile class provides a web-engine profile shared by multiple pages. + \since 5.5 + + \inmodule QtWebEngineWidgets + + QWebEngineProfile contains settings and history shared by all QWebEnginePages that belong + to the profile. + + A default profile is built-in that all web pages not specifically created with another profile + belongs to. +*/ + +/*! + \enum QWebEngineProfile::HttpCacheType + + This enum describes the HTTP cache types QtWebEngine can be configured to use. + + \value MemoryHttpCache Use a in-memory cache. This is the only setting possible if off-the-record is set or no cache path is available. + \value DiskHttpCache Use a disk cache. This is the default. +*/ + +/*! + \enum QWebEngineProfile::PersistentCookiesPolicy + + This enum describes policy for cookie persistency. + + \value NoPersistentCookies Both session and persistent cookies are stored in memory. This is the only setting possible if off-the-record is set or no persistent data path is available. + \value AllowPersistentCookies Cookies marked persistent are save and restored from disk, session cookies are only stored to disk for crash recovery. This is the default setting. + \value ForcePersistentCookies Both session and persistent cookies are save and restored from disk. +*/ + +/*! + \fn QWebEngineProfile::downloadRequested(QWebEngineDownloadItem *download) + + \since 5.5 + + This signal is emitted whenever a download has been triggered. + The \a download argument holds the state of the download. + The \a download either has to be explicitly accepted with + QWebEngineDownloadItem::accept(), else the download will be + cancelled by default. + The download item is parented by the profile, but if not accepted + will be deleted immediately after the signal emission. + This signal can not be used with a queued connection. + + \sa QWebEngineDownloadItem +*/ + +QWebEngineProfilePrivate::QWebEngineProfilePrivate(BrowserContextAdapter* browserContext, bool ownsContext) + : m_settings(new QWebEngineSettings()) + , m_browserContext(browserContext) +{ + if (ownsContext) + m_browserContextRef = browserContext; + + m_browserContext->setClient(this); + m_settings->d_ptr->initDefaults(browserContext->isOffTheRecord()); +} + +QWebEngineProfilePrivate::~QWebEngineProfilePrivate() +{ + delete m_settings; + m_settings = 0; + m_browserContext->setClient(0); + + Q_FOREACH (QWebEngineDownloadItem* download, m_ongoingDownloads) { + if (download) + download->cancel(); + } + + m_ongoingDownloads.clear(); +} + +void QWebEngineProfilePrivate::cancelDownload(quint32 downloadId) +{ + m_browserContext->cancelDownload(downloadId); +} + +void QWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId) +{ + m_ongoingDownloads.remove(downloadId); +} + +void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) +{ + Q_Q(QWebEngineProfile); + + Q_ASSERT(!m_ongoingDownloads.contains(info.id)); + QWebEngineDownloadItemPrivate *itemPrivate = new QWebEngineDownloadItemPrivate(this, info.url); + itemPrivate->downloadId = info.id; + itemPrivate->downloadState = QWebEngineDownloadItem::DownloadRequested; + itemPrivate->downloadPath = info.path; + + QWebEngineDownloadItem *download = new QWebEngineDownloadItem(itemPrivate, q); + + m_ongoingDownloads.insert(info.id, download); + + Q_EMIT q->downloadRequested(download); + + QWebEngineDownloadItem::DownloadState state = download->state(); + + info.path = download->path(); + info.accepted = state != QWebEngineDownloadItem::DownloadCancelled; + + if (state == QWebEngineDownloadItem::DownloadRequested) { + // Delete unaccepted downloads. + info.accepted = false; + m_ongoingDownloads.remove(info.id); + delete download; + } +} + +void QWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info) +{ + if (!m_ongoingDownloads.contains(info.id)) + return; + + QWebEngineDownloadItem* download = m_ongoingDownloads.value(info.id).data(); + + if (!download) { + downloadDestroyed(info.id); + return; + } + + download->d_func()->update(info); + + if (download->isFinished()) + m_ongoingDownloads.remove(info.id); +} + +/*! + Constructs a new off-the-record profile. + + An off-the-record profile leaves no record on the local machine, and has no persistent data or cache. + Thus, the HTTP cache can only be in memory and the cookies only be non-persistent, trying to change + these settings will have no effect. + + \sa isOffTheRecord() +*/ +QWebEngineProfile::QWebEngineProfile(QObject *parent) + : QObject(parent) + , d_ptr(new QWebEngineProfilePrivate(new BrowserContextAdapter(true), true)) +{ + d_ptr->q_ptr = this; +} + +/*! + Constructs a new profile with storage name \a storageName. + + The storage name must be unique. + + A disk-based QWebEngineProfile should be destroyed on or before application exit, otherwise the cache + and persistent data may not be fully flushed to disk. + + \sa storageName() +*/ +QWebEngineProfile::QWebEngineProfile(const QString &storageName, QObject *parent) + : QObject(parent) + , d_ptr(new QWebEngineProfilePrivate(new BrowserContextAdapter(storageName), true)) +{ + d_ptr->q_ptr = this; +} + +/*! \internal +*/ +QWebEngineProfile::QWebEngineProfile(QWebEngineProfilePrivate *privatePtr) + : d_ptr(privatePtr) +{ + d_ptr->q_ptr = this; +} + +/*! \internal +*/ +QWebEngineProfile::~QWebEngineProfile() +{ +} + +/*! + Returns the storage name for the profile. + + The storage name is used to give each profile that uses the disk separate subdirectories for persistent data and cache. +*/ +QString QWebEngineProfile::storageName() const +{ + const Q_D(QWebEngineProfile); + return d->browserContext()->storageName(); +} + +/*! + Returns true if this is an off-the-record profile that leaves no record on the computer. + + This will force cookies and HTTP cache to be in memory, but also force all other normally + persistent data to be stored in memory. +*/ +bool QWebEngineProfile::isOffTheRecord() const +{ + const Q_D(QWebEngineProfile); + return d->browserContext()->isOffTheRecord(); +} + +/*! + Returns the path used to store persistent data for the browser and web content. + + Persistent data includes persistent cookies, HTML5 local storage and visited links. + + By default this is below QStandardPaths::writableLocation(QStandardPaths::DataLocation) in a storage name specific directory. + + \sa setPersistentStoragePath(), storageName(), QStandardPaths::writableLocation() +*/ +QString QWebEngineProfile::persistentStoragePath() const +{ + const Q_D(QWebEngineProfile); + return d->browserContext()->dataPath(); +} + +/*! + Overrides the default path used to store persistent web engine data. + + If set to the null string, the default path is restored. + + \sa persistentStoragePath() +*/ +void QWebEngineProfile::setPersistentStoragePath(const QString &path) +{ + const Q_D(QWebEngineProfile); + d->browserContext()->setDataPath(path); +} + +/*! + Returns the path used for caches. + + By default this is below QStandardPaths::writableLocation(QStandardPaths::CacheLocation) in a storage name specific directory. + + \sa setCachePath(), storageName(), QStandardPaths::writableLocation() +*/ +QString QWebEngineProfile::cachePath() const +{ + const Q_D(QWebEngineProfile); + return d->browserContext()->cachePath(); +} + +/*! + Overrides the default path used for disk caches. + + If set to the null string, the default path is restored. + + \sa cachePath() +*/ +void QWebEngineProfile::setCachePath(const QString &path) +{ + Q_D(QWebEngineProfile); + d->browserContext()->setCachePath(path); +} + +/*! + Returns the user-agent string send with HTTP to identify the browser. + + \sa setHttpUserAgent() +*/ +QString QWebEngineProfile::httpUserAgent() const +{ + const Q_D(QWebEngineProfile); + return d->browserContext()->httpUserAgent(); +} + +/*! + Overrides the default user-agent string, setting it to \a userAgent. + + \sa httpUserAgent() +*/ +void QWebEngineProfile::setHttpUserAgent(const QString &userAgent) +{ + Q_D(QWebEngineProfile); + d->browserContext()->setHttpUserAgent(userAgent); +} + +/*! + Returns the type of HTTP cache used. + + If the profile is off-the-record MemoryHttpCache is returned. + + \sa setHttpCacheType(), cachePath() +*/ +QWebEngineProfile::HttpCacheType QWebEngineProfile::httpCacheType() const +{ + const Q_D(QWebEngineProfile); + return QWebEngineProfile::HttpCacheType(d->browserContext()->httpCacheType()); +} + +/*! + Sets the HTTP cache type to \a httpCacheType. + + \sa httpCacheType(), setCachePath() +*/ +void QWebEngineProfile::setHttpCacheType(QWebEngineProfile::HttpCacheType httpCacheType) +{ + Q_D(QWebEngineProfile); + d->browserContext()->setHttpCacheType(BrowserContextAdapter::HttpCacheType(httpCacheType)); +} + +/*! + Returns the current policy for persistent cookies. + + If the profile is off-the-record NoPersistentCookies is returned. + + \sa setPersistentCookiesPolicy() +*/ +QWebEngineProfile::PersistentCookiesPolicy QWebEngineProfile::persistentCookiesPolicy() const +{ + const Q_D(QWebEngineProfile); + return QWebEngineProfile::PersistentCookiesPolicy(d->browserContext()->persistentCookiesPolicy()); +} + +/*! + Sets the policy for persistent cookies to \a newPersistentCookiesPolicy. + + \sa persistentCookiesPolicy() +*/ +void QWebEngineProfile::setPersistentCookiesPolicy(QWebEngineProfile::PersistentCookiesPolicy newPersistentCookiesPolicy) +{ + Q_D(QWebEngineProfile); + d->browserContext()->setPersistentCookiesPolicy(BrowserContextAdapter::PersistentCookiesPolicy(newPersistentCookiesPolicy)); +} + +/*! + Returns the maximum size of the HTTP size. + + Will return 0 if the size is automatically controlled by QtWebEngine. + + \sa setHttpCacheMaximumSize(), httpCacheType() +*/ +int QWebEngineProfile::httpCacheMaximumSize() const +{ + const Q_D(QWebEngineProfile); + return d->browserContext()->httpCacheMaxSize(); +} + +/*! + Sets the maximum size of the HTTP cache to \a maxSize. + + Setting it to 0 means the size will be controlled automatically by QtWebEngine. + + \sa httpCacheMaximumSize(), setHttpCacheType() +*/ +void QWebEngineProfile::setHttpCacheMaximumSize(int maxSize) +{ + Q_D(QWebEngineProfile); + d->browserContext()->setHttpCacheMaxSize(maxSize); +} + +/*! + Clears all links from the visited links database. + + \sa clearVisitedLinks() +*/ +void QWebEngineProfile::clearAllVisitedLinks() +{ + Q_D(QWebEngineProfile); + d->browserContext()->visitedLinksManager()->deleteAllVisitedLinkData(); +} + +/*! + Clears the links in \a urls from the visited links database. + + \sa clearAllVisitedLinks() +*/ +void QWebEngineProfile::clearVisitedLinks(const QList<QUrl> &urls) +{ + Q_D(QWebEngineProfile); + d->browserContext()->visitedLinksManager()->deleteVisitedLinkDataForUrls(urls); +} + +/*! + Returns true if \a url is considered a visited link by this profile. +*/ +bool QWebEngineProfile::visitedLinksContainsUrl(const QUrl &url) const +{ + Q_D(const QWebEngineProfile); + return d->browserContext()->visitedLinksManager()->containsUrl(url); +} + +/*! + Returns the default profile. + + The default profile uses the storage name "Default". + + \sa storageName() +*/ +QWebEngineProfile *QWebEngineProfile::defaultProfile() +{ + static QWebEngineProfile profile(new QWebEngineProfilePrivate(BrowserContextAdapter::defaultContext(), false)); + return &profile; +} + +/*! + Returns the default settings for all pages in this profile. +*/ +QWebEngineSettings *QWebEngineProfile::settings() const +{ + const Q_D(QWebEngineProfile); + return d->settings(); +} + +QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h new file mode 100644 index 000000000..0908862e9 --- /dev/null +++ b/src/webenginewidgets/api/qwebengineprofile.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINEPROFILE_H +#define QWEBENGINEPROFILE_H + +#include "qtwebenginewidgetsglobal.h" + +#include <QObject> +#include <QScopedPointer> +#include <QString> + +QT_BEGIN_NAMESPACE + +class QObject; +class QUrl; +class QWebEngineDownloadItem; +class QWebEnginePage; +class QWebEnginePagePrivate; +class QWebEngineProfilePrivate; +class QWebEngineSettings; + +class QWEBENGINEWIDGETS_EXPORT QWebEngineProfile : public QObject { + Q_OBJECT +public: + explicit QWebEngineProfile(QObject *parent = 0); + explicit QWebEngineProfile(const QString &name, QObject *parent = 0); + virtual ~QWebEngineProfile(); + + enum HttpCacheType { + MemoryHttpCache, + DiskHttpCache + }; + + enum PersistentCookiesPolicy { + NoPersistentCookies, + AllowPersistentCookies, + ForcePersistentCookies + }; + + QString storageName() const; + bool isOffTheRecord() const; + + QString persistentStoragePath() const; + void setPersistentStoragePath(const QString &path); + + QString cachePath() const; + void setCachePath(const QString &path); + + QString httpUserAgent() const; + void setHttpUserAgent(const QString &userAgent); + + HttpCacheType httpCacheType() const; + void setHttpCacheType(QWebEngineProfile::HttpCacheType); + + PersistentCookiesPolicy persistentCookiesPolicy() const; + void setPersistentCookiesPolicy(QWebEngineProfile::PersistentCookiesPolicy); + + int httpCacheMaximumSize() const; + void setHttpCacheMaximumSize(int maxSize); + + void clearAllVisitedLinks(); + void clearVisitedLinks(const QList<QUrl> &urls); + bool visitedLinksContainsUrl(const QUrl &url) const; + + QWebEngineSettings *settings() const; + + static QWebEngineProfile *defaultProfile(); + +Q_SIGNALS: + void downloadRequested(QWebEngineDownloadItem *download); + +private: + Q_DECLARE_PRIVATE(QWebEngineProfile); + QWebEngineProfile(QWebEngineProfilePrivate *); + + friend class QWebEnginePagePrivate; + QScopedPointer<QWebEngineProfilePrivate> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEPROFILE_H diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h new file mode 100644 index 000000000..7c3d2a5e7 --- /dev/null +++ b/src/webenginewidgets/api/qwebengineprofile_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINEPROFILE_P_H +#define QWEBENGINEPROFILE_P_H + +#include "browser_context_adapter_client.h" +#include "qwebengineprofile.h" +#include <QMap> +#include <QPointer> + +class BrowserContextAdapter; + +QT_BEGIN_NAMESPACE + +class QWebEngineSettings; + +class QWebEngineProfilePrivate : public BrowserContextAdapterClient { +public: + Q_DECLARE_PUBLIC(QWebEngineProfile) + QWebEngineProfilePrivate(BrowserContextAdapter* browserContext, bool ownsContext); + ~QWebEngineProfilePrivate(); + + BrowserContextAdapter *browserContext() const { return m_browserContext; } + QWebEngineSettings *settings() const { return m_settings; } + + void cancelDownload(quint32 downloadId); + void downloadDestroyed(quint32 downloadId); + + void downloadRequested(DownloadItemInfo &info) Q_DECL_OVERRIDE; + void downloadUpdated(const DownloadItemInfo &info) Q_DECL_OVERRIDE; + +private: + QWebEngineProfile *q_ptr; + QWebEngineSettings *m_settings; + BrowserContextAdapter *m_browserContext; + QExplicitlySharedDataPointer<BrowserContextAdapter> m_browserContextRef; + QMap<quint32, QPointer<QWebEngineDownloadItem> > m_ongoingDownloads; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEPROFILE_P_H diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp index 729a09f56..e126a7e64 100644 --- a/src/webenginewidgets/api/qwebenginesettings.cpp +++ b/src/webenginewidgets/api/qwebenginesettings.cpp @@ -35,13 +35,14 @@ ****************************************************************************/ #include "qwebenginesettings.h" -#include "qwebenginesettings_p.h" -#include <QDebug> +#include "qwebengineprofile.h" +#include "web_engine_settings.h" -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE -static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::WebAttribute attribute) { +static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::WebAttribute attribute) +{ switch (attribute) { case QWebEngineSettings::AutoLoadImages: return WebEngineSettings::AutoLoadImages; @@ -74,144 +75,110 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web } } -Q_GLOBAL_STATIC(QList<QWebEngineSettingsPrivate*>, allSettings); - -QWebEngineSettingsPrivate::QWebEngineSettingsPrivate() - : coreSettings(new WebEngineSettings(this)) +QWebEngineSettings::QWebEngineSettings(QWebEngineSettings *parentSettings) + : d_ptr(new WebEngineSettings(parentSettings ? parentSettings->d_func() : 0)) { + Q_D(QWebEngineSettings); + d->scheduleApplyRecursively(); } -void QWebEngineSettingsPrivate::apply() +QWebEngineSettings::~QWebEngineSettings() { - coreSettings->scheduleApply(); - QWebEngineSettingsPrivate *globals = QWebEngineSettings::globalSettings()->d_func(); - Q_ASSERT((this == globals) != (allSettings->contains(this))); - if (this == globals) { - Q_FOREACH (QWebEngineSettingsPrivate *settings, *allSettings) - settings->coreSettings->scheduleApply(); - } } -void QWebEngineSettingsPrivate::initDefaults() +#if QT_DEPRECATED_SINCE(5, 5) +QWebEngineSettings *QWebEngineSettings::globalSettings() { - coreSettings->initDefaults(); -} - -WebEngineSettings *QWebEngineSettingsPrivate::fallbackSettings() const { - return QWebEngineSettings::globalSettings()->d_func()->coreSettings.data(); + return defaultSettings(); } +#endif -QWebEngineSettings *QWebEngineSettings::globalSettings() +QWebEngineSettings *QWebEngineSettings::defaultSettings() { - static QWebEngineSettings* globalSettings = 0; - if (!globalSettings) { - globalSettings = new QWebEngineSettings; - // globalSettings shouldn't be in that list. - allSettings->removeAll(globalSettings->d_func()); - globalSettings->d_func()->initDefaults(); - } - return globalSettings; + return QWebEngineProfile::defaultProfile()->settings(); } -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::StandardFont) == static_cast<int>(QWebEngineSettings::StandardFont), "The enum values must match"); -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::FixedFont) == static_cast<int>(QWebEngineSettings::FixedFont), "The enum values must match"); -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::SerifFont) == static_cast<int>(QWebEngineSettings::SerifFont), "The enum values must match"); -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::SansSerifFont) == static_cast<int>(QWebEngineSettings::SansSerifFont), "The enum values must match"); -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::CursiveFont) == static_cast<int>(QWebEngineSettings::CursiveFont), "The enum values must match"); -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::FantasyFont) == static_cast<int>(QWebEngineSettings::FantasyFont), "The enum values must match"); +ASSERT_ENUMS_MATCH(WebEngineSettings::StandardFont, QWebEngineSettings::StandardFont) +ASSERT_ENUMS_MATCH(WebEngineSettings::FixedFont, QWebEngineSettings::FixedFont) +ASSERT_ENUMS_MATCH(WebEngineSettings::SerifFont, QWebEngineSettings::SerifFont) +ASSERT_ENUMS_MATCH(WebEngineSettings::SansSerifFont, QWebEngineSettings::SansSerifFont) +ASSERT_ENUMS_MATCH(WebEngineSettings::CursiveFont, QWebEngineSettings::CursiveFont) +ASSERT_ENUMS_MATCH(WebEngineSettings::FantasyFont, QWebEngineSettings::FantasyFont) void QWebEngineSettings::setFontFamily(QWebEngineSettings::FontFamily which, const QString &family) { Q_D(QWebEngineSettings); - d->coreSettings->setFontFamily(static_cast<WebEngineSettings::FontFamily>(which), family); + d->setFontFamily(static_cast<WebEngineSettings::FontFamily>(which), family); } QString QWebEngineSettings::fontFamily(QWebEngineSettings::FontFamily which) const { - Q_D(const QWebEngineSettings); - return d->coreSettings->fontFamily(static_cast<WebEngineSettings::FontFamily>(which)); + return d_ptr->fontFamily(static_cast<WebEngineSettings::FontFamily>(which)); } void QWebEngineSettings::resetFontFamily(QWebEngineSettings::FontFamily which) { - Q_D(QWebEngineSettings); - d->coreSettings->resetFontFamily(static_cast<WebEngineSettings::FontFamily>(which)); + d_ptr->resetFontFamily(static_cast<WebEngineSettings::FontFamily>(which)); } -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::DefaultFixedFontSize) == static_cast<int>(QWebEngineSettings::DefaultFixedFontSize), "The enum values must match"); -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::DefaultFontSize) == static_cast<int>(QWebEngineSettings::DefaultFontSize), "The enum values must match"); -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::MinimumFontSize) == static_cast<int>(QWebEngineSettings::MinimumFontSize), "The enum values must match"); -Q_STATIC_ASSERT_X(static_cast<int>(WebEngineSettings::MinimumLogicalFontSize) == static_cast<int>(QWebEngineSettings::MinimumLogicalFontSize), "The enum values must match"); +ASSERT_ENUMS_MATCH(WebEngineSettings::DefaultFixedFontSize, QWebEngineSettings::DefaultFixedFontSize) +ASSERT_ENUMS_MATCH(WebEngineSettings::DefaultFontSize, QWebEngineSettings::DefaultFontSize) +ASSERT_ENUMS_MATCH(WebEngineSettings::MinimumFontSize, QWebEngineSettings::MinimumFontSize) +ASSERT_ENUMS_MATCH(WebEngineSettings::MinimumLogicalFontSize, QWebEngineSettings::MinimumLogicalFontSize) void QWebEngineSettings::setFontSize(QWebEngineSettings::FontSize type, int size) { - Q_D(const QWebEngineSettings); - d->coreSettings->setFontSize(static_cast<WebEngineSettings::FontSize>(type), size); + Q_D(QWebEngineSettings); + d->setFontSize(static_cast<WebEngineSettings::FontSize>(type), size); } int QWebEngineSettings::fontSize(QWebEngineSettings::FontSize type) const { Q_D(const QWebEngineSettings); - return d->coreSettings->fontSize(static_cast<WebEngineSettings::FontSize>(type)); + return d->fontSize(static_cast<WebEngineSettings::FontSize>(type)); } void QWebEngineSettings::resetFontSize(QWebEngineSettings::FontSize type) { Q_D(QWebEngineSettings); - d->coreSettings->resetFontSize(static_cast<WebEngineSettings::FontSize>(type)); -} - - -QWebEngineSettings::QWebEngineSettings() - : d_ptr(new QWebEngineSettingsPrivate) -{ - Q_D(QWebEngineSettings); - allSettings->append(d); - d->coreSettings->scheduleApply(); + d->resetFontSize(static_cast<WebEngineSettings::FontSize>(type)); } -QWebEngineSettings::~QWebEngineSettings() -{ - Q_D(QWebEngineSettings); - allSettings->removeAll(d); -} - void QWebEngineSettings::setDefaultTextEncoding(const QString &encoding) { Q_D(QWebEngineSettings); - d->coreSettings->setDefaultTextEncoding(encoding); + d->setDefaultTextEncoding(encoding); } QString QWebEngineSettings::defaultTextEncoding() const { Q_D(const QWebEngineSettings); - return d->coreSettings->defaultTextEncoding(); + return d->defaultTextEncoding(); } void QWebEngineSettings::setAttribute(QWebEngineSettings::WebAttribute attr, bool on) { Q_D(QWebEngineSettings); WebEngineSettings::Attribute webEngineAttribute = toWebEngineAttribute(attr); - if (webEngineAttribute != WebEngineSettings::UnsupportedInCoreSettings) - return d->coreSettings->setAttribute(webEngineAttribute, on); - qDebug() << Q_FUNC_INFO << "Missing support for:" << attr; + Q_ASSERT(webEngineAttribute != WebEngineSettings::UnsupportedInCoreSettings); + d->setAttribute(webEngineAttribute, on); } bool QWebEngineSettings::testAttribute(QWebEngineSettings::WebAttribute attr) const { Q_D(const QWebEngineSettings); WebEngineSettings::Attribute webEngineAttribute = toWebEngineAttribute(attr); - if (webEngineAttribute != WebEngineSettings::UnsupportedInCoreSettings) - return d->coreSettings->testAttribute(webEngineAttribute); - - - - qDebug() << Q_FUNC_INFO << "Missing support for:" << attr; - return false; + Q_ASSERT(webEngineAttribute != WebEngineSettings::UnsupportedInCoreSettings); + return d->testAttribute(webEngineAttribute); } void QWebEngineSettings::resetAttribute(QWebEngineSettings::WebAttribute attr) { - setAttribute(attr, globalSettings()->testAttribute(attr)); + Q_D(QWebEngineSettings); + WebEngineSettings::Attribute webEngineAttribute = toWebEngineAttribute(attr); + Q_ASSERT(webEngineAttribute != WebEngineSettings::UnsupportedInCoreSettings); + d->resetAttribute(webEngineAttribute); } + +QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h index d9f57a935..48cc3107c 100644 --- a/src/webenginewidgets/api/qwebenginesettings.h +++ b/src/webenginewidgets/api/qwebenginesettings.h @@ -25,12 +25,13 @@ #include <QtCore/qscopedpointer.h> #include <QtCore/qstring.h> +class WebEngineSettings; + QT_BEGIN_NAMESPACE class QIcon; class QPixmap; class QUrl; -class QWebEngineSettingsPrivate; class QWEBENGINEWIDGETS_EXPORT QWebEngineSettings { public: @@ -65,7 +66,10 @@ public: DefaultFixedFontSize }; +#if QT_DEPRECATED_SINCE(5, 5) static QWebEngineSettings *globalSettings(); +#endif + static QWebEngineSettings *defaultSettings(); void setFontFamily(FontFamily which, const QString &family); QString fontFamily(FontFamily which) const; @@ -84,12 +88,15 @@ public: private: Q_DISABLE_COPY(QWebEngineSettings) - Q_DECLARE_PRIVATE(QWebEngineSettings); + typedef WebEngineSettings QWebEngineSettingsPrivate; + QWebEngineSettingsPrivate* d_func() { return d_ptr.data(); } + const QWebEngineSettingsPrivate* d_func() const { return d_ptr.data(); } QScopedPointer<QWebEngineSettingsPrivate> d_ptr; friend class QWebEnginePagePrivate; + friend class QWebEngineProfilePrivate; - QWebEngineSettings(); ~QWebEngineSettings(); + explicit QWebEngineSettings(QWebEngineSettings *parentSettings = 0); }; QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 8d2198998..63ac40571 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -85,19 +85,22 @@ void QWebEngineViewPrivate::bind(QWebEngineView *view, QWebEnginePage *page) } } - +#ifndef QT_NO_ACCESSIBILITY static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *object) { if (QWebEngineView *v = qobject_cast<QWebEngineView*>(object)) return new QWebEngineViewAccessible(v); return Q_NULLPTR; } +#endif // QT_NO_ACCESSIBILITY QWebEngineViewPrivate::QWebEngineViewPrivate() : page(0) , m_pendingContextMenuEvent(false) { +#ifndef QT_NO_ACCESSIBILITY QAccessible::installFactory(&webAccessibleFactory); +#endif // QT_NO_ACCESSIBILITY } QWebEngineView::QWebEngineView(QWidget *parent) @@ -274,6 +277,7 @@ void QWebEngineView::contextMenuEvent(QContextMenuEvent *event) menu->popup(event->globalPos()); } +#ifndef QT_NO_ACCESSIBILITY int QWebEngineViewAccessible::childCount() const { if (view() && child(0)) @@ -294,6 +298,7 @@ int QWebEngineViewAccessible::indexOfChild(const QAccessibleInterface *c) const return 0; return -1; } +#endif // QT_NO_ACCESSIBILITY QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebengineview_p.h b/src/webenginewidgets/api/qwebengineview_p.h index 9db971f79..e0cc3f4ee 100644 --- a/src/webenginewidgets/api/qwebengineview_p.h +++ b/src/webenginewidgets/api/qwebengineview_p.h @@ -59,6 +59,7 @@ public: bool m_pendingContextMenuEvent; }; +#ifndef QT_NO_ACCESSIBILITY class QWebEngineViewAccessible : public QAccessibleWidget { public: @@ -72,7 +73,7 @@ public: private: QWebEngineView *view() const { return static_cast<QWebEngineView*>(object()); } }; - +#endif // QT_NO_ACCESSIBILITY QT_END_NAMESPACE diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index e89b10ab8..e23fc6f7c 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -147,10 +147,26 @@ */ /*! + \enum QWebEnginePage::NavigationType + + This enum describes the type of a navigation request. + + \value NavigationTypeLinkClicked The navigation request resulted from a clicked link. + \value NavigationTypeTyped The navigation request resulted from an explicitly loaded url. + \value NavigationTypeFormSubmitted The navigation request resulted from a form submission. + \value NavigationTypeBackForward The navigation request resulted from a back/forward action. + \value NavigationTypeReload The navigation request resulted from a reload action. + \value NavigationTypeOther The navigation request was triggered by other means not covered by the above. + + \sa acceptNavigationRequest() +*/ + +/*! \enum QWebEnginePage::Feature This enum describes the platform feature access categories that the user may be asked to grant or deny access to. + \value Geolocation Access to location hardware or service \value MediaAudioCapture Audio capture devices such a microphones \value MediaVideoCapture Video devices, e.g. cameras \value MediaAudioVideoCapture Both Audio and Video capture devices. @@ -209,6 +225,15 @@ */ /*! + \fn bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) + This function is called whenever there is a request to navigate to a specified \a url by means of the specified navigation type \atype. + The \a isMainFrame argument marks if the request corresponds to the main frame, or a sub frame. + If the request is accepted Chromium will continue to load the page, else the request will be ignored. + The default implementation accepts the navigation request. +*/ + + +/*! \fn void QWebEnginePage::javaScriptAlert(const QUrl &securityOrigin, const QString& msg) This function is called whenever a JavaScript program running in a frame affiliated with \a securityOrigin calls the alert() function with the message \a msg. diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp index c4a32d685..3880e4197 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -44,9 +44,11 @@ #include <QOpenGLContext> #include <QResizeEvent> #include <QSGAbstractRenderer> -#include <QSGEngine> #include <QSGNode> #include <QWindow> +#include <private/qsgcontext_p.h> +#include <private/qsgengine_p.h> + static const int MaxTooltipLength = 1024; @@ -119,6 +121,16 @@ bool RenderWidgetHostViewQtDelegateWidget::hasKeyboardFocus() return hasFocus(); } +void RenderWidgetHostViewQtDelegateWidget::lockMouse() +{ + grabMouse(); +} + +void RenderWidgetHostViewQtDelegateWidget::unlockMouse() +{ + releaseMouse(); +} + void RenderWidgetHostViewQtDelegateWidget::show() { // Check if we're attached to a QWebEngineView, we don't @@ -143,6 +155,22 @@ QWindow* RenderWidgetHostViewQtDelegateWidget::window() const return root ? root->windowHandle() : 0; } +QSGTexture *RenderWidgetHostViewQtDelegateWidget::createTextureFromImage(const QImage &image) +{ + return m_sgEngine->createTextureFromImage(image, QSGEngine::TextureCanUseAtlas); +} + +QSGLayer *RenderWidgetHostViewQtDelegateWidget::createLayer() +{ + QSGEnginePrivate *enginePrivate = QSGEnginePrivate::get(m_sgEngine.data()); + return enginePrivate->sgContext->createLayer(enginePrivate->sgRenderContext.data()); +} + +QSGImageNode *RenderWidgetHostViewQtDelegateWidget::createImageNode() +{ + return QSGEnginePrivate::get(m_sgEngine.data())->sgContext->createImageNode(); +} + void RenderWidgetHostViewQtDelegateWidget::update() { #if (QT_VERSION < QT_VERSION_CHECK(5, 4, 0)) diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h index 0b553d8eb..8fc189124 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h @@ -61,10 +61,15 @@ public: virtual QRectF contentsRect() const Q_DECL_OVERRIDE; virtual void setKeyboardFocus() Q_DECL_OVERRIDE; virtual bool hasKeyboardFocus() Q_DECL_OVERRIDE; + virtual void lockMouse() Q_DECL_OVERRIDE; + virtual void unlockMouse() Q_DECL_OVERRIDE; virtual void show() Q_DECL_OVERRIDE; virtual void hide() Q_DECL_OVERRIDE; virtual bool isVisible() const Q_DECL_OVERRIDE; virtual QWindow* window() const Q_DECL_OVERRIDE; + virtual QSGTexture *createTextureFromImage(const QImage &) Q_DECL_OVERRIDE; + virtual QSGLayer *createLayer() Q_DECL_OVERRIDE; + virtual QSGImageNode *createImageNode() Q_DECL_OVERRIDE; virtual void update() Q_DECL_OVERRIDE; virtual void updateCursor(const QCursor &) Q_DECL_OVERRIDE; virtual void resize(int width, int height) Q_DECL_OVERRIDE; diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro index 4da888baa..82908bfd0 100644 --- a/src/webenginewidgets/webenginewidgets.pro +++ b/src/webenginewidgets/webenginewidgets.pro @@ -4,7 +4,7 @@ TARGET = QtWebEngineWidgets DEFINES += QT_BUILD_WEBENGINEWIDGETS_LIB QT += webengine widgets network quick -QT_PRIVATE += webenginecore +QT_PRIVATE += webenginecore quick-private gui-private core-private QMAKE_DOCS = $$PWD/doc/qtwebenginewidgets.qdocconf @@ -13,20 +13,25 @@ INCLUDEPATH += $$PWD api ../core ../webengine/api SOURCES = \ api/qtwebenginewidgetsglobal.cpp \ api/qwebenginecertificateerror.cpp \ + api/qwebenginedownloaditem.cpp \ api/qwebenginehistory.cpp \ api/qwebenginepage.cpp \ + api/qwebengineprofile.cpp \ api/qwebenginesettings.cpp \ - api/qwebengineview.cpp\ + api/qwebengineview.cpp \ render_widget_host_view_qt_delegate_widget.cpp HEADERS = \ api/qtwebenginewidgetsglobal.h \ + api/qwebenginedownloaditem.h \ + api/qwebenginedownloaditem_p.h \ api/qwebenginecertificateerror.h \ api/qwebenginehistory.h \ api/qwebenginepage.h \ api/qwebenginepage_p.h \ + api/qwebengineprofile.h \ + api/qwebengineprofile_p.h \ api/qwebenginesettings.h \ - api/qwebenginesettings_p.h \ api/qwebengineview.h \ api/qwebengineview_p.h \ render_widget_host_view_qt_delegate_widget.h |