diff options
Diffstat (limited to 'src/core')
120 files changed, 6113 insertions, 799 deletions
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro new file mode 100644 index 000000000..e4cdf43cb --- /dev/null +++ b/src/core/api/core_api.pro @@ -0,0 +1,56 @@ +TARGET = qtwebenginecoreapi$$qtPlatformTargetSuffix() +DESTDIR = $$OUT_PWD/$$getConfigDir() + +TEMPLATE = lib + +CONFIG += staticlib c++11 +QT += network + +# Don't create .prl file for this intermediate library because +# their contents get used when linking against them, breaking +# "-Wl,-whole-archive -lqtwebenginecoreapi --Wl,-no-whole-archive" +CONFIG -= create_prl + +# Copy this logic from qt_module.prf so that the intermediate library can be +# created to the same rules as the final module linking in core_module.pro. +!host_build:if(win32|mac):!macx-xcode { + contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release + contains(QT_CONFIG, build_all):CONFIG += build_all +} + +DEFINES += \ + BUILDING_CHROMIUM \ + NOMINMAX + +CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir() +INCLUDEPATH += $$QTWEBENGINE_ROOT/src/core \ + $$CHROMIUM_SRC_DIR + +linux-g++*: QMAKE_CXXFLAGS += -Wno-unused-parameter + +HEADERS = \ + qwebenginecallback.h \ + qwebenginecallback_p.h \ + qtwebenginecoreglobal.h \ + qtwebenginecoreglobal_p.h \ + qwebenginecookiestoreclient.h \ + qwebenginecookiestoreclient_p.h \ + qwebengineurlrequestinterceptor.h \ + qwebengineurlrequestinfo.h \ + qwebengineurlrequestinfo_p.h \ + qwebengineurlrequestjob.h \ + qwebengineurlschemehandler.h + +SOURCES = \ + qwebenginecookiestoreclient.cpp \ + qwebengineurlrequestinfo.cpp \ + qwebengineurlrequestjob.cpp \ + qwebengineurlschemehandler.cpp + +msvc { + # Create a list of object files that can be used as response file for the linker. + # This is done to simulate -whole-archive on MSVC. + QMAKE_POST_LINK = \ + "if exist $(DESTDIR_TARGET).objects del $(DESTDIR_TARGET).objects$$escape_expand(\\n\\t)" \ + "for %%a in ($(OBJECTS)) do echo $$shell_quote($$shell_path($$OUT_PWD))\\%%a >> $(DESTDIR_TARGET).objects" +} diff --git a/src/core/api/qtwebenginecoreglobal.h b/src/core/api/qtwebenginecoreglobal.h new file mode 100644 index 000000000..16daaab7d --- /dev/null +++ b/src/core/api/qtwebenginecoreglobal.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QTWEBENGINECOREGLOBAL_H +#define QTWEBENGINECOREGLOBAL_H + +#include <QtCore/qglobal.h> + +#if defined(BUILDING_CHROMIUM) +# define QWEBENGINE_EXPORT Q_DECL_EXPORT +#else +# define QWEBENGINE_EXPORT Q_DECL_IMPORT +#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/qtwebenginecoreglobal.h b/src/core/api/qtwebenginecoreglobal_p.h index d09497ce8..e93ca9c2c 100644 --- a/src/core/qtwebenginecoreglobal.h +++ b/src/core/api/qtwebenginecoreglobal_p.h @@ -34,10 +34,21 @@ ** ****************************************************************************/ -#ifndef QTWEBENGINECOREGLOBAL_H -#define QTWEBENGINECOREGLOBAL_H +#ifndef QTWEBENGINECOREGLOBAL_P_H +#define QTWEBENGINECOREGLOBAL_P_H -#include <QtCore/qglobal.h> +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtwebenginecoreglobal.h" #ifdef QT_WEBENGINE_LOGGING #define QT_NOT_YET_IMPLEMENTED fprintf(stderr, "function %s not implemented! - %s:%d\n", __func__, __FILE__, __LINE__); @@ -47,16 +58,6 @@ #define QT_NOT_USED Q_UNREACHABLE(); // This will assert in debug. #endif -#ifndef QT_STATIC -# if defined(BUILDING_CHROMIUM) -# define QWEBENGINE_EXPORT Q_DECL_EXPORT -# else -# define QWEBENGINE_EXPORT Q_DECL_IMPORT -# endif -#else -# define QWEBENGINE_EXPORT -#endif - -#define ASSERT_ENUMS_MATCH(A, B) Q_STATIC_ASSERT_X(static_cast<int>(A) == static_cast<int>(B), "The enum values must match"); +#define QWEBENGINE_PRIVATE_EXPORT QWEBENGINE_EXPORT -#endif // QTWEBENGINECOREGLOBAL_H +#endif // QTWEBENGINECOREGLOBAL_P_H diff --git a/src/core/api/qwebenginecallback.h b/src/core/api/qwebenginecallback.h new file mode 100644 index 000000000..ddee20d06 --- /dev/null +++ b/src/core/api/qwebenginecallback.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QWEBENGINECALLBACK_H +#define QWEBENGINECALLBACK_H + +#include "qtwebenginecoreglobal.h" + +#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE +#include <QtCore/qshareddata.h> +#include <QtCore/qstring.h> +#include <QtCore/qvariant.h> + +namespace QtWebEngineCore { +class CallbackDirectory; +} + +QT_BEGIN_NAMESPACE + +namespace QtWebEnginePrivate { + +template <typename T> +class QWebEngineCallbackPrivateBase : public QSharedData { +public: + QWebEngineCallbackPrivateBase() {} + virtual ~QWebEngineCallbackPrivateBase() {} + virtual void operator()(T) = 0; +}; + +template <typename T, typename F> +class QWebEngineCallbackPrivate : public QWebEngineCallbackPrivateBase<T> { +public: + QWebEngineCallbackPrivate(F callable) + : m_callable(callable) + {} + virtual void operator()(T value) Q_DECL_OVERRIDE { m_callable(value); } +private: + F m_callable; +}; + +} // namespace QtWebEnginePrivate + +template <typename T> +class QWebEngineCallback { +public: + template <typename F> + QWebEngineCallback(F f) + : d(new QtWebEnginePrivate::QWebEngineCallbackPrivate<T, F>(f)) + { } + QWebEngineCallback() { } + operator bool() const { return d; } +private: + friend class QtWebEngineCore::CallbackDirectory; + QExplicitlySharedDataPointer<QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> > d; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINECALLBACK_H diff --git a/src/core/api/qwebenginecallback_p.h b/src/core/api/qwebenginecallback_p.h new file mode 100644 index 000000000..f0c25fe9e --- /dev/null +++ b/src/core/api/qwebenginecallback_p.h @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QWEBENGINECALLBACK_P_H +#define QWEBENGINECALLBACK_P_H + +#include "qtwebenginecoreglobal_p.h" +#include "qwebenginecallback.h" + +#include <QByteArray> +#include <QHash> +#include <QSharedData> +#include <QString> +#include <QVariant> +#include <type_traits> + +#define FOR_EACH_TYPE(F) \ + F(bool) \ + F(int) \ + F(const QString &) \ + F(const QByteArray &) \ + F(const QVariant &) + +namespace QtWebEngineCore { + +class CallbackDirectory { + template<typename T> + void invokeInternal(quint64 callbackId, T result); + template<typename T> + void invokeEmptyInternal(QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> *callback); + +public: + ~CallbackDirectory() + { + // "Cancel" pending callbacks by calling them with an invalid value. + // This guarantees that each callback is called exactly once. + for (CallbackSharedDataPointerBase * const sharedPtrBase: m_callbackMap) { + Q_ASSERT(sharedPtrBase); + sharedPtrBase->invokeEmpty(); + delete sharedPtrBase; + } + } + + enum ReservedCallbackIds { + NoCallbackId = 0, + DeleteCookieCallbackId, + DeleteSessionCookiesCallbackId, + DeleteAllCookiesCallbackId, + GetAllCookiesCallbackId, + + // Place reserved id's before this. + ReservedCallbackIdsEnd + }; + + template<typename T> + void registerCallback(quint64 callbackId, const QWebEngineCallback<T> &callback); + + template<typename T> + void invokeEmpty(const QWebEngineCallback<T> &callback); + +#define DEFINE_INVOKE_FOR_TYPE(Type) \ + void invoke(quint64 callbackId, Type result) { \ + invokeInternal<Type>(callbackId, std::forward<Type>(result)); \ + } + FOR_EACH_TYPE(DEFINE_INVOKE_FOR_TYPE) +#undef DEFINE_INVOKE_FOR_TYPE + + template <typename A> + void invokeDirectly(const QWebEngineCallback<A> &callback, const A &argument) + { + return callback.d.data()->operator()(std::forward<const A&>(argument)); + } + +private: + struct CallbackSharedDataPointerBase { + virtual ~CallbackSharedDataPointerBase() { } + virtual void invokeEmpty() = 0; + virtual void doRef() = 0; + virtual void doDeref() = 0; + virtual operator bool () const = 0; + }; + + template <typename T> + struct CallbackSharedDataPointer : public CallbackSharedDataPointerBase { + CallbackDirectory* parent; + QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> *callback; + + ~CallbackSharedDataPointer() { doDeref(); } + CallbackSharedDataPointer() : parent(0), callback(0) { } + CallbackSharedDataPointer(const CallbackSharedDataPointer<T> &other) + : parent(other.parent), callback(other.callback) { doRef(); } + CallbackSharedDataPointer(CallbackDirectory *p, QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> *c) + : parent(p), callback(c) { Q_ASSERT(callback); doRef(); } + + void invokeEmpty() override; + operator bool () const override { return callback; } + + private: + void doRef() override; + void doDeref() override; + }; + + QHash<quint64, CallbackSharedDataPointerBase*> m_callbackMap; +}; + +template<typename T> +inline +void CallbackDirectory::registerCallback(quint64 callbackId, const QWebEngineCallback<T> &callback) +{ + if (!callback.d) + return; + m_callbackMap.insert(callbackId, new CallbackSharedDataPointer<T>(this, callback.d.data())); +} + +template<typename T> +inline +void CallbackDirectory::invokeInternal(quint64 callbackId, T result) +{ + CallbackSharedDataPointerBase * const sharedPtrBase = m_callbackMap.take(callbackId); + if (!sharedPtrBase) + return; + + auto ptr = static_cast<CallbackSharedDataPointer<T> *>(sharedPtrBase); + Q_ASSERT(ptr); + (*ptr->callback)(std::forward<T>(result)); + delete ptr; +} + +template<typename T> +inline +void CallbackDirectory::invokeEmptyInternal(QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> *callback) +{ + Q_ASSERT(callback); + using NoRefT = typename std::remove_reference<T>::type; + using NoConstNoRefT = typename std::remove_const<NoRefT>::type; + NoConstNoRefT t; + (*callback)(t); +} + +template<> +inline +void CallbackDirectory::invokeEmptyInternal(QtWebEnginePrivate::QWebEngineCallbackPrivateBase<bool> *callback) +{ + Q_ASSERT(callback); + (*callback)(false); +} + +template<> +inline +void CallbackDirectory::invokeEmptyInternal(QtWebEnginePrivate::QWebEngineCallbackPrivateBase<int> *callback) +{ + Q_ASSERT(callback); + (*callback)(0); +} + +template<typename T> +inline +void CallbackDirectory::invokeEmpty(const QWebEngineCallback<T> &callback) +{ + if (!callback.d) + return; + + invokeEmptyInternal(callback.d.data()); +} + +template <typename T> +inline +void CallbackDirectory::CallbackSharedDataPointer<T>::doRef() +{ + if (!callback) + return; + + callback->ref.ref(); +} + +template <typename T> +inline +void CallbackDirectory::CallbackSharedDataPointer<T>::doDeref() +{ + if (!callback) + return; + if (!callback->ref.deref()) + delete callback; +} + +template <typename T> +inline +void CallbackDirectory::CallbackSharedDataPointer<T>::invokeEmpty() +{ + if (!callback) + return; + + Q_ASSERT(parent); + parent->invokeEmptyInternal(callback); +} + +} // namespace QtWebEngineCore + +#endif // QWEBENGINECALLBACK_P_H diff --git a/src/core/api/qwebenginecookiestoreclient.cpp b/src/core/api/qwebenginecookiestoreclient.cpp new file mode 100644 index 000000000..bd43b871d --- /dev/null +++ b/src/core/api/qwebenginecookiestoreclient.cpp @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "qwebenginecookiestoreclient.h" +#include "qwebenginecookiestoreclient_p.h" + +#include <cookie_monster_delegate_qt.h> + +#include <QByteArray> +#include <QUrl> + +QT_BEGIN_NAMESPACE + +using namespace QtWebEngineCore; + +QWebEngineCookieStoreClientPrivate::QWebEngineCookieStoreClientPrivate(QWebEngineCookieStoreClient* q) + : m_nextCallbackId(CallbackDirectory::ReservedCallbackIdsEnd) + , m_deleteSessionCookiesPending(false) + , m_deleteAllCookiesPending(false) + , m_getAllCookiesPending(false) + , delegate(0) + , q_ptr(q) +{ +} + +QWebEngineCookieStoreClientPrivate::~QWebEngineCookieStoreClientPrivate() +{ + +} + +void QWebEngineCookieStoreClientPrivate::processPendingUserCookies() +{ + Q_ASSERT(delegate); + Q_ASSERT(delegate->hasCookieMonster()); + + if (m_getAllCookiesPending) { + m_getAllCookiesPending = false; + delegate->getAllCookies(CallbackDirectory::GetAllCookiesCallbackId); + } + + if (m_deleteAllCookiesPending) { + m_deleteAllCookiesPending = false; + delegate->deleteAllCookies(CallbackDirectory::DeleteAllCookiesCallbackId); + } + + if (m_deleteSessionCookiesPending) { + m_deleteSessionCookiesPending = false; + delegate->deleteSessionCookies(CallbackDirectory::DeleteSessionCookiesCallbackId); + } + + if (m_pendingUserCookies.isEmpty()) + return; + + Q_FOREACH (const auto &cookieData, m_pendingUserCookies) { + if (cookieData.callbackId == CallbackDirectory::DeleteCookieCallbackId) + delegate->deleteCookie(cookieData.cookie, cookieData.origin); + else + delegate->setCookie(cookieData.callbackId, cookieData.cookie, cookieData.origin); + } + + m_pendingUserCookies.clear(); +} + +void QWebEngineCookieStoreClientPrivate::setCookie(const QWebEngineCallback<bool> &callback, const QNetworkCookie &cookie, const QUrl &origin) +{ + const quint64 currentCallbackId = callback ? m_nextCallbackId++ : static_cast<quint64>(CallbackDirectory::NoCallbackId); + + if (currentCallbackId != CallbackDirectory::NoCallbackId) + callbackDirectory.registerCallback(currentCallbackId, callback); + + if (!delegate || !delegate->hasCookieMonster()) { + m_pendingUserCookies.append(CookieData{ currentCallbackId, cookie, origin }); + return; + } + + delegate->setCookie(currentCallbackId, cookie, origin); +} + +void QWebEngineCookieStoreClientPrivate::deleteCookie(const QNetworkCookie &cookie, const QUrl &url) +{ + if (!delegate || !delegate->hasCookieMonster()) { + m_pendingUserCookies.append(CookieData{ CallbackDirectory::DeleteCookieCallbackId, cookie, url }); + return; + } + + delegate->deleteCookie(cookie, url); +} + +void QWebEngineCookieStoreClientPrivate::deleteSessionCookies() +{ + if (!delegate || !delegate->hasCookieMonster()) { + m_deleteSessionCookiesPending = true; + return; + } + + delegate->deleteSessionCookies(CallbackDirectory::DeleteSessionCookiesCallbackId); +} + +void QWebEngineCookieStoreClientPrivate::deleteAllCookies() +{ + if (!delegate || !delegate->hasCookieMonster()) { + m_deleteAllCookiesPending = true; + m_deleteSessionCookiesPending = false; + return; + } + + delegate->deleteAllCookies(CallbackDirectory::DeleteAllCookiesCallbackId); +} + +void QWebEngineCookieStoreClientPrivate::getAllCookies() +{ + if (!delegate || !delegate->hasCookieMonster()) { + m_getAllCookiesPending = true; + return; + } + + delegate->getAllCookies(CallbackDirectory::GetAllCookiesCallbackId); +} + +void QWebEngineCookieStoreClientPrivate::onGetAllCallbackResult(qint64 callbackId, const QByteArray &cookieList) +{ + callbackDirectory.invoke(callbackId, cookieList); +} +void QWebEngineCookieStoreClientPrivate::onSetCallbackResult(qint64 callbackId, bool success) +{ + callbackDirectory.invoke(callbackId, success); +} + +void QWebEngineCookieStoreClientPrivate::onDeleteCallbackResult(qint64 callbackId, int numCookies) +{ + callbackDirectory.invoke(callbackId, numCookies); +} + +void QWebEngineCookieStoreClientPrivate::onCookieChanged(const QNetworkCookie &cookie, bool removed) +{ + Q_Q(QWebEngineCookieStoreClient); + if (removed) + Q_EMIT q->cookieRemoved(cookie); + else + Q_EMIT q->cookieAdded(cookie); +} + +bool QWebEngineCookieStoreClientPrivate::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) +{ + if (filterCallback) { + QWebEngineCookieStoreClient::FilterRequest request; + request.accepted = true; + request.firstPartyUrl = firstPartyUrl; + request.cookieLine = cookieLine; + request.cookieSource = url; + callbackDirectory.invokeDirectly<QWebEngineCookieStoreClient::FilterRequest&>(filterCallback, request); + return request.accepted; + } + return true; +} + +/*! + \class QWebEngineCookieStoreClient + \inmodule QtWebEngineCore + \since 5.6 + \brief The QWebEngineCookieStoreClient class provides access to Chromium's cookies. + + The class allows to access HTTP cookies of Chromium for a specific profile. + It can be used to synchronize cookies of Chromium and the QNetworkAccessManager, as well as + to set, delete, and intercept cookies during navigation. + Because cookie operations are asynchronous, the user can choose to provide a callback function + to get notified about the success of the operation. + The signal handlers for removal and addition should not be used to execute heavy tasks, + because they might block the IO thread in case of a blocking connection. +*/ + +/*! + \class QWebEngineCookieStoreClient::FilterRequest + \inmodule QtWebEngineCore + \since 5.6 + + The structure specifies properties of a cookie, and whether it should accepted or not. It is + used as an argument to a filter installed via setCookieFilter(). +*/ + +/*! + \variable QWebEngineCookieStoreClient::FilterRequest::accepted + Whether the cookie shall be accepted. The default is \c true. + \variable QWebEngineCookieStoreClient::FilterRequest::firstPartyUrl + URL of page that triggered the setting of the cookie. + \variable QWebEngineCookieStoreClient::FilterRequest::cookieLine + Content of the cookie. + \variable QWebEngineCookieStoreClient::FilterRequest::cookieSource + URL of site that sets the cookie. +*/ + + +/*! + \fn void QWebEngineCookieStoreClient::cookieAdded(const QNetworkCookie &cookie) + + This signal is emitted whenever a new \a cookie is added to the cookie store. +*/ + +/*! + \fn void QWebEngineCookieStoreClient::cookieRemoved(const QNetworkCookie &cookie) + + This signal is emitted whenever a \a cookie is deleted from the cookie store. +*/ + +/*! + Creates a new QWebEngineCookieStoreClient object with \a parent. +*/ + +QWebEngineCookieStoreClient::QWebEngineCookieStoreClient(QObject *parent) + : QObject(parent) + , d_ptr(new QWebEngineCookieStoreClientPrivate(this)) +{ + +} + +/*! + Destroys this QWebEngineCookieStoreClient object. +*/ + +QWebEngineCookieStoreClient::~QWebEngineCookieStoreClient() +{ + +} + +/*! + \fn void setCookieWithCallback(const QNetworkCookie &cookie, FunctorOrLambda resultCallback, const QUrl &origin = QUrl()) + + Adds \a cookie to the cookie store. When the operation finishes, \a resultCallback will be executed + on the caller thread. + It is possible to provide an optional \a origin URL argument to limit the scope of the cookie. + The provided URL should also include the scheme. + + \sa setCookie() +*/ + +void QWebEngineCookieStoreClient::setCookieWithCallback(const QNetworkCookie &cookie, const QWebEngineCallback<bool> &resultCallback, const QUrl &origin) +{ + Q_D(QWebEngineCookieStoreClient); + d->setCookie(resultCallback, cookie, origin); +} + +/*! + Adds \a cookie to the cookie store. This function is provided for convenience and is + equivalent to calling setCookieWithCallback() with an empty callback. + It is possible to provide an optional \a origin URL argument to limit the scope of the cookie. + The provided URL should also include the scheme. + + \sa setCookieWithCallback() +*/ + +void QWebEngineCookieStoreClient::setCookie(const QNetworkCookie &cookie, const QUrl &origin) +{ + setCookieWithCallback(cookie, QWebEngineCallback<bool>(), origin); +} + +/*! + Deletes \a cookie from the cookie store. + It is possible to provide an optional \a origin URL argument to limit the scope of the + cookie to be deleted. + The provided URL should also include the scheme. +*/ + +void QWebEngineCookieStoreClient::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin) +{ + Q_D(QWebEngineCookieStoreClient); + d->deleteCookie(cookie, origin); +} + +/*! + \fn void QWebEngineCookieStoreClient::getAllCookies(FunctorOrLambda resultCallback) + + Requests all the cookies in the cookie store. When the asynchronous operation finishes, + \a resultCallback will be called with a QByteArray as the argument containing the cookies. + This QByteArray can be parsed using QNetworkCookie::parseCookies(). + + \sa deleteCookie() +*/ + +void QWebEngineCookieStoreClient::getAllCookies(const QWebEngineCallback<const QByteArray&> &resultCallback) +{ + Q_D(QWebEngineCookieStoreClient); + if (d->m_getAllCookiesPending) { + d->callbackDirectory.invokeEmpty(resultCallback); + return; + } + d->callbackDirectory.registerCallback(CallbackDirectory::GetAllCookiesCallbackId, resultCallback); + d->getAllCookies(); +} + +/*! + \fn void QWebEngineCookieStoreClient::deleteSessionCookiesWithCallback(FunctorOrLambda resultCallback) + + Deletes all the session cookies in the cookie store. Session cookies do not have an + expiration date assigned to them. + When the asynchronous operation finishes, \a resultCallback will be called with the + number of cookies deleted as the argument. +*/ + +void QWebEngineCookieStoreClient::deleteSessionCookiesWithCallback(const QWebEngineCallback<int> &resultCallback) +{ + Q_D(QWebEngineCookieStoreClient); + if (d->m_deleteAllCookiesPending || d->m_deleteSessionCookiesPending) { + d->callbackDirectory.invokeEmpty(resultCallback); + return; + } + d->callbackDirectory.registerCallback(CallbackDirectory::DeleteSessionCookiesCallbackId, resultCallback); + d->deleteSessionCookies(); +} + +/*! + \fn void QWebEngineCookieStoreClient::deleteAllCookiesWithCallback(FunctorOrLambda resultCallback) + + Deletes all the cookies in the cookie store. When the asynchronous operation finishes, + \a resultCallback will be called with the number of cookies deleted as the argument. + + \sa deleteSessionCookiesWithCallback(), getAllCookies() +*/ + +void QWebEngineCookieStoreClient::deleteAllCookiesWithCallback(const QWebEngineCallback<int> &resultCallback) +{ + Q_D(QWebEngineCookieStoreClient); + if (d->m_deleteAllCookiesPending) { + d->callbackDirectory.invokeEmpty(resultCallback); + return; + } + d->callbackDirectory.registerCallback(CallbackDirectory::DeleteAllCookiesCallbackId, resultCallback); + d->deleteAllCookies(); +} + +/*! + Deletes all the session cookies in the cookie store. + + \sa deleteSessionCookiesWithCallback() +*/ + +void QWebEngineCookieStoreClient::deleteSessionCookies() +{ + deleteSessionCookiesWithCallback(QWebEngineCallback<int>()); +} + +/*! + Deletes all the cookies in the cookie store. + + \sa deleteAllCookiesWithCallback(), getAllCookies() +*/ + +void QWebEngineCookieStoreClient::deleteAllCookies() +{ + deleteAllCookiesWithCallback(QWebEngineCallback<int>()); +} + +/*! + \fn void QWebEngineCookieStoreClient::setCookieFilter(FunctorOrLambda filterCallback) + + Installs a cookie filter that can reject cookies before they are added to the cookie store. + The \a filterCallback must be a lambda or functor taking FilterRequest structure. If the + cookie is to be rejected, the filter can set FilterRequest::accepted to \c false. + + The callback should not be used to execute heavy tasks since it is running on the + IO thread and therefore blocks the Chromium networking. + + \sa deleteAllCookiesWithCallback(), getAllCookies() +*/ +void QWebEngineCookieStoreClient::setCookieFilter(const QWebEngineCallback<QWebEngineCookieStoreClient::FilterRequest&> &filter) +{ + Q_D(QWebEngineCookieStoreClient); + d->filterCallback = filter; +} + +QT_END_NAMESPACE diff --git a/src/core/api/qwebenginecookiestoreclient.h b/src/core/api/qwebenginecookiestoreclient.h new file mode 100644 index 000000000..4664a8459 --- /dev/null +++ b/src/core/api/qwebenginecookiestoreclient.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QWEBENGINECOOKIESTORECLIENT_H +#define QWEBENGINECOOKIESTORECLIENT_H + +#include "qtwebenginecoreglobal.h" +#include "qwebenginecallback.h" + +#include <QtCore/qobject.h> +#include <QtCore/qscopedpointer.h> +#include <QtCore/qurl.h> +#include <QtNetwork/qnetworkcookie.h> + +namespace QtWebEngineCore { +class BrowserContextAdapter; +class CookieMonsterDelegateQt; +} + +QT_BEGIN_NAMESPACE + +class QWebEngineCookieStoreClientPrivate; +class QWEBENGINE_EXPORT QWebEngineCookieStoreClient : public QObject { + Q_OBJECT + +public: + struct FilterRequest { + bool accepted; + + QUrl firstPartyUrl; + QByteArray cookieLine; + QUrl cookieSource; + }; + virtual ~QWebEngineCookieStoreClient(); + +#ifdef Q_QDOC + void setCookieWithCallback(const QNetworkCookie &cookie, FunctorOrLambda resultCallback, const QUrl &origin = QUrl()); + void deleteSessionCookiesWithCallback(FunctorOrLambda resultCallback); + void deleteAllCookiesWithCallback(FunctorOrLambda resultCallback); + void getAllCookies(FunctorOrLambda resultCallback); + void setCookieFilter(FunctorOrLambda filterCallback); +#else + void setCookieWithCallback(const QNetworkCookie &cookie, const QWebEngineCallback<bool> &resultCallback, const QUrl &origin = QUrl()); + void deleteSessionCookiesWithCallback(const QWebEngineCallback<int> &resultCallback); + void deleteAllCookiesWithCallback(const QWebEngineCallback<int> &resultCallback); + void getAllCookies(const QWebEngineCallback<const QByteArray&> &resultCallback); + void setCookieFilter(const QWebEngineCallback<FilterRequest&> &filterCallback); +#endif + void setCookie(const QNetworkCookie &cookie, const QUrl &origin = QUrl()); + void deleteCookie(const QNetworkCookie &cookie, const QUrl &origin = QUrl()); + void deleteSessionCookies(); + void deleteAllCookies(); + +Q_SIGNALS: + void cookieAdded(const QNetworkCookie &cookie); + void cookieRemoved(const QNetworkCookie &cookie); + +private: + explicit QWebEngineCookieStoreClient(QObject *parent = 0); + friend class QtWebEngineCore::BrowserContextAdapter; + friend class QtWebEngineCore::CookieMonsterDelegateQt; + Q_DISABLE_COPY(QWebEngineCookieStoreClient) + Q_DECLARE_PRIVATE(QWebEngineCookieStoreClient) + QScopedPointer<QWebEngineCookieStoreClientPrivate> d_ptr; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QWebEngineCookieStoreClient*) + +#endif // QWEBENGINECOOKIESTORECLIENT_H diff --git a/src/core/api/qwebenginecookiestoreclient_p.h b/src/core/api/qwebenginecookiestoreclient_p.h new file mode 100644 index 000000000..68ab6549f --- /dev/null +++ b/src/core/api/qwebenginecookiestoreclient_p.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QWEBENGINECOOKIESTORECLIENT_P_H +#define QWEBENGINECOOKIESTORECLIENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtwebenginecoreglobal_p.h" + +#include "qwebenginecallback_p.h" +#include "qwebenginecookiestoreclient.h" + +#include <QList> +#include <QMap> +#include <QNetworkCookie> +#include <QUrl> + +namespace QtWebEngineCore { +class CookieMonsterDelegateQt; +} + +QT_BEGIN_NAMESPACE + +class QWEBENGINE_PRIVATE_EXPORT QWebEngineCookieStoreClientPrivate { + struct CookieData { + quint64 callbackId; + QNetworkCookie cookie; + QUrl origin; + }; + +public: + Q_DECLARE_PUBLIC(QWebEngineCookieStoreClient) + QtWebEngineCore::CallbackDirectory callbackDirectory; + QWebEngineCallback<QWebEngineCookieStoreClient::FilterRequest&> filterCallback; + QList<CookieData> m_pendingUserCookies; + quint64 m_nextCallbackId; + bool m_deleteSessionCookiesPending; + bool m_deleteAllCookiesPending; + bool m_getAllCookiesPending; + + QtWebEngineCore::CookieMonsterDelegateQt *delegate; + QWebEngineCookieStoreClient *q_ptr; + + QWebEngineCookieStoreClientPrivate(QWebEngineCookieStoreClient *q); + ~QWebEngineCookieStoreClientPrivate(); + + void processPendingUserCookies(); + void setCookie(const QWebEngineCallback<bool> &callback, const QNetworkCookie &cookie, const QUrl &origin); + void deleteCookie(const QNetworkCookie &cookie, const QUrl &url); + void deleteSessionCookies(); + void deleteAllCookies(); + void getAllCookies(); + + bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url); + + void onGetAllCallbackResult(qint64 callbackId, const QByteArray &cookieList); + void onSetCallbackResult(qint64 callbackId, bool success); + void onDeleteCallbackResult(qint64 callbackId, int numCookies); + void onCookieChanged(const QNetworkCookie &cookie, bool removed); +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINECOOKIESTORECLIENT_P_H diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp new file mode 100644 index 000000000..e8ce65be3 --- /dev/null +++ b/src/core/api/qwebengineurlrequestinfo.cpp @@ -0,0 +1,277 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "qwebengineurlrequestinfo.h" +#include "qwebengineurlrequestinfo_p.h" + +#include "content/public/common/resource_type.h" + +#include "web_contents_adapter_client.h" + +QT_BEGIN_NAMESPACE + +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMainFrame, content::RESOURCE_TYPE_MAIN_FRAME) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSubFrame, content::RESOURCE_TYPE_SUB_FRAME) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeStylesheet, content::RESOURCE_TYPE_STYLESHEET) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeScript, content::RESOURCE_TYPE_SCRIPT) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeImage, content::RESOURCE_TYPE_IMAGE) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeFontResource, content::RESOURCE_TYPE_FONT_RESOURCE) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSubResource, content::RESOURCE_TYPE_SUB_RESOURCE) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeObject, content::RESOURCE_TYPE_OBJECT) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMedia, content::RESOURCE_TYPE_MEDIA) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeWorker, content::RESOURCE_TYPE_WORKER) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeSharedWorker, content::RESOURCE_TYPE_SHARED_WORKER) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePrefetch, content::RESOURCE_TYPE_PREFETCH) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeFavicon, content::RESOURCE_TYPE_FAVICON) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeXhr, content::RESOURCE_TYPE_XHR) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypePing, content::RESOURCE_TYPE_PING) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker, content::RESOURCE_TYPE_SERVICE_WORKER) +ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeUnknown, content::RESOURCE_TYPE_LAST_TYPE) + +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::LinkNavigation, QWebEngineUrlRequestInfo::NavigationTypeLink) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::TypedNavigation, QWebEngineUrlRequestInfo::NavigationTypeTyped) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::FormSubmittedNavigation, QWebEngineUrlRequestInfo::NavigationTypeFormSubmitted) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::BackForwardNavigation, QWebEngineUrlRequestInfo::NavigationTypeBackForward) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::ReloadNavigation, QWebEngineUrlRequestInfo::NavigationTypeReload) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::OtherNavigation, QWebEngineUrlRequestInfo::NavigationTypeOther) + +/*! + \class QWebEngineUrlRequestInfo + \inmodule QtWebEngineCore + \since 5.6 + \brief The QWebEngineUrlRequestInfo class provides information about URL requests. + + The QWebEngineUrlRequestInfo is useful for setting extra header fields for requests + or for redirecting certain requests without payload data to another URL. + This class cannot be instantiated or copied by the user, instead it will + be created by Qt WebEngine and sent through the virtual function + QWebEngineUrlRequestInterceptor::interceptRequest() if an interceptor has been set. +*/ + +/*! + \class QWebEngineUrlRequestInterceptor + \inmodule QtWebEngineCore + \since 5.6 + \brief The QWebEngineUrlRequestInterceptor class provides an abstract base class for URL interception. + + Implementing the \l{QWebEngineUrlRequestInterceptor} interface and installing the + interceptor on the profile enables intercepting, blocking, and modifying URL requests + before they reach the networking stack of Chromium. + + \sa QWebEngineUrlRequestInterceptor::interceptRequest, QWebEngineUrlRequestInfo +*/ + +/*! + \fn QWebEngineUrlRequestInterceptor::QWebEngineUrlRequestInterceptor(QObject * p = 0) + + Creates a new QWebEngineUrlRequestInterceptor object with \a p as parent. +*/ + +/*! + \fn QWebEngineUrlRequestInterceptor::~QWebEngineUrlRequestInterceptor() + + Destroys this QWebEngineUrlRequestInterceptor object. +*/ + +/*! + \fn bool QWebEngineUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info) + + Reimplementing this virtual function and setting the interceptor on a profile makes + it possible to intercept URL requests. This function is executed on the IO thread, + and therefore running long tasks here will block networking. + If this function is only used for inspection, it should return \c false, in which + case any modification to \a info will be ignored. + + \sa QWebEngineProfile::setRequestInterceptor +*/ + + +QWebEngineUrlRequestInfoPrivate::QWebEngineUrlRequestInfoPrivate(QWebEngineUrlRequestInfo::ResourceType resource, QWebEngineUrlRequestInfo::NavigationType navigation, const QUrl &u, const QUrl &fpu, const QByteArray &m) + : resourceType(resource) + , navigationType(navigation) + , shouldBlockRequest(false) + , url(u) + , firstPartyUrl(fpu) + , method(m) +{ +} + +/*! + \internal +*/ + +QWebEngineUrlRequestInfo::~QWebEngineUrlRequestInfo() +{ + +} + +/*! + \internal +*/ + +QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPrivate *p) + : d_ptr(p) +{ + d_ptr->q_ptr = this; +} + +/*! + \enum QWebEngineUrlRequestInfo::ResourceType + + This enum type holds the type of the requested resource: + + \value ResourceTypeMainFrame Top level page. + \value ResourceTypeSubFrame Frame or iframe. + \value ResourceTypeStylesheet A CSS stylesheet. + \value ResourceTypeScript An external script. + \value ResourceTypeImage An image (JPG, GIF, PNG, and so on). + \value ResourceTypeFontResource A font. + \value ResourceTypeSubResource An "other" subresource. + \value ResourceTypeObject An object (or embed) tag for a plugin or a resource that a plugin requested. + \value ResourceTypeMedia A media resource. + \value ResourceTypeWorker The main resource of a dedicated worker. + \value ResourceTypeSharedWorker The main resource of a shared worker. + \value ResourceTypePrefetch An explicitly requested prefetch. + \value ResourceTypeFavicon A favicon. + \value ResourceTypeXhr An XMLHttpRequest. + \value ResourceTypePing A ping request for <a ping>. + \value ResourceTypeServiceWorker The main resource of a service worker. + \value ResourceTypeUnknown Unknown request type. +*/ + +/*! + Returns the resource type of the request. + + \sa QWebEngineUrlRequestInfo::ResourceType +*/ + +QWebEngineUrlRequestInfo::ResourceType QWebEngineUrlRequestInfo::resourceType() const +{ + Q_D(const QWebEngineUrlRequestInfo); + return d->resourceType; +} + +/*! + \enum QWebEngineUrlRequestInfo::NavigationType + + This enum type describes the navigation type of the request: + + \value NavigationTypeLink Navigation initiated by clicking a link. + \value NavigationTypeTyped Navigation explicitly initiated by typing a URL. + \value NavigationTypeFormSubmitted Navigation submits a form. + \value NavigationTypeBackForward Navigation initiated by a history action. + \value NavigationTypeReload Navigation initiated by refreshing the page. + \value NavigationTypeOther None of the above. +*/ + +/*! + Returns the navigation type of the request. + + \sa QWebEngineUrlRequestInfo::NavigationType +*/ + +QWebEngineUrlRequestInfo::NavigationType QWebEngineUrlRequestInfo::navigationType() const +{ + Q_D(const QWebEngineUrlRequestInfo); + return d->navigationType; +} + +/*! + Returns the requested URL. +*/ + +QUrl QWebEngineUrlRequestInfo::requestUrl() const +{ + Q_D(const QWebEngineUrlRequestInfo); + return d->url; +} + +/*! + Returns the first party URL of the request. + The first party URL is the URL of the page that issued the request. +*/ + +QUrl QWebEngineUrlRequestInfo::firstPartyUrl() const +{ + Q_D(const QWebEngineUrlRequestInfo); + return d->firstPartyUrl; +} + + +/*! + Returns the HTTP method of the request (for example, GET or POST). +*/ + +QByteArray QWebEngineUrlRequestInfo::requestMethod() const +{ + Q_D(const QWebEngineUrlRequestInfo); + return d->method; +} + +/*! + Redirects this request to \a url. + It is only possible to redirect requests that do not have payload data, such as GET requests. +*/ + +void QWebEngineUrlRequestInfo::redirect(const QUrl &url) +{ + Q_D(QWebEngineUrlRequestInfo); + d->url = url; +} + +/*! + Blocks this request if \a shouldBlock is true, so that it will not proceed. + + This function can be used to prevent navigating away from a given domain, for example. +*/ + +void QWebEngineUrlRequestInfo::block(bool shouldBlock) +{ + Q_D(QWebEngineUrlRequestInfo); + d->shouldBlockRequest = shouldBlock; +} + +/*! + Sets an extra request header for this request with \a name and \a value. +*/ + +void QWebEngineUrlRequestInfo::setExtraHeader(const QByteArray &name, const QByteArray &value) +{ + Q_D(QWebEngineUrlRequestInfo); + d->extraHeaders.insert(name, value); +} + +QT_END_NAMESPACE diff --git a/src/core/api/qwebengineurlrequestinfo.h b/src/core/api/qwebengineurlrequestinfo.h new file mode 100644 index 000000000..e6e225051 --- /dev/null +++ b/src/core/api/qwebengineurlrequestinfo.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QWEBENGINEURLREQUESTINFO_H +#define QWEBENGINEURLREQUESTINFO_H + +#include "qtwebenginecoreglobal.h" + +#include <QtCore/qscopedpointer.h> +#include <QtCore/qurl.h> + +namespace QtWebEngineCore { +class NetworkDelegateQt; +} + +QT_BEGIN_NAMESPACE + +class QWebEngineUrlRequestInfoPrivate; + +class QWEBENGINE_EXPORT QWebEngineUrlRequestInfo { +public: + enum ResourceType { + ResourceTypeMainFrame = 0, // top level page + ResourceTypeSubFrame, // frame or iframe + ResourceTypeStylesheet, // a CSS stylesheet + ResourceTypeScript, // an external script + ResourceTypeImage, // an image (jpg/gif/png/etc) + ResourceTypeFontResource, // a font + ResourceTypeSubResource, // an "other" subresource. + ResourceTypeObject, // an object (or embed) tag for a plugin, + // or a resource that a plugin requested. + ResourceTypeMedia, // a media resource. + ResourceTypeWorker, // the main resource of a dedicated worker. + ResourceTypeSharedWorker, // the main resource of a shared worker. + ResourceTypePrefetch, // an explicitly requested prefetch + ResourceTypeFavicon, // a favicon + ResourceTypeXhr, // a XMLHttpRequest + ResourceTypePing, // a ping request for <a ping> + ResourceTypeServiceWorker, // the main resource of a service worker. + ResourceTypeUnknown + }; + + enum NavigationType { + NavigationTypeLink, + NavigationTypeTyped, + NavigationTypeFormSubmitted, + NavigationTypeBackForward, + NavigationTypeReload, + NavigationTypeOther + }; + + ResourceType resourceType() const; + NavigationType navigationType() const; + + QUrl requestUrl() const; + QUrl firstPartyUrl() const; + QByteArray requestMethod() const; + + void block(bool shouldBlock); + void redirect(const QUrl &url); + void setExtraHeader(const QByteArray &name, const QByteArray &value); + +private: + friend class QtWebEngineCore::NetworkDelegateQt; + Q_DISABLE_COPY(QWebEngineUrlRequestInfo) + Q_DECLARE_PRIVATE(QWebEngineUrlRequestInfo) + + QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPrivate *p); + ~QWebEngineUrlRequestInfo(); + QScopedPointer<QWebEngineUrlRequestInfoPrivate> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEURLREQUESTINFO_H diff --git a/src/core/api/qwebengineurlrequestinfo_p.h b/src/core/api/qwebengineurlrequestinfo_p.h new file mode 100644 index 000000000..1b1279d27 --- /dev/null +++ b/src/core/api/qwebengineurlrequestinfo_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QWEBENGINEURLREQUESTINFO_P_H +#define QWEBENGINEURLREQUESTINFO_P_H + +#include "qtwebenginecoreglobal_p.h" + +#include "qwebengineurlrequestinfo.h" + +#include <QByteArray> +#include <QHash> +#include <QUrl> + +namespace net { +class URLRequest; +} + +QT_BEGIN_NAMESPACE + +class QWebEngineUrlRequestInfoPrivate +{ + Q_DECLARE_PUBLIC(QWebEngineUrlRequestInfo) +public: + QWebEngineUrlRequestInfoPrivate(QWebEngineUrlRequestInfo::ResourceType resource + , QWebEngineUrlRequestInfo::NavigationType navigation + , const QUrl &u + , const QUrl &fpu + , const QByteArray &m); + + QWebEngineUrlRequestInfo::ResourceType resourceType; + QWebEngineUrlRequestInfo::NavigationType navigationType; + bool shouldBlockRequest; + + QUrl url; + QUrl firstPartyUrl; + const QByteArray method; + QHash<QByteArray, QByteArray> extraHeaders; + + QWebEngineUrlRequestInfo *q_ptr; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEURLREQUESTINFO_P_H diff --git a/src/core/api/qwebengineurlrequestinterceptor.h b/src/core/api/qwebengineurlrequestinterceptor.h new file mode 100644 index 000000000..72f3452d0 --- /dev/null +++ b/src/core/api/qwebengineurlrequestinterceptor.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QWEBENINGEURLREQUESTINTERCEPTOR_H +#define QWEBENINGEURLREQUESTINTERCEPTOR_H + +#include "qtwebenginecoreglobal.h" +#include "qwebengineurlrequestinfo.h" + +#include <QtCore/qbytearray.h> +#include <QtCore/qhash.h> +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> + +QT_BEGIN_NAMESPACE + +class QWEBENGINE_EXPORT QWebEngineUrlRequestInterceptor : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(QWebEngineUrlRequestInterceptor) +public: + explicit QWebEngineUrlRequestInterceptor(QObject *p = 0) + : QObject (p) + { + } + virtual ~QWebEngineUrlRequestInterceptor() + { + } + + virtual bool interceptRequest(QWebEngineUrlRequestInfo &info) = 0; +}; + +QT_END_NAMESPACE + +#endif // QWEBENINGEURLREQUESTINTERCEPTOR_H diff --git a/src/core/api/qwebengineurlrequestjob.cpp b/src/core/api/qwebengineurlrequestjob.cpp new file mode 100644 index 000000000..0e56ba5b3 --- /dev/null +++ b/src/core/api/qwebengineurlrequestjob.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "qwebengineurlrequestjob.h" + +#include "url_request_custom_job_delegate.h" + +using QtWebEngineCore::URLRequestCustomJobDelegate; + +QT_BEGIN_NAMESPACE + +/*! + \class QWebEngineUrlRequestJob + \brief The QWebEngineUrlRequestJob class represents a custom URL request. + \since 5.6 + + A QWebEngineUrlRequestJob is given to QWebEngineUrlSchemeHandler::requestStarted() and must + be handled by the derived implementations of the class. The job can be handled by calling + either reply(), redirect(), or fail(). + + The class is owned by the web engine and does not need to be deleted. However, the web engine + may delete the job when it is no longer needed, and therefore the signal QObject::destroyed() + must be monitored if a pointer to the object is stored. + + \inmodule QtWebEngineCore +*/ + +/*! + \enum QWebEngineUrlRequestJob::Error + + This enum type holds the type of the error that occurred: + + \value NoError + The request was successful. + \value UrlNotFound + The requested URL was not found. + \value UrlInvalid + The requested URL is invalid. + \value RequestAborted + The request was canceled. + \value RequestDenied + The request was denied. + \value RequestFailed + The request failed. +*/ + +/*! + \internal + */ +QWebEngineUrlRequestJob::QWebEngineUrlRequestJob(URLRequestCustomJobDelegate * p) + : QObject(p) // owned by the jobdelegate and deleted when the job is done + , d_ptr(p) +{ +} + +/*! + \internal + */ +QWebEngineUrlRequestJob::~QWebEngineUrlRequestJob() +{ +} + +/*! + Returns the requested URL. +*/ +QUrl QWebEngineUrlRequestJob::requestUrl() const +{ + return d_ptr->url(); +} + +/*! + Returns the HTTP method of the request (for example, GET or POST). +*/ +QByteArray QWebEngineUrlRequestJob::requestMethod() const +{ + return d_ptr->method(); +} + +/*! + Replies to the request with \a device and the MIME type \a contentType. + */ +void QWebEngineUrlRequestJob::reply(const QByteArray &contentType, QIODevice *device) +{ + d_ptr->setReply(contentType, device); +} + +/*! + Fails the request with the error \a r. + + \sa Error + */ +void QWebEngineUrlRequestJob::fail(Error r) +{ + d_ptr->fail((URLRequestCustomJobDelegate::Error)r); +} + +/*! + Redirects the request to \a url. + */ +void QWebEngineUrlRequestJob::redirect(const QUrl &url) +{ + d_ptr->redirect(url); +} + +QT_END_NAMESPACE diff --git a/src/core/api/qwebengineurlrequestjob.h b/src/core/api/qwebengineurlrequestjob.h new file mode 100644 index 000000000..fc9f4d911 --- /dev/null +++ b/src/core/api/qwebengineurlrequestjob.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QWEBENGINEURLREQUESTJOB_H +#define QWEBENGINEURLREQUESTJOB_H + +#include "qtwebenginecoreglobal.h" + +#include <QtCore/qbytearray.h> +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> + +namespace QtWebEngineCore { +class URLRequestCustomJob; +class URLRequestCustomJobDelegate; +} // namespace + +QT_BEGIN_NAMESPACE + +class QIODevice; + +class QWEBENGINE_EXPORT QWebEngineUrlRequestJob : public QObject { + Q_OBJECT +public: + ~QWebEngineUrlRequestJob(); + + enum Error { + NoError = 0, + UrlNotFound, + UrlInvalid, + RequestAborted, + RequestDenied, + RequestFailed + }; + Q_ENUM(Error) + + QUrl requestUrl() const; + QByteArray requestMethod() const; + + void reply(const QByteArray &contentType, QIODevice *device); + void fail(Error error); + void redirect(const QUrl &url); + +private: + QWebEngineUrlRequestJob(QtWebEngineCore::URLRequestCustomJobDelegate *); + friend class QtWebEngineCore::URLRequestCustomJob; + + QtWebEngineCore::URLRequestCustomJobDelegate* d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEURLREQUESTJOB_H diff --git a/src/core/api/qwebengineurlschemehandler.cpp b/src/core/api/qwebengineurlschemehandler.cpp new file mode 100644 index 000000000..f887e4e98 --- /dev/null +++ b/src/core/api/qwebengineurlschemehandler.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "qwebengineurlschemehandler.h" + +#include "qwebengineurlrequestjob.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QWebEngineUrlSchemeHandler + \brief The QWebEngineUrlSchemeHandler is a base class for handling custom URL schemes. + \since 5.6 + + To implement a custom URL scheme for QtWebEngine, you must write a class derived from this class, + and reimplement requestStarted(). + + \inmodule QtWebEngineCore + +*/ + +/*! + \fn QWebEngineUrlSchemeHandler::destroyed(QWebEngineUrlSchemeHandler *handler) + + This signal is emitted when the custom URL scheme handler \a handler is deleted. +*/ + +/*! + Constructs a new URL scheme handler. + + The handler is created with the parent \a parent. + + */ +QWebEngineUrlSchemeHandler::QWebEngineUrlSchemeHandler(QObject *parent) + : QObject(parent) +{ +} + +/*! + Deletes a custom URL scheme handler. +*/ +QWebEngineUrlSchemeHandler::~QWebEngineUrlSchemeHandler() +{ + Q_EMIT destroyed(this); + delete d_ptr; +} + +/*! + \fn void QWebEngineUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request) + + This method is called whenever a request \a request for the registered scheme is started. + + This method must be reimplemented by all custom URL scheme handlers. + The request is asynchronous and does not need to be handled right away. + + \sa QWebEngineUrlRequestJob +*/ + +QT_END_NAMESPACE diff --git a/src/core/api/qwebengineurlschemehandler.h b/src/core/api/qwebengineurlschemehandler.h new file mode 100644 index 000000000..8c1e52646 --- /dev/null +++ b/src/core/api/qwebengineurlschemehandler.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 QWEBENGINEURLSCHEMEHANDLER_H +#define QWEBENGINEURLSCHEMEHANDLER_H + +#include "qtwebenginecoreglobal.h" + +#include <QtCore/qobject.h> + +namespace QtWebEngineCore { +class URLRequestContextGetterQt; +} + +QT_BEGIN_NAMESPACE + +class QWebEngineUrlRequestJob; +class QWebEngineUrlSchemeHandlerPrivate; + +class QWEBENGINE_EXPORT QWebEngineUrlSchemeHandler : public QObject { + Q_OBJECT +public: + QWebEngineUrlSchemeHandler(QObject *parent = 0); + ~QWebEngineUrlSchemeHandler(); + + virtual void requestStarted(QWebEngineUrlRequestJob*) = 0; + +Q_SIGNALS: + void destroyed(QWebEngineUrlSchemeHandler*); + +private: + Q_DISABLE_COPY(QWebEngineUrlSchemeHandler) + Q_DECLARE_PRIVATE(QWebEngineUrlSchemeHandler) + QWebEngineUrlSchemeHandlerPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEURLSCHEMEHANDLER_H diff --git a/src/core/authentication_dialog_controller.cpp b/src/core/authentication_dialog_controller.cpp new file mode 100644 index 000000000..db534a24e --- /dev/null +++ b/src/core/authentication_dialog_controller.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "authentication_dialog_controller.h" +#include "authentication_dialog_controller_p.h" + +#include "content/public/browser/browser_thread.h" + +namespace QtWebEngineCore { + +AuthenticationDialogControllerPrivate::AuthenticationDialogControllerPrivate(ResourceDispatcherHostLoginDelegateQt *loginDelegate) + : loginDelegate(loginDelegate) +{ +} + +void AuthenticationDialogControllerPrivate::dialogFinished(bool accepted, const QString &user, const QString &password) +{ + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&ResourceDispatcherHostLoginDelegateQt::sendAuthToRequester, loginDelegate, accepted, user, password)); +} + +AuthenticationDialogController::AuthenticationDialogController(AuthenticationDialogControllerPrivate *dd) +{ + Q_ASSERT(dd); + d.reset(dd); +} + +AuthenticationDialogController::~AuthenticationDialogController() +{ +} + +QUrl AuthenticationDialogController::url() const +{ + return d->loginDelegate->url(); +} + +QString AuthenticationDialogController::realm() const +{ + return d->loginDelegate->realm(); +} + +QString AuthenticationDialogController::host() const +{ + return d->loginDelegate->host(); +} + +bool AuthenticationDialogController::isProxy() const +{ + return d->loginDelegate->isProxy(); +} + +void AuthenticationDialogController::accept(const QString &user, const QString &password) +{ + d->dialogFinished(true, user, password); +} + +void AuthenticationDialogController::reject() +{ + d->dialogFinished(false); +} + +} // namespace QtWebEngineCore diff --git a/src/core/authentication_dialog_controller.h b/src/core/authentication_dialog_controller.h new file mode 100644 index 000000000..ae741f537 --- /dev/null +++ b/src/core/authentication_dialog_controller.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 AUTHENTICATION_DIALOG_CONTROLLER_H +#define AUTHENTICATION_DIALOG_CONTROLLER_H + +#include "qtwebenginecoreglobal.h" + +#include <QObject> + +namespace QtWebEngineCore { + +class AuthenticationDialogControllerPrivate; + +class QWEBENGINE_EXPORT AuthenticationDialogController : public QObject { + Q_OBJECT +public: + ~AuthenticationDialogController(); + + QUrl url() const; + QString realm() const; + QString host() const; + bool isProxy() const; + +public Q_SLOTS: + void accept(const QString &user, const QString &password); + void reject(); + +private: + AuthenticationDialogController(AuthenticationDialogControllerPrivate *); + + QScopedPointer<AuthenticationDialogControllerPrivate> d; + friend class ResourceDispatcherHostLoginDelegateQt; +}; + +} // namespace QtWebEngineCore + +#endif // AUTHENTICATION_DIALOG_CONTROLLER_H diff --git a/src/core/custom_url_scheme_handler.cpp b/src/core/authentication_dialog_controller_p.h index b9fcf9c36..5b1d21ae0 100644 --- a/src/core/custom_url_scheme_handler.cpp +++ b/src/core/authentication_dialog_controller_p.h @@ -34,34 +34,23 @@ ** ****************************************************************************/ -#include "custom_url_scheme_handler.h" -#include "custom_protocol_handler.h" +#ifndef AUTHENTICATION_DIALOG_CONTROLLER_P_H +#define AUTHENTICATION_DIALOG_CONTROLLER_P_H -namespace QtWebEngineCore { +#include "base/memory/ref_counted.h" +#include "resource_dispatcher_host_delegate_qt.h" -CustomUrlSchemeHandler::CustomUrlSchemeHandler(const QByteArray &scheme) - : m_scheme(scheme) -{ -} +namespace QtWebEngineCore { -CustomUrlSchemeHandler::~CustomUrlSchemeHandler() -{ -} +class AuthenticationDialogControllerPrivate { -QByteArray CustomUrlSchemeHandler::scheme() const -{ - return m_scheme; -} +public: + AuthenticationDialogControllerPrivate(ResourceDispatcherHostLoginDelegateQt *loginDelegate); + void dialogFinished(bool accepted, const QString &user = QString(), const QString &password = QString()); -void CustomUrlSchemeHandler::setScheme(const QByteArray &scheme) -{ - m_scheme = scheme; -} + scoped_refptr<ResourceDispatcherHostLoginDelegateQt> loginDelegate; +}; -CustomProtocolHandler *CustomUrlSchemeHandler::createProtocolHandler() -{ - // Will be owned by the JobFactory. - return new CustomProtocolHandler(this); -} +} // namespace QtWebEngineCore -} // namespace +#endif // AUTHENTICATION_DIALOG_CONTROLLER_H diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index 7cd5ac21f..ebf99e950 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -46,7 +46,7 @@ #include "ui/accessibility/ax_node_data.h" #include "browser_accessibility_manager_qt.h" -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include "type_conversion.h" using namespace blink; @@ -86,19 +86,19 @@ void BrowserAccessibilityQt::OnDataChanged() // always returns the primary name in "name" and the secondary name, // if any, in "description". - int title_elem_id = GetIntAttribute( - ui::AX_ATTR_TITLE_UI_ELEMENT); - std::string help = GetStringAttribute(ui::AX_ATTR_HELP); - std::string description = GetStringAttribute( - ui::AX_ATTR_DESCRIPTION); + int title_elem_id = GetIntAttribute(ui::AX_ATTR_TITLE_UI_ELEMENT); + base::string16 name = GetString16Attribute(ui::AX_ATTR_NAME); + base::string16 description = GetString16Attribute(ui::AX_ATTR_DESCRIPTION); + base::string16 help = GetString16Attribute(ui::AX_ATTR_HELP); + base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); // WebKit annoyingly puts the title in the description if there's no other // description, which just confuses the rest of the logic. Put it back. // Now "help" is always the value of the "title" attribute, if present. - std::string title_attr; + base::string16 title_attr; if (GetHtmlAttribute("title", &title_attr) && - description == title_attr && - help.empty()) { + description == title_attr && + help.empty()) { help = description; description.clear(); } @@ -107,32 +107,34 @@ void BrowserAccessibilityQt::OnDataChanged() // it's nonempty, and the help should become the description if // there's no description - or the name if there's no name or description. if (!description.empty()) { - set_name(description); + name = description; description.clear(); } if (!help.empty() && description.empty()) { description = help; help.clear(); } - if (!description.empty() && name().empty() && !title_elem_id) { - set_name(description); + if (!description.empty() && name.empty() && !title_elem_id) { + name = description; description.clear(); } // If it's a text field, also consider the placeholder. - std::string placeholder; + base::string16 placeholder; if (GetRole() == ui::AX_ROLE_TEXT_FIELD && - HasState(ui::AX_STATE_FOCUSABLE) && - GetHtmlAttribute("placeholder", &placeholder)) { - if (name().empty() && !title_elem_id) { - set_name(placeholder); + HasState(ui::AX_STATE_FOCUSABLE) && + GetHtmlAttribute("placeholder", &placeholder)) { + if (name.empty() && !title_elem_id) { + name = placeholder; } else if (description.empty()) { description = placeholder; } } - SetStringAttribute(ui::AX_ATTR_DESCRIPTION, description); - SetStringAttribute(ui::AX_ATTR_HELP, help); + m_name = toQt(name); + m_description = toQt(description); + m_help = toQt(help); + m_value = toQt(value); } bool BrowserAccessibilityQt::isValid() const @@ -227,13 +229,13 @@ QString BrowserAccessibilityQt::text(QAccessible::Text t) const { switch (t) { case QAccessible::Name: - return toQt(name()); + return name(); case QAccessible::Description: - return toQt(GetStringAttribute(ui::AX_ATTR_DESCRIPTION)); + return description(); case QAccessible::Help: - return toQt(GetStringAttribute(ui::AX_ATTR_HELP)); + return help(); case QAccessible::Value: - return toQt(GetStringAttribute(ui::AX_ATTR_VALUE)); + return value(); case QAccessible::Accelerator: return toQt(GetStringAttribute(ui::AX_ATTR_SHORTCUT)); default: @@ -277,10 +279,10 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Document; // returning Application here makes Qt return the top level app object case ui::AX_ROLE_ARTICLE: return QAccessible::Section; - case ui::AX_ROLE_BROWSER: - return QAccessible::Document; // FIXME case ui::AX_ROLE_BANNER: return QAccessible::Section; + case ui::AX_ROLE_BLOCKQUOTE: + return QAccessible::Section; case ui::AX_ROLE_BUSY_INDICATOR: return QAccessible::Animation; // FIXME case ui::AX_ROLE_BUTTON: @@ -325,10 +327,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Section; case ui::AX_ROLE_DOCUMENT: return QAccessible::Document; - case ui::AX_ROLE_DRAWER: - return QAccessible::Client; // FIXME - case ui::AX_ROLE_EDITABLE_TEXT: - return QAccessible::EditableText; case ui::AX_ROLE_EMBEDDED_OBJECT: return QAccessible::Grouping; // FIXME case ui::AX_ROLE_FOOTER: @@ -339,14 +337,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Table; case ui::AX_ROLE_GROUP: return QAccessible::Grouping; - case ui::AX_ROLE_GROW_AREA: - return QAccessible::Grip; case ui::AX_ROLE_HEADING: return QAccessible::Heading; - case ui::AX_ROLE_HELP_TAG: - return QAccessible::HelpBalloon; // FIXME - case ui::AX_ROLE_HORIZONTAL_RULE: - return QAccessible::Separator; case ui::AX_ROLE_IFRAME: return QAccessible::Grouping; case ui::AX_ROLE_IGNORED: @@ -357,8 +349,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Graphic; case ui::AX_ROLE_IMAGE_MAP_LINK: return QAccessible::Link; - case ui::AX_ROLE_INCREMENTOR: - return QAccessible::NoRole; // FIXME case ui::AX_ROLE_INLINE_TEXT_BOX: return QAccessible::EditableText; case ui::AX_ROLE_LABEL_TEXT: @@ -387,8 +377,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::NoRole; // FIXME case ui::AX_ROLE_MATH: return QAccessible::Equation; - case ui::AX_ROLE_MATTE: - return QAccessible::NoRole; // FIXME case ui::AX_ROLE_MENU: return QAccessible::PopupMenu; case ui::AX_ROLE_MENU_BAR: @@ -413,6 +401,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Paragraph; case ui::AX_ROLE_POP_UP_BUTTON: return QAccessible::ComboBox; + case ui::AX_ROLE_PRE: + return QAccessible::Section; case ui::AX_ROLE_PRESENTATIONAL: return QAccessible::NoRole; // FIXME case ui::AX_ROLE_PROGRESS_INDICATOR: @@ -429,8 +419,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::RowHeader; case ui::AX_ROLE_RULER: return QAccessible::NoRole; // FIXME - case ui::AX_ROLE_RULER_MARKER: - return QAccessible::NoRole; // FIXME case ui::AX_ROLE_SCROLL_AREA: return QAccessible::Client; // FIXME case ui::AX_ROLE_SCROLL_BAR: @@ -439,8 +427,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::NoRole; // FIXME case ui::AX_ROLE_SEARCH: return QAccessible::Section; - case ui::AX_ROLE_SHEET: - return QAccessible::NoRole; // FIXME case ui::AX_ROLE_SLIDER: return QAccessible::Slider; case ui::AX_ROLE_SLIDER_THUMB: @@ -451,16 +437,12 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::NoRole; // FIXME case ui::AX_ROLE_SPLITTER: return QAccessible::Splitter; - case ui::AX_ROLE_SPLIT_GROUP: - return QAccessible::Splitter; case ui::AX_ROLE_STATIC_TEXT: return QAccessible::StaticText; case ui::AX_ROLE_STATUS: return QAccessible::StatusBar; case ui::AX_ROLE_SVG_ROOT: return QAccessible::Graphic; - case ui::AX_ROLE_SYSTEM_WIDE: - return QAccessible::NoRole; // FIXME case ui::AX_ROLE_TABLE: return QAccessible::Table; case ui::AX_ROLE_TABLE_HEADER_CONTAINER: @@ -473,8 +455,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::PageTabList; case ui::AX_ROLE_TAB_PANEL: return QAccessible::PageTab; - case ui::AX_ROLE_TEXT_AREA: - return QAccessible::EditableText; case ui::AX_ROLE_TEXT_FIELD: return QAccessible::EditableText; case ui::AX_ROLE_TIMER: @@ -493,8 +473,6 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Tree; case ui::AX_ROLE_TREE_ITEM: return QAccessible::TreeItem; - case ui::AX_ROLE_VALUE_INDICATOR: - return QAccessible::Client; // FIXME case ui::AX_ROLE_WINDOW: return QAccessible::Window; } diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h index 7d58f515e..b7b4c39bc 100644 --- a/src/core/browser_accessibility_qt.h +++ b/src/core/browser_accessibility_qt.h @@ -142,6 +142,18 @@ public: virtual QAccessibleInterface* table() const Q_DECL_OVERRIDE; virtual void modelChange(QAccessibleTableModelChangeEvent *event) Q_DECL_OVERRIDE; + + QString name() const { return m_name; } + QString description() const { return m_description; } + QString help() const { return m_help; } + QString value() const { return m_value; } + +private: + // IAccessible name, description, help, value. + QString m_name; + QString m_description; + QString m_help; + QString m_value; }; } diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp index a35f313f0..b5fdf2ce0 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/browser_context_adapter.cpp @@ -41,6 +41,7 @@ #include "browser_context_qt.h" #include "content_client_qt.h" #include "download_manager_delegate_qt.h" +#include "permission_manager_qt.h" #include "web_engine_context.h" #include "web_engine_visited_links_manager.h" #include "url_request_context_getter_qt.h" @@ -54,6 +55,8 @@ #include <QStringBuilder> #include <QStandardPaths> +#include <numeric> + namespace { inline QString buildLocationFromStandardPath(const QString &standardPath, const QString &name) { QString location = standardPath; @@ -133,6 +136,23 @@ DownloadManagerDelegateQt *BrowserContextAdapter::downloadManagerDelegate() return m_downloadManagerDelegate.data(); } +QWebEngineCookieStoreClient *BrowserContextAdapter::cookieStoreClient() +{ + if (!m_cookieStoreClient) + m_cookieStoreClient.reset(new QWebEngineCookieStoreClient); + return m_cookieStoreClient.data(); +} + +QWebEngineUrlRequestInterceptor *BrowserContextAdapter::requestInterceptor() +{ + return m_requestInterceptor.data(); +} + +void BrowserContextAdapter::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) +{ + m_requestInterceptor = interceptor; +} + void BrowserContextAdapter::addClient(BrowserContextAdapterClient *adapterClient) { m_clients.append(adapterClient); @@ -230,12 +250,12 @@ void BrowserContextAdapter::setHttpUserAgent(const QString &userAgent) { if (m_httpUserAgent == userAgent) return; - m_httpUserAgent = userAgent; + m_httpUserAgent = userAgent.simplified(); std::vector<content::WebContentsImpl *> list = content::WebContentsImpl::GetAllWebContents(); Q_FOREACH (content::WebContentsImpl *web_contents, list) if (web_contents->GetBrowserContext() == m_browserContext.data()) - web_contents->SetUserAgentOverride(userAgent.toStdString()); + web_contents->SetUserAgentOverride(m_httpUserAgent.toStdString()); if (m_browserContext->url_request_getter_.get()) m_browserContext->url_request_getter_->updateUserAgent(); @@ -329,7 +349,7 @@ void BrowserContextAdapter::setHttpCacheMaxSize(int maxSize) m_browserContext->url_request_getter_->updateHttpCache(); } -QVector<CustomUrlSchemeHandler*> &BrowserContextAdapter::customUrlSchemeHandlers() +QHash<QByteArray, QWebEngineUrlSchemeHandler *> &BrowserContextAdapter::customUrlSchemeHandlers() { return m_customUrlSchemeHandlers; } @@ -340,6 +360,37 @@ void BrowserContextAdapter::updateCustomUrlSchemeHandlers() m_browserContext->url_request_getter_->updateStorageSettings(); } +bool BrowserContextAdapter::removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler) +{ + bool removedOneOrMore = false; + auto it = m_customUrlSchemeHandlers.begin(); + auto end = m_customUrlSchemeHandlers.end(); + for (; it != end; ++it) { + if (it.value() == handler) { + it = m_customUrlSchemeHandlers.erase(it); + removedOneOrMore = true; + continue; + } + } + if (removedOneOrMore) + updateCustomUrlSchemeHandlers(); + return removedOneOrMore; +} + +QWebEngineUrlSchemeHandler *BrowserContextAdapter::takeCustomUrlSchemeHandler(const QByteArray &scheme) +{ + QWebEngineUrlSchemeHandler *handler = m_customUrlSchemeHandlers.take(scheme); + if (handler) + updateCustomUrlSchemeHandlers(); + return handler; +} + +void BrowserContextAdapter::addCustomUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler) +{ + m_customUrlSchemeHandlers.insert(scheme, handler); + updateCustomUrlSchemeHandlers(); +} + UserScriptControllerHost *BrowserContextAdapter::userScriptController() { if (!m_userScriptController) @@ -347,4 +398,29 @@ UserScriptControllerHost *BrowserContextAdapter::userScriptController() return m_userScriptController.data(); } +void BrowserContextAdapter::permissionRequestReply(const QUrl &origin, PermissionType type, bool reply) +{ + static_cast<PermissionManagerQt*>(browserContext()->GetPermissionManager())->permissionRequestReply(origin, type, reply); +} + +QString BrowserContextAdapter::httpAcceptLanguageWithoutQualities() const +{ + const QStringList list = m_httpAcceptLanguage.split(QLatin1Char(',')); + return std::accumulate(list.constBegin(), list.constEnd(), QString(), + [](const QString &r, const QString &e) { + return (r.isEmpty() ? r : r + QString(QLatin1Char(','))) + + e.split(QLatin1Char(';')).first(); + }); +} + +QString BrowserContextAdapter::httpAcceptLanguage() const +{ + return m_httpAcceptLanguage; +} + +void BrowserContextAdapter::setHttpAcceptLanguage(const QString &httpAcceptLanguage) +{ + m_httpAcceptLanguage = httpAcceptLanguage; +} + } // namespace QtWebEngineCore diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h index 42787bc23..818dfda3d 100644 --- a/src/core/browser_context_adapter.h +++ b/src/core/browser_context_adapter.h @@ -40,18 +40,22 @@ #include "qtwebenginecoreglobal.h" #include <QList> +#include <QPointer> #include <QScopedPointer> #include <QSharedData> #include <QString> #include <QVector> +#include "api/qwebenginecookiestoreclient.h" +#include "api/qwebengineurlrequestinterceptor.h" +#include "api/qwebengineurlschemehandler.h" + QT_FORWARD_DECLARE_CLASS(QObject) namespace QtWebEngineCore { class BrowserContextAdapterClient; class BrowserContextQt; -class CustomUrlSchemeHandler; class DownloadManagerDelegateQt; class UserScriptControllerHost; class WebEngineVisitedLinksManager; @@ -69,6 +73,11 @@ public: WebEngineVisitedLinksManager *visitedLinksManager(); DownloadManagerDelegateQt *downloadManagerDelegate(); + QWebEngineCookieStoreClient *cookieStoreClient(); + + QWebEngineUrlRequestInterceptor* requestInterceptor(); + void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); + QList<BrowserContextAdapterClient*> clients() { return m_clients; } void addClient(BrowserContextAdapterClient *adapterClient); void removeClient(BrowserContextAdapterClient *adapterClient); @@ -113,6 +122,13 @@ public: TrackVisitedLinksOnDisk, }; + enum PermissionType { + UnsupportedPermission = 0, + GeolocationPermission = 1, +// Reserved: +// NotificationPermission = 2, + }; + HttpCacheType httpCacheType() const; void setHttpCacheType(BrowserContextAdapter::HttpCacheType); @@ -128,10 +144,19 @@ public: bool trackVisitedLinks() const; bool persistVisitedLinks() const; - QVector<CustomUrlSchemeHandler*> &customUrlSchemeHandlers(); + QHash<QByteArray, QWebEngineUrlSchemeHandler *> &customUrlSchemeHandlers(); void updateCustomUrlSchemeHandlers(); + void addCustomUrlSchemeHandler(const QByteArray &, QWebEngineUrlSchemeHandler *); + bool removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *); + QWebEngineUrlSchemeHandler *takeCustomUrlSchemeHandler(const QByteArray &); UserScriptControllerHost *userScriptController(); + void permissionRequestReply(const QUrl &origin, PermissionType type, bool reply); + + QString httpAcceptLanguageWithoutQualities() const; + QString httpAcceptLanguage() const; + void setHttpAcceptLanguage(const QString &httpAcceptLanguage); + private: QString m_name; bool m_offTheRecord; @@ -139,14 +164,17 @@ private: QScopedPointer<WebEngineVisitedLinksManager> m_visitedLinksManager; QScopedPointer<DownloadManagerDelegateQt> m_downloadManagerDelegate; QScopedPointer<UserScriptControllerHost> m_userScriptController; + QScopedPointer<QWebEngineCookieStoreClient> m_cookieStoreClient; + QPointer<QWebEngineUrlRequestInterceptor> m_requestInterceptor; QString m_dataPath; QString m_cachePath; QString m_httpUserAgent; HttpCacheType m_httpCacheType; + QString m_httpAcceptLanguage; PersistentCookiesPolicy m_persistentCookiesPolicy; VisitedLinksPolicy m_visitedLinksPolicy; - QVector<CustomUrlSchemeHandler*> m_customUrlSchemeHandlers; + QHash<QByteArray, QWebEngineUrlSchemeHandler *> m_customUrlSchemeHandlers; QList<BrowserContextAdapterClient*> m_clients; int m_httpCacheMaxSize; diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp index 7f285b1e5..28486cced 100644 --- a/src/core/browser_context_qt.cpp +++ b/src/core/browser_context_qt.cpp @@ -38,9 +38,10 @@ #include "browser_context_adapter.h" #include "download_manager_delegate_qt.h" -#include "type_conversion.h" -#include "qtwebenginecoreglobal.h" +#include "permission_manager_qt.h" +#include "qtwebenginecoreglobal_p.h" #include "resource_context_qt.h" +#include "type_conversion.h" #include "url_request_context_getter_qt.h" #include "base/time/time.h" @@ -134,6 +135,18 @@ content::SSLHostStateDelegate* BrowserContextQt::GetSSLHostStateDelegate() return 0; } +scoped_ptr<content::ZoomLevelDelegate> BrowserContextQt::CreateZoomLevelDelegate(const base::FilePath&) +{ + return nullptr; +} + +content::PermissionManager *BrowserContextQt::GetPermissionManager() +{ + if (!permissionManager) + permissionManager.reset(new PermissionManagerQt(m_adapter)); + return permissionManager.get(); +} + net::URLRequestContextGetter *BrowserContextQt::CreateRequestContext(content::ProtocolHandlerMap *protocol_handlers) { url_request_getter_ = new URLRequestContextGetterQt(m_adapter, protocol_handlers); diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h index af36b55ab..eccd684a3 100644 --- a/src/core/browser_context_qt.h +++ b/src/core/browser_context_qt.h @@ -47,6 +47,7 @@ namespace QtWebEngineCore { class BrowserContextAdapter; +class PermissionManagerQt; class URLRequestContextGetterQt; class BrowserContextQt : public content::BrowserContext @@ -72,13 +73,17 @@ public: virtual content::PushMessagingService* GetPushMessagingService() Q_DECL_OVERRIDE; virtual content::SSLHostStateDelegate* GetSSLHostStateDelegate() Q_DECL_OVERRIDE; net::URLRequestContextGetter *CreateRequestContext(content::ProtocolHandlerMap *protocol_handlers); + virtual scoped_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(const base::FilePath& partition_path) Q_DECL_OVERRIDE; + virtual content::PermissionManager *GetPermissionManager() Q_DECL_OVERRIDE; + + BrowserContextAdapter *adapter() { return m_adapter; } - BrowserContextAdapter* adapter() { return m_adapter; } private: friend class ContentBrowserClientQt; friend class WebContentsAdapter; scoped_ptr<content::ResourceContext> resourceContext; scoped_refptr<URLRequestContextGetterQt> url_request_getter_; + scoped_ptr<PermissionManagerQt> permissionManager; BrowserContextAdapter *m_adapter; friend class BrowserContextAdapter; diff --git a/src/core/chrome_qt.gyp b/src/core/chrome_qt.gyp index 703ce7525..0f30b7a04 100644 --- a/src/core/chrome_qt.gyp +++ b/src/core/chrome_qt.gyp @@ -19,6 +19,8 @@ '<(chromium_src_dir)/chrome/browser/media/desktop_streams_registry.cc', '<(chromium_src_dir)/chrome/browser/media/desktop_streams_registry.h', '<(chromium_src_dir)/chrome/browser/media/desktop_media_list.h', + '<(chromium_src_dir)/chrome/common/chrome_switches.cc', + '<(chromium_src_dir)/chrome/common/chrome_switches.h', '<(chromium_src_dir)/chrome/common/localized_error.cc', '<(chromium_src_dir)/chrome/common/localized_error.h', ], diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp index ef574eccd..9dfc498ad 100644 --- a/src/core/chromium_gpu_helper.cpp +++ b/src/core/chromium_gpu_helper.cpp @@ -43,18 +43,18 @@ // Including gpu/command_buffer headers before content/gpu headers makes sure that // guards are defined to prevent duplicate definition errors with forward declared // GL typedefs cascading through content header includes. +#include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/texture_manager.h" #include "content/common/gpu/gpu_channel_manager.h" -#include "content/common/gpu/sync_point_manager.h" #include "content/gpu/gpu_child_thread.h" #ifdef Q_OS_QNX #include "content/common/gpu/stream_texture_qnx.h" #endif -static void addSyncPointCallbackDelegate(content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback) +static void addSyncPointCallbackDelegate(gpu::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback) { syncPointManager->AddSyncPointCallback(sync_point, callback); } @@ -78,13 +78,13 @@ base::MessageLoop *gpu_message_loop() return content::GpuChildThread::instance()->message_loop(); } -content::SyncPointManager *sync_point_manager() +gpu::SyncPointManager *sync_point_manager() { content::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager(); return gpuChannelManager->sync_point_manager(); } -void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback) +void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, gpu::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback) { // We need to set our callback from the GPU thread, where the SyncPointManager lives. gpuMessageLoop->PostTask(FROM_HERE, base::Bind(&addSyncPointCallbackDelegate, make_scoped_refptr(syncPointManager), sync_point, callback)); diff --git a/src/core/chromium_gpu_helper.h b/src/core/chromium_gpu_helper.h index 936ad1d24..6242dd068 100644 --- a/src/core/chromium_gpu_helper.h +++ b/src/core/chromium_gpu_helper.h @@ -47,12 +47,9 @@ namespace base { class MessageLoop; } -namespace content { -class SyncPointManager; -} - namespace gpu { struct Mailbox; +class SyncPointManager; namespace gles2 { class MailboxManager; class Texture; @@ -66,10 +63,10 @@ class Texture; QMap<uint32, gfx::TransferableFence> transferFences(); base::MessageLoop *gpu_message_loop(); -content::SyncPointManager *sync_point_manager(); +gpu::SyncPointManager *sync_point_manager(); gpu::gles2::MailboxManager *mailbox_manager(); -void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback); +void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, gpu::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback); gpu::gles2::Texture* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::Mailbox& mailbox); unsigned int service_id(gpu::gles2::Texture *tex); diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index 5af8a6ad8..b9ce722dd 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -37,8 +37,9 @@ #include "chromium_overrides.h" #include "gl_context_qt.h" -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include "web_contents_view_qt.h" + #include "base/values.h" #include "content/browser/renderer_host/pepper/pepper_truetype_font_list.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" @@ -47,6 +48,8 @@ #include <QGuiApplication> #include <QScreen> #include <QWindow> +#include <QFontDatabase> +#include <QStringList> #if defined(USE_X11) #include "ui/gfx/x/x11_types.h" @@ -115,8 +118,17 @@ namespace content { // content/common/font_list.h scoped_ptr<base::ListValue> GetFontList_SlowBlocking() { - QT_NOT_USED - return scoped_ptr<base::ListValue>(new base::ListValue); + scoped_ptr<base::ListValue> font_list(new base::ListValue); + + QFontDatabase database; + for (auto family : database.families()){ + base::ListValue* font_item = new base::ListValue(); + font_item->Append(new base::StringValue(family.toStdString())); + font_item->Append(new base::StringValue(family.toStdString())); // should be localized name. + // TODO: Support localized family names. + font_list->Append(font_item); + } + return font_list.Pass(); } #if defined(ENABLE_PLUGINS) @@ -142,39 +154,6 @@ OSExchangeData::Provider* OSExchangeData::CreateProvider() return 0; } -} - -namespace gfx { - -// Stubs for these unused functions that are stripped in case -// of a release aura build but a debug build needs the symbols. - -RenderText* RenderText::CreateNativeInstance() -{ - QT_NOT_USED; - return 0; -} - -#if defined(OS_LINUX) -PlatformFont* PlatformFont::CreateDefault() -{ - QT_NOT_USED; - return 0; -} - -PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont) -{ - QT_NOT_USED; - return 0; -} - -PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string&, int) -{ - QT_NOT_USED; - return 0; -} -#endif - -} // namespace gfx +} // namespace ui #endif // defined(USE_AURA) && !defined(USE_OZONE) diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 797f5c7f4..206392840 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -331,7 +331,7 @@ SkBitmap ClipboardQt::ReadImage(ui::ClipboardType type) const 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); + image = image.convertToFormat(QImage::Format_ARGB32); SkBitmap bitmap; bitmap.setInfo(SkImageInfo::MakeN32(image.width(), image.height(), kOpaque_SkAlphaType)); bitmap.setPixels(const_cast<uchar*>(image.constBits())); @@ -361,7 +361,7 @@ void ClipboardQt::ReadData(const FormatType& format, std::string* result) const *result = std::string(byteArray.constData(), byteArray.length()); } -uint64 ClipboardQt::GetSequenceNumber(ui::ClipboardType type) +uint64 ClipboardQt::GetSequenceNumber(ui::ClipboardType type) const { return clipboardChangeObserver()->getSequenceNumber(type == ui::CLIPBOARD_TYPE_COPY_PASTE ? QClipboard::Clipboard : QClipboard::Selection); } diff --git a/src/core/clipboard_qt.h b/src/core/clipboard_qt.h index 4c7e6ab59..ee1fc7440 100644 --- a/src/core/clipboard_qt.h +++ b/src/core/clipboard_qt.h @@ -62,7 +62,7 @@ private: class ClipboardQt : public ui::Clipboard { public: - virtual uint64 GetSequenceNumber(ui::ClipboardType type) Q_DECL_OVERRIDE; + virtual uint64 GetSequenceNumber(ui::ClipboardType type) const 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; diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index c692ee5ca..25a995b27 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -31,6 +31,9 @@ IPC_MESSAGE_ROUTED1(QtRenderViewObserver_FetchDocumentMarkup, IPC_MESSAGE_ROUTED1(QtRenderViewObserver_FetchDocumentInnerText, uint64 /* requestId */) +IPC_MESSAGE_ROUTED1(QtRenderViewObserver_SetBackgroundColor, + uint32 /* color */) + IPC_MESSAGE_ROUTED1(WebChannelIPCTransport_Message, std::vector<char> /*binaryJSON*/) // User scripts messages diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri index 041b094a1..f0bf6cb23 100644 --- a/src/core/config/desktop_linux.pri +++ b/src/core/config/desktop_linux.pri @@ -1,21 +1,10 @@ GYP_ARGS += "-D qt_os=\"desktop_linux\"" +include(linux.pri) + GYP_CONFIG += \ desktop_linux=1 \ - toolkit_uses_gtk=0 \ - use_aura=1 \ - use_ash=0 \ - use_cairo=0 \ - use_clipboard_aurax11=0 \ - use_cups=0 \ - use_gconf=0 \ - use_gio=0 \ - use_gnome_keyring=0 \ - use_kerberos=0 \ - use_pango=0 \ - host_clang=0 \ - clang=0 \ - -contains(QT_CONFIG, system-jpeg): GYP_CONFIG += use_system_libjpeg=1 + enable_plugins=1 \ -!contains(QT_CONFIG, pulseaudio): GYP_CONFIG += use_pulseaudio=0 +linux-clang: GYP_CONFIG += clang=1 host_clang=1 clang_use_chrome_plugins=0 make_clang_dir=/usr +else: GYP_CONFIG += clang=0 host_clang=0 diff --git a/src/core/config/embedded_linux.pri b/src/core/config/embedded_linux.pri index cc8c40f8e..50f94147e 100644 --- a/src/core/config/embedded_linux.pri +++ b/src/core/config/embedded_linux.pri @@ -1,7 +1,8 @@ GYP_ARGS += "-D qt_os=\"embedded_linux\" -I config/embedded_linux.gypi" +include(linux.pri) + GYP_CONFIG += \ - build_ffmpegsumo=1 \ clang=0 \ desktop_linux=0 \ disable_nacl=1 \ @@ -24,31 +25,17 @@ GYP_CONFIG += \ gtest_target_type=none \ host_clang=0 \ notifications=0 \ + ozone_auto_platforms=0 \ ozone_platform_dri=0 \ ozone_platform_test=0 \ p2p_apis=0 \ safe_browsing=0 \ toolkit_views=1 \ - use_ash=0 \ - use_aura=1 \ - use_cairo=0 \ - use_clipboard_aurax11=0 \ - use_cups=0 \ use_custom_freetype=0 \ - use_gconf=0 \ - use_gio=0 \ - use_gnome_keyring=0 \ - use_kerberos=0 \ use_libpci=0 \ - use_openssl=1 \ use_ozone=1 \ - use_pango=0 \ use_system_fontconfig=1 \ - use_system_icu=1 \ icu_use_data_file_flag=0 \ use_x11=0 \ v8_use_snapshot=false \ want_separate_host_toolset=1 \ - -contains(QT_CONFIG, system-jpeg): GYP_CONFIG += use_system_libjpeg=1 -!contains(QT_CONFIG, pulseaudio): GYP_CONFIG += use_pulseaudio=0 diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri new file mode 100644 index 000000000..8d736d0c1 --- /dev/null +++ b/src/core/config/linux.pri @@ -0,0 +1,45 @@ +# linux_use_bundled_gold currently relies on a hardcoded relative path from chromium/src/out/(Release|Debug) +# Disable it along with the -Wl,--threads flag just in case gold isn't installed on the system. +GYP_CONFIG += \ + linux_use_bundled_gold=0 \ + linux_use_bundled_binutils=0 \ + linux_use_gold_flags=0 \ + +GYP_CONFIG += \ + toolkit_uses_gtk=0 \ + use_ash=0 \ + use_aura=1 \ + use_cairo=0 \ + use_clipboard_aurax11=0 \ + use_cups=0 \ + use_gconf=0 \ + use_gio=0 \ + use_gnome_keyring=0 \ + use_kerberos=0 \ + use_pango=0 + +!use?(nss) { + GYP_CONFIG += use_nss_certs=0 \ + use_openssl=1 \ + use_openssl_certs=1 +} + +contains(QT_CONFIG, system-zlib): use?(system_minizip): GYP_CONFIG += use_system_zlib=1 +contains(QT_CONFIG, system-png): GYP_CONFIG += use_system_libpng=1 +contains(QT_CONFIG, system-jpeg): GYP_CONFIG += use_system_libjpeg=1 +contains(QT_CONFIG, system-harfbuzz): GYP_CONFIG += use_system_harfbuzz=1 +!contains(QT_CONFIG, pulseaudio): GYP_CONFIG += use_pulseaudio=0 + +use?(system_libevent): GYP_CONFIG += use_system_libevent=1 +use?(system_libwebp): GYP_CONFIG += use_system_libwebp=1 +use?(system_libsrtp): GYP_CONFIG += use_system_libsrtp=1 +use?(system_libxslt): GYP_CONFIG += use_system_libxml=1 +use?(system_flac): GYP_CONFIG += use_system_flac=1 +use?(system_jsoncpp): GYP_CONFIG += use_system_jsoncpp=1 +use?(system_opus): GYP_CONFIG += use_system_opus=1 +use?(system_snappy): GYP_CONFIG += use_system_snappy=1 +use?(system_speex): GYP_CONFIG += use_system_speex=1 +use?(system_vpx): GYP_CONFIG += use_system_libvpx=1 +use?(system_icu): GYP_CONFIG += use_system_icu=1 +use?(system_ffmpeg): GYP_CONFIG += use_system_ffmpeg=1 + diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri index 3f42b6fd7..93c77623c 100644 --- a/src/core/config/mac_osx.pri +++ b/src/core/config/mac_osx.pri @@ -14,7 +14,8 @@ GYP_CONFIG += \ mac_sdk_min=\"10.7\" \ mac_deployment_target=\"$${QMAKE_MACOSX_DEPLOYMENT_TARGET}\" \ make_clang_dir=\"$${QMAKE_CLANG_DIR}\" \ - clang_use_chrome_plugins=0 + clang_use_chrome_plugins=0 \ + enable_plugins=1 QMAKE_MAC_SDK_PATH = "$$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path)" exists($$QMAKE_MAC_SDK_PATH): GYP_CONFIG += mac_sdk_path=\"$${QMAKE_MAC_SDK_PATH}\" diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri index f7644c83b..602afbc67 100644 --- a/src/core/config/windows.pri +++ b/src/core/config/windows.pri @@ -28,3 +28,17 @@ contains(QT_CONFIG, angle) { GYP_ARGS += "-D qt_gl=\"opengl\"" } +msvc { + equals(MSVC_VER, 12.0) { + MSVS_VERSION = 2013 + } else:equals(MSVC_VER, 14.0) { + MSVS_VERSION = 2015 + } else { + fatal("Visual Studio compiler version \"$$MSVC_VER\" is not supported by Qt WebEngine") + } + + GYP_ARGS += "-G msvs_version=$$MSVS_VERSION" + +} else { + fatal("Qt WebEngine for Windows can only be built with the Microsoft Visual Studio C++ compiler") +} diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index fdfbaf0f5..91cd0b0c4 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -56,6 +56,7 @@ #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_share_group.h" +#include "ui/gl/gpu_timing.h" #include "access_token_store_qt.h" #include "browser_context_adapter.h" @@ -74,6 +75,12 @@ #include "web_engine_context.h" #include "web_engine_library_info.h" +#if defined(ENABLE_PLUGINS) +#include "content/public/browser/browser_ppapi_host.h" +#include "ppapi/host/ppapi_host.h" +#include "renderer/pepper/pepper_host_factory_qt.h" +#endif + #include <QGuiApplication> #include <QLocale> #include <QOpenGLContext> @@ -277,7 +284,11 @@ public: virtual bool MakeCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; } virtual void ReleaseCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); } virtual bool IsCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; } - virtual void SetSwapInterval(int) Q_DECL_OVERRIDE { Q_UNREACHABLE(); } + virtual void OnSetSwapInterval(int) Q_DECL_OVERRIDE { Q_UNREACHABLE(); } + virtual scoped_refptr<gfx::GPUTimingClient> CreateGPUTimingClient() Q_DECL_OVERRIDE + { + return nullptr; + } private: void *m_handle; @@ -360,9 +371,8 @@ content::MediaObserver *ContentBrowserClientQt::GetMediaObserver() return MediaCaptureDevicesDispatcher::GetInstance(); } -void ContentBrowserClientQt::OverrideWebkitPrefs(content::RenderViewHost *rvh, const GURL &url, content::WebPreferences *web_prefs) +void ContentBrowserClientQt::OverrideWebkitPrefs(content::RenderViewHost *rvh, content::WebPreferences *web_prefs) { - Q_UNUSED(url); if (content::WebContents *webContents = rvh->GetDelegate()->GetAsWebContents()) static_cast<WebContentsDelegateQt*>(webContents->GetDelegate())->overrideWebPreferences(webContents, web_prefs); } @@ -402,41 +412,6 @@ void ContentBrowserClientQt::AllowCertificateError(int render_process_id, int re contentsDelegate->allowCertificateError(errorController); } -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(bridge_id); - Q_UNUSED(user_gesture); - 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); -} - -blink::WebNotificationPermission ContentBrowserClientQt::CheckDesktopNotificationPermission(const GURL&, content::ResourceContext *, int ) -{ - return blink::WebNotificationPermission::WebNotificationPermissionDenied; -} - content::LocationProvider *ContentBrowserClientQt::OverrideSystemLocationProvider() { #ifdef QT_USE_POSITIONING @@ -451,6 +426,11 @@ std::string ContentBrowserClientQt::GetApplicationLocale() return WebEngineLibraryInfo::getApplicationLocale(); } +std::string ContentBrowserClientQt::GetAcceptLangs(content::BrowserContext *context) +{ + return static_cast<BrowserContextQt*>(context)->adapter()->httpAcceptLanguage().toStdString(); +} + void ContentBrowserClientQt::AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) { Q_UNUSED(child_process_id); @@ -460,6 +440,13 @@ void ContentBrowserClientQt::AppendExtraCommandLineSwitches(base::CommandLine* c command_line->AppendSwitchASCII(switches::kLang, GetApplicationLocale()); } +#if defined(ENABLE_PLUGINS) + void ContentBrowserClientQt::DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) { + browser_host->GetPpapiHost()->AddHostFactoryFilter( + scoped_ptr<ppapi::host::HostFactory>(new QtWebEngineCore::PepperHostFactoryQt(browser_host))); + } +#endif + 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 0af5ae9d3..eea7d2a22 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -40,7 +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 "third_party/WebKit/public/platform/modules/notifications/WebNotificationPermission.h" #include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE @@ -51,6 +51,11 @@ class URLRequestContextGetter; namespace content { class BrowserContext; class BrowserMainParts; + +#if defined(ENABLE_PLUGINS) +class BrowserPpapiHost; +#endif + class DevToolsManagerDelegate; class RenderProcessHost; class RenderViewHostDelegateView; @@ -83,7 +88,7 @@ public: virtual content::MediaObserver* GetMediaObserver() 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 OverrideWebkitPrefs(content::RenderViewHost *, content::WebPreferences *) Q_DECL_OVERRIDE; virtual void AllowCertificateError( int render_process_id, int render_frame_id, @@ -96,26 +101,18 @@ public: bool expired_previous_decision, const base::Callback<void(bool)>& callback, content::CertificateRequestResultType* result) Q_DECL_OVERRIDE; - virtual void 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_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; - virtual blink::WebNotificationPermission CheckDesktopNotificationPermission(const GURL& source_origin, content::ResourceContext* context, int render_process_id) Q_DECL_OVERRIDE; - virtual std::string GetApplicationLocale() Q_DECL_OVERRIDE; + std::string GetAcceptLangs(content::BrowserContext* context) Q_DECL_OVERRIDE; virtual void AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) Q_DECL_OVERRIDE; +#if defined(ENABLE_PLUGINS) + virtual void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) Q_DECL_OVERRIDE; +#endif + private: BrowserMainPartsQt* m_browserMainParts; scoped_ptr<ResourceDispatcherHostDelegateQt> m_resourceDispatcherHostDelegate; diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index 20a8df75e..01e1fe383 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -36,11 +36,119 @@ #include "content_client_qt.h" +#include "base/command_line.h" #include "base/strings/string_piece.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "content/public/common/content_constants.h" #include "content/public/common/user_agent.h" #include "ui/base/layout.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "type_conversion.h" + +#include <QCoreApplication> +#include <QFile> +#include <QStringBuilder> + +#if defined(ENABLE_PLUGINS) +#include "content/public/common/pepper_plugin_info.h" +#include "ppapi/shared_impl/ppapi_permissions.h" + +static const int32 kPepperFlashPermissions = ppapi::PERMISSION_DEV | + ppapi::PERMISSION_PRIVATE | + ppapi::PERMISSION_BYPASS_USER_GESTURE | + ppapi::PERMISSION_FLASH; + +namespace switches { +const char kPpapiFlashPath[] = "ppapi-flash-path"; +const char kPpapiFlashVersion[] = "ppapi-flash-version"; +} + +// Adopted from chrome_content_client.cc +content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path, const std::string& version) +{ + content::PepperPluginInfo plugin; + + plugin.is_out_of_process = true; + plugin.name = content::kFlashPluginName; + plugin.path = path; + plugin.permissions = kPepperFlashPermissions; + + std::vector<std::string> flash_version_numbers; + base::SplitString(version, '.', &flash_version_numbers); + if (flash_version_numbers.size() < 1) + flash_version_numbers.push_back("11"); + else if (flash_version_numbers[0].empty()) + flash_version_numbers[0] = "11"; + if (flash_version_numbers.size() < 2) + flash_version_numbers.push_back("2"); + if (flash_version_numbers.size() < 3) + flash_version_numbers.push_back("999"); + if (flash_version_numbers.size() < 4) + flash_version_numbers.push_back("999"); + + // E.g., "Shockwave Flash 10.2 r154": + plugin.description = plugin.name + " " + flash_version_numbers[0] + "." + flash_version_numbers[1] + " r" + flash_version_numbers[2]; + plugin.version = JoinString(flash_version_numbers, '.'); + content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType, + content::kFlashPluginSwfExtension, + content::kFlashPluginSwfDescription); + plugin.mime_types.push_back(swf_mime_type); + content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType, + content::kFlashPluginSplExtension, + content::kFlashPluginSplDescription); + plugin.mime_types.push_back(spl_mime_type); + + return plugin; +} + +void AddPepperFlashFromSystem(std::vector<content::PepperPluginInfo>* plugins) +{ + QStringList pluginPaths; +#if defined(Q_OS_WIN) && defined(Q_PROCESSOR_X86_32) + QDir pluginDir("C:/Windows/SysWOW64/Macromed/Flash"); + pluginDir.setFilter(QDir::Files); + QStringList nameFilters("pepflashplayer*.dll"); + pluginPaths << pluginDir.entryList(nameFilters); +#endif +#if defined(Q_OS_OSX) + pluginPaths << "/Library/Internet Plug-Ins/PepperFlashPlayer/PepperFlashPlayer.plugin"; // Mac OS X +#endif +#if defined(Q_OS_LINUX) + pluginPaths << "/usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so" // Ubuntu + << "/usr/lib/PepperFlash/libpepflashplayer.so" // Arch + << "/usr/lib64/chromium/PepperFlash/libpepflashplayer.so"; // OpenSuSE +#endif + for (auto it = pluginPaths.constBegin(); it != pluginPaths.constEnd(); ++it) { + if (!QFile(*it).exists()) + continue; + plugins->push_back(CreatePepperFlashInfo(QtWebEngineCore::toFilePath(*it), std::string())); + return; + } +} + +void AddPepperFlashFromCommandLine(std::vector<content::PepperPluginInfo>* plugins) +{ + const base::CommandLine::StringType flash_path = base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(switches::kPpapiFlashPath); + if (flash_path.empty() || !QFile(QtWebEngineCore::toQt(flash_path)).exists()) + return; + + // Read pepper flash plugin version from command-line. (e.g. 16.0.0.235) + std::string flash_version = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kPpapiFlashVersion); + plugins->push_back(CreatePepperFlashInfo(base::FilePath(flash_path), flash_version)); +} + +namespace QtWebEngineCore { + +void ContentClientQt::AddPepperPlugins(std::vector<content::PepperPluginInfo>* plugins) +{ + AddPepperFlashFromSystem(plugins); + AddPepperFlashFromCommandLine(plugins); +} + +} +#endif #include <QCoreApplication> #include <QStringBuilder> diff --git a/src/core/content_client_qt.h b/src/core/content_client_qt.h index f68282dcf..309e049dc 100644 --- a/src/core/content_client_qt.h +++ b/src/core/content_client_qt.h @@ -48,6 +48,10 @@ class ContentClientQt : public content::ContentClient { public: static std::string getUserAgent(); +#if defined(ENABLE_PLUGINS) + virtual void AddPepperPlugins(std::vector<content::PepperPluginInfo>* plugins) Q_DECL_OVERRIDE; +#endif + virtual base::StringPiece GetDataResource(int, ui::ScaleFactor) const Q_DECL_OVERRIDE; virtual std::string GetUserAgent() const Q_DECL_OVERRIDE { return getUserAgent(); } virtual base::string16 GetLocalizedString(int message_id) const Q_DECL_OVERRIDE; diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index 4003823b1..0688fb015 100644 --- a/src/core/content_main_delegate_qt.cpp +++ b/src/core/content_main_delegate_qt.cpp @@ -72,7 +72,7 @@ void ContentMainDelegateQt::PreSandboxStartup() // Suppress info, warning and error messages per default. int logLevel = logging::LOG_FATAL; - CommandLine* parsedCommandLine = CommandLine::ForCurrentProcess(); + base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess(); if (parsedCommandLine->HasSwitch(switches::kLoggingLevel)) { std::string logLevelValue = parsedCommandLine->GetSwitchValueASCII(switches::kLoggingLevel); int level = 0; diff --git a/src/core/cookie_monster_delegate_qt.cpp b/src/core/cookie_monster_delegate_qt.cpp new file mode 100644 index 000000000..7622614ca --- /dev/null +++ b/src/core/cookie_monster_delegate_qt.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "cookie_monster_delegate_qt.h" + +#include "base/bind.h" +#include "content/public/browser/browser_thread.h" +#include "net/cookies/cookie_util.h" + +#include "api/qwebenginecookiestoreclient.h" +#include "api/qwebenginecookiestoreclient_p.h" +#include "type_conversion.h" + +#include <QStringBuilder> + +namespace QtWebEngineCore { + +static GURL sourceUrlForCookie(const QNetworkCookie &cookie) { + QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path()); + return net::cookie_util::CookieOriginToURL(urlFragment.toStdString(), /* is_https */ cookie.isSecure()); +} + +static void onSetCookieCallback(QWebEngineCookieStoreClientPrivate *client, qint64 callbackId, bool success) { + client->onSetCallbackResult(callbackId, success); +} + +static void onDeleteCookiesCallback(QWebEngineCookieStoreClientPrivate *client, qint64 callbackId, int numCookies) { + client->onDeleteCallbackResult(callbackId, numCookies); +} + +static void onGetAllCookiesCallback(QWebEngineCookieStoreClientPrivate *client, qint64 callbackId, const net::CookieList& cookies) { + QByteArray rawCookies; + for (auto&& cookie: cookies) + rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n"); + + client->onGetAllCallbackResult(callbackId, rawCookies); +} + +CookieMonsterDelegateQt::CookieMonsterDelegateQt() + : m_client(0) + , m_cookieMonster(0) +{ + +} + +CookieMonsterDelegateQt::~CookieMonsterDelegateQt() +{ + +} + +bool CookieMonsterDelegateQt::hasCookieMonster() +{ + return m_cookieMonster.get(); +} + +void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId) +{ + net::CookieMonster::GetCookieListCallback callback = base::Bind(&onGetAllCookiesCallback, m_client->d_func(), callbackId); + m_cookieMonster->GetAllCookiesAsync(callback); +} + +void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin) +{ + Q_ASSERT(hasCookieMonster()); + Q_ASSERT(m_client); + + net::CookieStore::SetCookiesCallback callback; + if (callbackId != CallbackDirectory::NoCallbackId) + callback = base::Bind(&onSetCookieCallback, m_client->d_func(), callbackId); + + net::CookieOptions options; + options.set_include_httponly(); + + GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); + + m_cookieMonster->SetCookieWithOptionsAsync(gurl, cookie.toRawForm().toStdString(), options, callback); +} + +void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin) +{ + Q_ASSERT(hasCookieMonster()); + Q_ASSERT(m_client); + + GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin); + + m_cookieMonster->DeleteCookieAsync(gurl, cookie.name().toStdString(), base::Closure()); +} + +void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId) +{ + Q_ASSERT(hasCookieMonster()); + Q_ASSERT(m_client); + + net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId); + m_cookieMonster->DeleteSessionCookiesAsync(callback); +} + +void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId) +{ + Q_ASSERT(hasCookieMonster()); + Q_ASSERT(m_client); + + net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId); + m_cookieMonster->DeleteAllAsync(callback); +} + +void CookieMonsterDelegateQt::setCookieMonster(net::CookieMonster* monster) +{ + m_cookieMonster = monster; + + if (m_client) + m_client->d_func()->processPendingUserCookies(); +} + +void CookieMonsterDelegateQt::setClient(QWebEngineCookieStoreClient *client) +{ + m_client = client; + + if (!m_client) + return; + + m_client->d_ptr->delegate = this; + + if (hasCookieMonster()) + m_client->d_func()->processPendingUserCookies(); +} + +bool CookieMonsterDelegateQt::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) +{ + if (!m_client) + return true; + + return m_client->d_ptr->canSetCookie(firstPartyUrl, cookieLine, url); +} + +void CookieMonsterDelegateQt::OnCookieChanged(const net::CanonicalCookie& cookie, bool removed, ChangeCause cause) +{ + if (!m_client) + return; + m_client->d_ptr->onCookieChanged(toQt(cookie), removed); +} + +} diff --git a/src/core/cookie_monster_delegate_qt.h b/src/core/cookie_monster_delegate_qt.h new file mode 100644 index 000000000..7592d57fa --- /dev/null +++ b/src/core/cookie_monster_delegate_qt.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 COOKIE_MONSTER_DELEGATE_QT_H +#define COOKIE_MONSTER_DELEGATE_QT_H + +#include "qtwebenginecoreglobal.h" + +QT_WARNING_PUSH +// For some reason adding -Wno-unused-parameter to QMAKE_CXXFLAGS has no +// effect with clang, so use a pragma for these dirty chromium headers +QT_WARNING_DISABLE_CLANG("-Wunused-parameter") +#include "base/memory/ref_counted.h" +#include "net/cookies/cookie_monster.h" +QT_WARNING_POP + +#include <QList> +#include <QNetworkCookie> +#include <QPointer> + +QT_FORWARD_DECLARE_CLASS(QWebEngineCookieStoreClient) + +namespace QtWebEngineCore { + +// Extends net::CookieMonster::kDefaultCookieableSchemes with qrc, without enabling +// cookies for the file:// scheme, which is disabled by default in Chromium. +// Since qrc:// is similar to file:// and there are some unknowns about how +// to correctly handle file:// cookies, qrc:// should only be used for testing. +static const char* const kCookieableSchemes[] = + { "http", "https", "qrc", "ws", "wss" }; + +class QWEBENGINE_EXPORT CookieMonsterDelegateQt: public net::CookieMonsterDelegate { + QPointer<QWebEngineCookieStoreClient> m_client; + scoped_refptr<net::CookieMonster> m_cookieMonster; +public: + CookieMonsterDelegateQt(); + ~CookieMonsterDelegateQt(); + + bool hasCookieMonster(); + + void setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin); + void deleteCookie(const QNetworkCookie &cookie, const QUrl &origin); + void getAllCookies(quint64 callbackId); + void deleteSessionCookies(quint64 callbackId); + void deleteAllCookies(quint64 callbackId); + + void setCookieMonster(net::CookieMonster* monster); + void setClient(QWebEngineCookieStoreClient *client); + + bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url); + void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed, ChangeCause cause) override; +}; + +} + +#endif // COOKIE_MONSTER_DELEGATE_QT_H diff --git a/src/core/core.pro b/src/core/core.pro index cf00f39cb..7ddad4ed6 100644 --- a/src/core/core.pro +++ b/src/core/core.pro @@ -8,13 +8,14 @@ core_gyp_generator.file = core_gyp_generator.pro gyp_run.file = gyp_run.pro gyp_run.depends = core_gyp_generator +core_api.file = api/core_api.pro +core_api.depends = gyp_run + # This will take the compile output of ninja, and link+deploy the final binary. core_module.file = core_module.pro -core_module.depends = gyp_run +core_module.depends = core_api -SUBDIRS += core_gyp_generator \ - gyp_run \ - core_module +SUBDIRS += core_gyp_generator !win32 { # gyp_configure_host.pro and gyp_configure_target.pro are phony pro files that @@ -28,3 +29,7 @@ SUBDIRS += core_gyp_generator \ gyp_run.depends += gyp_configure_host gyp_configure_target SUBDIRS += gyp_configure_host gyp_configure_target } + +SUBDIRS += gyp_run \ + core_api \ + core_module diff --git a/src/core/core_common.pri b/src/core/core_common.pri index cefde4302..1ea4e1862 100644 --- a/src/core/core_common.pri +++ b/src/core/core_common.pri @@ -6,7 +6,7 @@ QT += qml quick webchannel QT_PRIVATE += quick-private gui-private core-private # Make QtCreator happy. -CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$${getChromiumSrcDir()} +CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir() INCLUDEPATH += $$CHROMIUM_SRC_DIR qtHaveModule(positioning):QT += positioning diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro index c745fd19e..813626dc3 100644 --- a/src/core/core_gyp_generator.pro +++ b/src/core/core_gyp_generator.pro @@ -18,17 +18,18 @@ DEFINES += QT_NO_KEYWORDS \ # Assume that we want mobile touch and low-end hardware behaviors # whenever we are cross compiling. -cross_compile: DEFINES += QTWEBENGINE_MOBILE_SWITCHES +cross_compile: DEFINES += QTWEBENGINE_EMBEDDED_SWITCHES contains(QT_CONFIG, egl): CONFIG += egl else: DEFINES += QT_NO_EGL RESOURCES += devtools.qrc -INCLUDEPATH += $$PWD +INCLUDEPATH += $$PWD $$PWD/api SOURCES = \ access_token_store_qt.cpp \ + authentication_dialog_controller.cpp \ browser_accessibility_manager_qt.cpp \ browser_accessibility_qt.cpp \ browser_context_adapter.cpp \ @@ -42,12 +43,13 @@ SOURCES = \ content_client_qt.cpp \ content_browser_client_qt.cpp \ content_main_delegate_qt.cpp \ + cookie_monster_delegate_qt.cpp \ custom_protocol_handler.cpp \ - custom_url_scheme_handler.cpp \ delegated_frame_node.cpp \ desktop_screen_qt.cpp \ dev_tools_http_handler_delegate_qt.cpp \ download_manager_delegate_qt.cpp \ + file_picker_controller.cpp \ gl_context_qt.cpp \ gl_surface_qt.cpp \ javascript_dialog_controller.cpp \ @@ -56,11 +58,18 @@ SOURCES = \ native_web_keyboard_event_qt.cpp \ network_delegate_qt.cpp \ ozone_platform_eglfs.cpp \ + permission_manager_qt.cpp \ process_main.cpp \ + proxy_config_service_qt.cpp \ qrc_protocol_handler_qt.cpp \ qt_render_view_observer_host.cpp \ render_widget_host_view_qt.cpp \ renderer/content_renderer_client_qt.cpp \ + renderer/pepper/pepper_flash_browser_host_qt.cpp \ + renderer/pepper/pepper_flash_renderer_host_qt.cpp \ + renderer/pepper/pepper_host_factory_qt.cpp \ + renderer/pepper/pepper_renderer_host_factory_qt.cpp \ + renderer/qt_render_frame_observer.cpp \ renderer/qt_render_view_observer.cpp \ renderer/user_script_controller.cpp \ renderer/web_channel_ipc_transport.cpp \ @@ -89,6 +98,8 @@ SOURCES = \ HEADERS = \ access_token_store_qt.h \ + authentication_dialog_controller_p.h \ + authentication_dialog_controller.h \ browser_accessibility_manager_qt.h \ browser_accessibility_qt.h \ browser_context_adapter.h \ @@ -103,13 +114,14 @@ HEADERS = \ content_client_qt.h \ content_browser_client_qt.h \ content_main_delegate_qt.h \ + cookie_monster_delegate_qt.h \ custom_protocol_handler.h \ - custom_url_scheme_handler.h \ delegated_frame_node.h \ desktop_screen_qt.h \ dev_tools_http_handler_delegate_qt.h \ download_manager_delegate_qt.h \ chromium_gpu_helper.h \ + file_picker_controller.h \ gl_context_qt.h \ gl_surface_qt.h \ javascript_dialog_controller_p.h \ @@ -118,13 +130,19 @@ HEADERS = \ media_capture_devices_dispatcher.h \ network_delegate_qt.h \ ozone_platform_eglfs.h \ + permission_manager_qt.h \ process_main.h \ + proxy_config_service_qt.h \ qrc_protocol_handler_qt.h \ qt_render_view_observer_host.h \ - qtwebenginecoreglobal.h \ render_widget_host_view_qt.h \ render_widget_host_view_qt_delegate.h \ renderer/content_renderer_client_qt.h \ + renderer/pepper/pepper_flash_browser_host_qt.h \ + renderer/pepper/pepper_flash_renderer_host_qt.h \ + renderer/pepper/pepper_host_factory_qt.h \ + renderer/pepper/pepper_renderer_host_factory_qt.h \ + renderer/qt_render_frame_observer.h \ renderer/qt_render_view_observer.h \ renderer/user_script_controller.h \ renderer/web_channel_ipc_transport.h \ diff --git a/src/core/core_module.pro b/src/core/core_module.pro index e6a36332f..68d46cd5a 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -9,10 +9,31 @@ QMAKE_INFO_PLIST = Info_mac.plist error("Could not find the linking information that gyp should have generated.") } -# We distribute the module binary but headers are only available in-tree. -CONFIG += no_module_headers load(qt_module) +api_library_name = qtwebenginecoreapi$$qtPlatformTargetSuffix() +api_library_path = $$OUT_PWD/api/$$getConfigDir() + + +LIBS_PRIVATE += -L$$api_library_path +CONFIG *= no_smart_library_merge +osx { + LIBS_PRIVATE += -Wl,-force_load,$${api_library_path}$${QMAKE_DIR_SEP}lib$${api_library_name}.a +} else:msvc { + # Simulate -whole-archive by passing the list of object files that belong to the public + # API library as response file to the linker. + QMAKE_LFLAGS += /OPT:REF + QMAKE_LFLAGS += @$${api_library_path}$${QMAKE_DIR_SEP}$${api_library_name}.lib.objects +} else { + LIBS_PRIVATE += -Wl,-whole-archive -l$$api_library_name -Wl,-no-whole-archive +} + +win32-msvc* { + POST_TARGETDEPS += $${api_library_path}$${QMAKE_DIR_SEP}$${api_library_name}.lib +} else { + POST_TARGETDEPS += $${api_library_path}$${QMAKE_DIR_SEP}lib$${api_library_name}.a +} + # Using -Wl,-Bsymbolic-functions seems to confuse the dynamic linker # and doesn't let Chromium get access to libc symbols through dlsym. CONFIG -= bsymbolic_functions @@ -31,17 +52,8 @@ resources.files = $$REPACK_DIR/qtwebengine_resources.pak \ $$REPACK_DIR/qtwebengine_resources_100p.pak \ $$REPACK_DIR/qtwebengine_resources_200p.pak -PLUGIN_EXTENSION = .so -PLUGIN_PREFIX = lib -osx: PLUGIN_PREFIX = -win32 { - PLUGIN_EXTENSION = .dll - PLUGIN_PREFIX = -} icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat -plugins.files = $$OUT_PWD/$$getConfigDir()/$${PLUGIN_PREFIX}ffmpegsumo$${PLUGIN_EXTENSION} - !debug_and_release|!build_all|CONFIG(release, debug|release) { contains(QT_CONFIG, qt_framework) { locales.version = Versions @@ -50,12 +62,10 @@ plugins.files = $$OUT_PWD/$$getConfigDir()/$${PLUGIN_PREFIX}ffmpegsumo$${PLUGIN_ resources.path = Resources icu.version = Versions icu.path = Resources - plugins.version = Versions - plugins.path = Libraries # No files, this prepares the bundle Helpers symlink, process.pro will create the directories qtwebengineprocessplaceholder.version = Versions qtwebengineprocessplaceholder.path = Helpers - QMAKE_BUNDLE_DATA += icu locales resources plugins qtwebengineprocessplaceholder + QMAKE_BUNDLE_DATA += icu locales resources qtwebengineprocessplaceholder } else { locales.CONFIG += no_check_exist locales.path = $$[QT_INSTALL_TRANSLATIONS]/qtwebengine_locales @@ -63,9 +73,7 @@ plugins.files = $$OUT_PWD/$$getConfigDir()/$${PLUGIN_PREFIX}ffmpegsumo$${PLUGIN_ resources.path = $$[QT_INSTALL_DATA] icu.CONFIG += no_check_exist icu.path = $$[QT_INSTALL_DATA] - plugins.CONFIG += no_check_exist - plugins.path = $$[QT_INSTALL_PLUGINS]/qtwebengine - INSTALLS += icu locales resources plugins + INSTALLS += icu locales resources } !contains(QT_CONFIG, qt_framework): contains(QT_CONFIG, private_tests) { @@ -75,15 +83,7 @@ plugins.files = $$OUT_PWD/$$getConfigDir()/$${PLUGIN_PREFIX}ffmpegsumo$${PLUGIN_ unix: icu_rule.commands = if [ -e $$ICU_FILE ] ; then $$QMAKE_COPY $$ICU_FILE $$ICU_TARGET ; fi win32: icu_rule.commands = if exist $$ICU_FILE ( $$QMAKE_COPY $$ICU_FILE $$ICU_TARGET ) - PLUGIN_DIR = $$shell_path($$[QT_INSTALL_PLUGINS/get]/qtwebengine) - PLUGIN_TARGET = $$shell_path($$PLUGIN_DIR/$${PLUGIN_PREFIX}ffmpegsumo$${PLUGIN_EXTENSION}) - PLUGIN_FILE = $$shell_path($$OUT_PWD/$$getConfigDir()/$${PLUGIN_PREFIX}ffmpegsumo$${PLUGIN_EXTENSION}) - plugins_rule.target = $$PLUGIN_TARGET - unix: plugins_rule.commands = $$QMAKE_MKDIR $$PLUGIN_DIR && if [ -e $$PLUGIN_FILE ] ; then $$QMAKE_COPY $$PLUGIN_FILE $$PLUGIN_TARGET ; fi - win32: plugins_rule.commands = (if not exist $$PLUGIN_DIR ( $$QMAKE_MKDIR $$PLUGIN_DIR )) && \ - if exist $$PLUGIN_FILE ( $$QMAKE_COPY $$PLUGIN_FILE $$PLUGIN_TARGET ) - - QMAKE_EXTRA_TARGETS += icu_rule plugins_rule - PRE_TARGETDEPS += $$ICU_TARGET $$PLUGIN_TARGET + QMAKE_EXTRA_TARGETS += icu_rule + PRE_TARGETDEPS += $$ICU_TARGET } } diff --git a/src/core/custom_protocol_handler.cpp b/src/core/custom_protocol_handler.cpp index f140f98cf..fd1a4de41 100644 --- a/src/core/custom_protocol_handler.cpp +++ b/src/core/custom_protocol_handler.cpp @@ -43,7 +43,7 @@ namespace QtWebEngineCore { -CustomProtocolHandler::CustomProtocolHandler(CustomUrlSchemeHandler *schemeHandler) +CustomProtocolHandler::CustomProtocolHandler(QWebEngineUrlSchemeHandler *schemeHandler) : m_schemeHandler(schemeHandler) { } diff --git a/src/core/custom_protocol_handler.h b/src/core/custom_protocol_handler.h index 225bb0567..94da28673 100644 --- a/src/core/custom_protocol_handler.h +++ b/src/core/custom_protocol_handler.h @@ -45,6 +45,7 @@ #include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE QT_FORWARD_DECLARE_CLASS(QIODevice) +QT_FORWARD_DECLARE_CLASS(QWebEngineUrlSchemeHandler) namespace net { class NetworkDelegate; @@ -54,20 +55,19 @@ class URLRequestJob; namespace QtWebEngineCore { class BrowserContextAdapter; -class CustomUrlSchemeHandler; // Implements a ProtocolHandler for custom URL schemes. // If |network_delegate_| is NULL then all file requests will fail with ERR_ACCESS_DENIED. class QWEBENGINE_EXPORT CustomProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { public: - CustomProtocolHandler(CustomUrlSchemeHandler *); + CustomProtocolHandler(QWebEngineUrlSchemeHandler *); virtual net::URLRequestJob *MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const Q_DECL_OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); - CustomUrlSchemeHandler *m_schemeHandler; + QWebEngineUrlSchemeHandler *m_schemeHandler; }; } // namespace diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index 6f79d4952..aebdfd027 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -76,6 +76,10 @@ #include <EGL/eglext.h> #endif +#ifndef GL_TIMEOUT_IGNORED +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#endif + namespace QtWebEngineCore { class MailboxTexture : public QSGTexture, protected QOpenGLFunctions { @@ -161,9 +165,9 @@ static QSGNode *buildLayerChain(QSGNode *chainParent, const cc::SharedQuadState layerChain->appendChildNode(clipNode); layerChain = clipNode; } - if (!layerState->content_to_target_transform.IsIdentity()) { + if (!layerState->quad_to_target_transform.IsIdentity()) { QSGTransformNode *transformNode = new QSGTransformNode; - transformNode->setMatrix(toQt(layerState->content_to_target_transform.matrix())); + transformNode->setMatrix(toQt(layerState->quad_to_target_transform.matrix())); layerChain->appendChildNode(transformNode); layerChain = transformNode; } @@ -205,7 +209,6 @@ static void waitChromiumSync(gfx::TransferableFence *sync) #endif break; case gfx::TransferableFence::ArbSync: -#ifdef GL_ARB_sync typedef void (QOPENGLF_APIENTRYP WaitSyncPtr)(GLsync sync, GLbitfield flags, GLuint64 timeout); static WaitSyncPtr glWaitSync_ = 0; if (!glWaitSync_) { @@ -214,7 +217,6 @@ static void waitChromiumSync(gfx::TransferableFence *sync) Q_ASSERT(glWaitSync_); } glWaitSync_(sync->arb.sync, 0, GL_TIMEOUT_IGNORED); -#endif break; } } @@ -250,7 +252,6 @@ static void deleteChromiumSync(gfx::TransferableFence *sync) #endif break; case gfx::TransferableFence::ArbSync: -#ifdef GL_ARB_sync typedef void (QOPENGLF_APIENTRYP DeleteSyncPtr)(GLsync sync); static DeleteSyncPtr glDeleteSync_ = 0; if (!glDeleteSync_) { @@ -260,7 +261,6 @@ static void deleteChromiumSync(gfx::TransferableFence *sync) } glDeleteSync_(sync->arb.sync); sync->reset(); -#endif break; } // If Chromium was able to create a sync, we should have been able to handle its type here too. @@ -409,7 +409,7 @@ void DelegatedFrameNode::preprocess() { QMutexLocker lock(&m_mutex); base::MessageLoop *gpuMessageLoop = gpu_message_loop(); - content::SyncPointManager *syncPointManager = sync_point_manager(); + gpu::SyncPointManager *syncPointManager = sync_point_manager(); Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) { m_numPendingSyncPoints++; @@ -444,6 +444,20 @@ void DelegatedFrameNode::preprocess() } } +static YUVVideoMaterial::ColorSpace toQt(cc::YUVVideoDrawQuad::ColorSpace color_space) +{ + switch (color_space) { + case cc::YUVVideoDrawQuad::REC_601: + return YUVVideoMaterial::REC_601; + case cc::YUVVideoDrawQuad::REC_709: + return YUVVideoMaterial::REC_709; + case cc::YUVVideoDrawQuad::JPEG: + return YUVVideoMaterial::JPEG; + } + Q_UNREACHABLE(); + return YUVVideoMaterial::REC_601; +} + void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, cc::ReturnedResourceArray *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate) { m_chromiumCompositorData = chromiumCompositorData; @@ -557,10 +571,10 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, break; } case cc::DrawQuad::TEXTURE_CONTENT: { const cc::TextureDrawQuad *tquad = cc::TextureDrawQuad::MaterialCast(quad); - ResourceHolder *resource = findAndHoldResource(tquad->resource_id, resourceCandidates); + ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates); QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode; - textureNode->setTextureCoordinatesTransform(tquad->flipped ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform); + textureNode->setTextureCoordinatesTransform(tquad->y_flipped ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform); textureNode->setRect(toQt(quad->rect)); textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest); textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate)); @@ -605,7 +619,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, break; } case cc::DrawQuad::TILED_CONTENT: { const cc::TileDrawQuad *tquad = cc::TileDrawQuad::MaterialCast(quad); - ResourceHolder *resource = findAndHoldResource(tquad->resource_id, resourceCandidates); + ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates); QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode; textureNode->setRect(toQt(quad->rect)); @@ -616,26 +630,28 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, break; } case cc::DrawQuad::YUV_VIDEO_CONTENT: { const cc::YUVVideoDrawQuad *vquad = cc::YUVVideoDrawQuad::MaterialCast(quad); - 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 *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) - aResource = findAndHoldResource(vquad->a_plane_resource_id, resourceCandidates); + if (vquad->a_plane_resource_id()) + aResource = findAndHoldResource(vquad->a_plane_resource_id(), resourceCandidates); 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)); + aResource ? initAndHoldTexture(aResource, quad->ShouldDrawWithBlending()) : 0, + toQt(vquad->ya_tex_coord_rect), toQt(vquad->uv_tex_coord_rect), + toQt(vquad->ya_tex_size), toQt(vquad->uv_tex_size), toQt(vquad->color_space)); 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); - ResourceHolder *resource = findAndHoldResource(squad->resource_id, resourceCandidates); + 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 diff --git a/src/core/dev_tools_http_handler_delegate_qt.cpp b/src/core/dev_tools_http_handler_delegate_qt.cpp index 964d6ad38..793ed0981 100644 --- a/src/core/dev_tools_http_handler_delegate_qt.cpp +++ b/src/core/dev_tools_http_handler_delegate_qt.cpp @@ -49,9 +49,11 @@ #include "base/files/file_path.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "components/devtools_discovery/devtools_discovery_manager.h" +#include "components/devtools_discovery/devtools_target_descriptor.h" +#include "components/devtools_http_handler/devtools_http_handler.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/devtools_frontend_host.h" #include "content/public/browser/favicon_status.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_view_host.h" @@ -59,14 +61,17 @@ #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/base/net_errors.h" #include "net/socket/tcp_server_socket.h" using namespace content; +using namespace devtools_discovery; +using namespace devtools_http_handler; namespace { const char kTargetTypePage[] = "page"; +const char kTargetTypeSharedWorker[] = "worker"; const char kTargetTypeServiceWorker[] = "service_worker"; const char kTargetTypeOther[] = "other"; @@ -74,15 +79,29 @@ class TCPServerSocketFactory : public DevToolsHttpHandler::ServerSocketFactory { public: TCPServerSocketFactory(const std::string& address, int port, int backlog) - : DevToolsHttpHandler::ServerSocketFactory(address, port, backlog) {} + : m_address(address), m_port(port), m_backlog(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); + scoped_ptr<net::ServerSocket> CreateForHttpServer() override { + scoped_ptr<net::ServerSocket> socket(new net::TCPServerSocket(nullptr, net::NetLog::Source())); + if (socket->ListenWithAddressAndPort(m_address, m_port, m_backlog) != net::OK) + return scoped_ptr<net::ServerSocket>(); + + return socket; + } + + const std::string m_address; + int m_port; + int m_backlog; + DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory); }; -class Target : public content::DevToolsTarget { +class DevToolsDiscoveryProviderQt : public DevToolsDiscoveryManager::Provider { +public: + DevToolsTargetDescriptor::List GetDescriptors() override; +}; + +class Target : public DevToolsTargetDescriptor { public: explicit Target(scoped_refptr<DevToolsAgentHost> agent_host); @@ -92,6 +111,8 @@ public: switch (agent_host_->GetType()) { case DevToolsAgentHost::TYPE_WEB_CONTENTS: return kTargetTypePage; + case DevToolsAgentHost::TYPE_SHARED_WORKER: + return kTargetTypeSharedWorker; case DevToolsAgentHost::TYPE_SERVICE_WORKER: return kTargetTypeServiceWorker; default: @@ -141,17 +162,40 @@ bool Target::Close() const { return agent_host_->Close(); } +DevToolsTargetDescriptor::List DevToolsDiscoveryProviderQt::GetDescriptors() +{ + DevToolsTargetDescriptor::List targets; + for (const auto& agent_host : DevToolsAgentHost::GetOrCreateAll()) { + targets.push_back(new Target(agent_host)); + } + return targets; +} + } // namespace namespace QtWebEngineCore { +scoped_ptr<DevToolsHttpHandler> createDevToolsHttpHandler() +{ + DevToolsHttpHandlerDelegateQt *delegate = new DevToolsHttpHandlerDelegateQt(); + if (!delegate->isValid()) { + delete delegate; + return nullptr; + } + scoped_ptr<DevToolsHttpHandler::ServerSocketFactory> factory(new TCPServerSocketFactory(delegate->bindAddress().toStdString(), delegate->port(), 1)); + // Ownership of the delegate is taken over the devtools http handler. + scoped_ptr<DevToolsHttpHandler> handler(new DevToolsHttpHandler(factory.Pass(), std::string(), delegate, base::FilePath(), base::FilePath(), std::string(), std::string())); + DevToolsDiscoveryManager::GetInstance()->AddProvider(scoped_ptr<DevToolsDiscoveryManager::Provider>(new DevToolsDiscoveryProviderQt())); + return handler; +} + DevToolsHttpHandlerDelegateQt::DevToolsHttpHandlerDelegateQt() - : m_devtoolsHttpHandler(0) - , m_bindAddress(QLatin1String("127.0.0.1")) + : m_bindAddress(QLatin1String("127.0.0.1")) , m_port(0) + , m_valid(false) { const QString inspectorEnv = QString::fromUtf8(qgetenv("QTWEBENGINE_REMOTE_DEBUGGING")); - const CommandLine &commandLine = *CommandLine::ForCurrentProcess(); + const base::CommandLine &commandLine = *base::CommandLine::ForCurrentProcess(); QString portStr; if (commandLine.HasSwitch(switches::kRemoteDebuggingPort)) { @@ -166,26 +210,16 @@ DevToolsHttpHandlerDelegateQt::DevToolsHttpHandlerDelegateQt() } 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 + m_port = portStr.toInt(&m_valid); + m_valid = m_valid && m_port > 0 && m_port < 65535; + if (!m_valid) 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() -{ - // Stop() takes care of deleting the DevToolsHttpHandler. - if (m_devtoolsHttpHandler) - m_devtoolsHttpHandler->Stop(); -} - -void DevToolsHttpHandlerDelegateQt::Initialized(const net::IPEndPoint& ip_address) +void DevToolsHttpHandlerDelegateQt::Initialized(const net::IPEndPoint *ip_address) { - if (ip_address.address().size()) { - QString addressAndPort = QString::fromStdString(ip_address.ToString()); + if (ip_address && 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); @@ -203,42 +237,19 @@ std::string DevToolsHttpHandlerDelegateQt::GetDiscoveryPageHTML() return html; } -bool DevToolsHttpHandlerDelegateQt::BundlesFrontendResources() -{ - return true; -} - -base::FilePath DevToolsHttpHandlerDelegateQt::GetDebugFrontendDir() -{ - return base::FilePath(); -} - -scoped_ptr<net::StreamListenSocket> DevToolsHttpHandlerDelegateQt::CreateSocketForTethering(net::StreamListenSocket::Delegate* delegate, std::string* name) -{ - return scoped_ptr<net::StreamListenSocket>(); -} - -base::DictionaryValue* DevToolsManagerDelegateQt::HandleCommand(DevToolsAgentHost *, base::DictionaryValue *) { - return 0; -} - -std::string DevToolsManagerDelegateQt::GetPageThumbnailData(const GURL& url) +std::string DevToolsHttpHandlerDelegateQt::GetPageThumbnailData(const GURL& url) { return std::string(); } -scoped_ptr<DevToolsTarget> DevToolsManagerDelegateQt::CreateNewTarget(const GURL &) +std::string DevToolsHttpHandlerDelegateQt::GetFrontendResource(const std::string &path) { - return scoped_ptr<DevToolsTarget>(); + return content::DevToolsFrontendHost::GetFrontendResource(path).as_string(); } -void DevToolsManagerDelegateQt::EnumerateTargets(TargetCallback callback) +base::DictionaryValue* DevToolsManagerDelegateQt::HandleCommand(DevToolsAgentHost *, base::DictionaryValue *) { - TargetList targets; - for (const auto& agent_host : DevToolsAgentHost::GetOrCreateAll()) { - targets.push_back(new Target(agent_host)); - } - callback.Run(targets); + return 0; } } //namespace QtWebEngineCore diff --git a/src/core/dev_tools_http_handler_delegate_qt.h b/src/core/dev_tools_http_handler_delegate_qt.h index 902e99507..0fe9ad0ce 100644 --- a/src/core/dev_tools_http_handler_delegate_qt.h +++ b/src/core/dev_tools_http_handler_delegate_qt.h @@ -37,43 +37,42 @@ #ifndef DEV_TOOLS_HTTP_HANDLER_DELEGATE_QT_H #define DEV_TOOLS_HTTP_HANDLER_DELEGATE_QT_H -#include "content/public/browser/devtools_http_handler_delegate.h" +#include "components/devtools_http_handler/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 { -class StreamListenSocket; -} - namespace content { class BrowserContext; +} + +namespace devtools_http_handler { class DevToolsHttpHandler; -class RenderViewHost; } namespace QtWebEngineCore { -class DevToolsHttpHandlerDelegateQt : public content::DevToolsHttpHandlerDelegate { -public: +scoped_ptr<devtools_http_handler::DevToolsHttpHandler> createDevToolsHttpHandler(); +class DevToolsHttpHandlerDelegateQt : public devtools_http_handler::DevToolsHttpHandlerDelegate { +public: 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; - // Requests the list of all inspectable targets. - // The caller gets the ownership of the returned targets. - virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(net::StreamListenSocket::Delegate *delegate, std::string *name) Q_DECL_OVERRIDE; + bool isValid() const { return m_valid; } + QString bindAddress() const { return m_bindAddress; } + int port() const { return m_port; } + + // devtools_http_handler::DevToolsHttpHandlerDelegate Overrides + void Initialized(const net::IPEndPoint *ip_address) Q_DECL_OVERRIDE; + std::string GetDiscoveryPageHTML() Q_DECL_OVERRIDE; + std::string GetFrontendResource(const std::string&) Q_DECL_OVERRIDE; + std::string GetPageThumbnailData(const GURL &url) Q_DECL_OVERRIDE; private: - content::DevToolsHttpHandler *m_devtoolsHttpHandler; QString m_bindAddress; int m_port; + bool m_valid; }; class DevToolsManagerDelegateQt : public content::DevToolsManagerDelegate { @@ -81,9 +80,6 @@ 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; }; } // namespace QtWebEngineCore diff --git a/src/core/doc/snippets/qtwebenginecore_build_snippet.qdoc b/src/core/doc/snippets/qtwebenginecore_build_snippet.qdoc new file mode 100644 index 000000000..4806359c9 --- /dev/null +++ b/src/core/doc/snippets/qtwebenginecore_build_snippet.qdoc @@ -0,0 +1,8 @@ +//! [0] +QT += webenginecore +//! [0] + + +//! [1] +#include <QtWebEngineCore> +//! [1] diff --git a/src/core/doc/src/qtwebenginecore-index.qdoc b/src/core/doc/src/qtwebenginecore-index.qdoc new file mode 100644 index 000000000..49231c8f2 --- /dev/null +++ b/src/core/doc/src/qtwebenginecore-index.qdoc @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page qtwebenginecore-index.html + \title Qt WebEngine Core + \ingroup modules + + \brief Provides common API shared by Qt WebEngine and Qt WebEngine Widgets. + + Qt WebEngine Core provides API shared by \l {Qt WebEngine} and \l {Qt WebEngine Widgets}. + + \section1 Getting Started + + To include the definitions of the module's classes, use the + following directive: + + \snippet qtwebenginecore_build_snippet.qdoc 1 + + To link against the module, add this line to your qmake project file: + + \snippet qtwebenginecore_build_snippet.qdoc 0 + + \section1 Articles and Guides + + \list + \li \l{Qt WebEngine Overview} + \endlist + + \section1 API Reference + + \list + \li \l{Qt WebEngine Core C++ Classes} + \endlist + + \section1 License Information + + This is a snapshot of the integration of Chromium into Qt. + + Qt Commercial Edition licensees that wish to distribute applications that + use the Qt WebEngine module need to be aware of their obligations under the + GNU Library General Public License (LGPLv2). + + Developers using the Open Source Edition can choose to redistribute + the module under the GNU LGPLv3 or GPLv2 and up. + + \legalese + + Chromium is licensed under the following license: + + Copyright (c) 2013 The Chromium Authors. All rights reserved. + + 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 Google Inc. 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. + + \endlegalese +*/ diff --git a/src/core/doc/src/qtwebenginecore-module.qdoc b/src/core/doc/src/qtwebenginecore-module.qdoc new file mode 100644 index 000000000..750a0244e --- /dev/null +++ b/src/core/doc/src/qtwebenginecore-module.qdoc @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +/*! + \module QtWebEngineCore + \title Qt WebEngine Core C++ Classes + \brief Provides public API shared by both QtWebEngine and QtWebEngineWidgets + \since 5.6 + \ingroup qtwebengine-modules + + To include the definitions of the module's classes, use the + following directive: + + \snippet qtwebenginecore_build_snippet.qdoc 1 + + If you use qmake to build your projects, Qt WebEngine Core is usually + indirectly included through the \l[QtWebEngine]{Qt WebEngine} or + \l[QtWebEngineWidgets]{Qt WebEngine Widgets} modules. +*/ diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp new file mode 100644 index 000000000..18896c6b4 --- /dev/null +++ b/src/core/file_picker_controller.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** 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 "file_picker_controller.h" +#include "type_conversion.h" +#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" + +#include <QFileInfo> +#include <QDir> +#include <QVariant> +#include <QStringList> + +namespace QtWebEngineCore { + +FilePickerController::FilePickerController(FileChooserMode mode, content::WebContents *contents, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject *parent) + : QObject(parent) + , m_defaultFileName(defaultFileName) + , m_acceptedMimeTypes(acceptedMimeTypes) + , m_contents(contents) + , m_mode(mode) +{ +} + +void FilePickerController::accepted(const QStringList &files) +{ + FilePickerController::filesSelectedInChooser(files, m_contents); +} + +void FilePickerController::accepted(const QVariant &files) +{ + QStringList stringList; + + if (files.canConvert(QVariant::StringList)) { + stringList = files.toStringList(); + } else if (files.canConvert<QList<QUrl> >()) { + Q_FOREACH (const QUrl &url, files.value<QList<QUrl> >()) + stringList.append(url.toLocalFile()); + } else { + qWarning("An unhandled type '%s' was provided in FilePickerController::accepted(QVariant)", files.typeName()); + } + + FilePickerController::filesSelectedInChooser(stringList, m_contents); +} + +void FilePickerController::rejected() +{ + FilePickerController::filesSelectedInChooser(QStringList(), m_contents); +} + +static QStringList listRecursively(const QDir &dir) +{ + QStringList ret; + QFileInfoList infoList(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden)); + Q_FOREACH (const QFileInfo &fileInfo, infoList) { + if (fileInfo.isDir()) { + ret.append(fileInfo.absolutePath() + QStringLiteral("/.")); // Match chromium's behavior. See chrome/browser/file_select_helper.cc + ret.append(listRecursively(QDir(fileInfo.absoluteFilePath()))); + } else + ret.append(fileInfo.absoluteFilePath()); + } + return ret; +} + +ASSERT_ENUMS_MATCH(FilePickerController::Open, content::FileChooserParams::Open) +ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, content::FileChooserParams::OpenMultiple) +ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, content::FileChooserParams::UploadFolder) +ASSERT_ENUMS_MATCH(FilePickerController::Save, content::FileChooserParams::Save) + +void FilePickerController::filesSelectedInChooser(const QStringList &filesList, content::WebContents *contents) +{ + content::RenderViewHost *rvh = contents->GetRenderViewHost(); + Q_ASSERT(rvh); + QStringList files(filesList); + if (this->m_mode == UploadFolder && !filesList.isEmpty() + && QFileInfo(filesList.first()).isDir()) // Enumerate the directory + files = listRecursively(QDir(filesList.first())); + rvh->FilesSelectedInChooser(toVector<content::FileChooserFileInfo>(files), static_cast<content::FileChooserParams::Mode>(this->m_mode)); +} + +QStringList FilePickerController::acceptedMimeTypes() +{ + return m_acceptedMimeTypes; +} + +FilePickerController::FileChooserMode FilePickerController::mode() +{ + return m_mode; +} + +QString FilePickerController::defaultFileName() +{ + return m_defaultFileName; +} + +} // namespace diff --git a/src/core/file_picker_controller.h b/src/core/file_picker_controller.h new file mode 100644 index 000000000..347dd11ef --- /dev/null +++ b/src/core/file_picker_controller.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 FILE_PICKER_CONTROLLER_H +#define FILE_PICKER_CONTROLLER_H + +#include "qtwebenginecoreglobal.h" +#include <QObject> +#include <QStringList> + +namespace content { + class WebContents; +} + +namespace QtWebEngineCore { + +class QWEBENGINE_EXPORT FilePickerController : public QObject { + Q_OBJECT +public: + enum FileChooserMode { + Open, + OpenMultiple, + UploadFolder, + Save + }; + + FilePickerController(FileChooserMode mode, content::WebContents *contents, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject * = 0); + QStringList acceptedMimeTypes(); + QString defaultFileName(); + FileChooserMode mode(); + void filesSelectedInChooser(const QStringList &filesList, content::WebContents *contents); + +public Q_SLOTS: + void accepted(const QStringList &files); + void accepted(const QVariant &files); + void rejected(); + +private: + QString m_defaultFileName; + QStringList m_acceptedMimeTypes; + content::WebContents *m_contents; + FileChooserMode m_mode; + +}; + +} // namespace + +#endif // FILE_PICKER_CONTROLLER_H diff --git a/src/core/gl_surface_qt.cpp b/src/core/gl_surface_qt.cpp index 584bdc227..86bb4fda9 100644 --- a/src/core/gl_surface_qt.cpp +++ b/src/core/gl_surface_qt.cpp @@ -44,7 +44,7 @@ #include <QGuiApplication> #include "gl_context_qt.h" -#include "qtwebenginecoreglobal.h" +#include "qtwebenginecoreglobal_p.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -439,11 +439,11 @@ bool GLSurfaceQt::IsOffscreen() return true; } -bool GLSurfaceQt::SwapBuffers() +gfx::SwapResult GLSurfaceQt::SwapBuffers() { LOG(ERROR) << "Attempted to call SwapBuffers on a pbuffer."; Q_UNREACHABLE(); - return false; + return gfx::SwapResult::SWAP_FAILED; } gfx::Size GLSurfaceQt::GetSize() @@ -533,6 +533,17 @@ GLSurface::CreateViewGLSurface(gfx::AcceleratedWidget window) return NULL; } +std::string DriverEGL::GetPlatformExtensions() +{ + EGLDisplay display = GLContextHelper::getEGLDisplay(); + if (display == EGL_NO_DISPLAY) + return ""; + + DCHECK(g_driver_egl.fn.eglQueryStringFn); + const char* str = g_driver_egl.fn.eglQueryStringFn(display, EGL_EXTENSIONS); + return str ? std::string(str) : ""; +} + } // namespace gfx namespace content { diff --git a/src/core/gl_surface_qt.h b/src/core/gl_surface_qt.h index 21c46e699..7646063b2 100644 --- a/src/core/gl_surface_qt.h +++ b/src/core/gl_surface_qt.h @@ -39,7 +39,7 @@ #ifndef GL_SURFACE_QT_H_ #define GL_SURFACE_QT_H_ -#include "ui/gfx/size.h" +#include "ui/gfx/geometry/size.h" #include "ui/gl/gl_surface.h" #include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE @@ -56,7 +56,7 @@ public: virtual void* GetDisplay() Q_DECL_OVERRIDE; virtual void* GetConfig() Q_DECL_OVERRIDE; virtual bool IsOffscreen() Q_DECL_OVERRIDE; - virtual bool SwapBuffers() Q_DECL_OVERRIDE; + virtual gfx::SwapResult SwapBuffers() Q_DECL_OVERRIDE; virtual gfx::Size GetSize() Q_DECL_OVERRIDE; protected: diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro index 3f631302c..def7d4698 100644 --- a/src/core/gyp_run.pro +++ b/src/core/gyp_run.pro @@ -28,9 +28,6 @@ force_debug_info { else: GYP_CONFIG += release_extra_cflags=-g } -# Append additional platform options defined in GYP_CONFIG -for (config, GYP_CONFIG): GYP_ARGS += "-D $$config" - # Copy this logic from qt_module.prf so that ninja can run according # to the same rules as the final module linking in core_module.pro. !host_build:if(win32|mac):!macx-xcode { @@ -40,58 +37,63 @@ for (config, GYP_CONFIG): GYP_ARGS += "-D $$config" cross_compile { TOOLCHAIN_SYSROOT = $$[QT_SYSROOT] + !isEmpty(TOOLCHAIN_SYSROOT): GYP_CONFIG += sysroot=\"$${TOOLCHAIN_SYSROOT}\" + + # Needed for v8, see chromium/v8/build/toolchain.gypi + GYP_CONFIG += CXX=\"$$which($$QMAKE_CXX)\" +} + +contains(QT_ARCH, "arm") { + # Chromium will set a default sysroot on arm unless we give it one. + !cross_compile: GYP_CONFIG += sysroot=\"\" + + GYP_CONFIG += target_arch=arm + + # Extract ARM specific compiler options that we have to pass to gyp, + # but let gyp figure out a default if an option is not present. + MARCH = $$extractCFlag("-march=.*") + !isEmpty(MARCH): GYP_CONFIG += arm_arch=\"$$MARCH\" - !isEmpty(TOOLCHAIN_SYSROOT): GYP_ARGS += "-D sysroot=\"$${TOOLCHAIN_SYSROOT}\"" - - contains(QT_ARCH, "arm") { - GYP_ARGS += "-D target_arch=arm" - - # Extract ARM specific compiler options that we have to pass to gyp, - # but let gyp figure out a default if an option is not present. - MARCH = $$extractCFlag("-march=.*") - !isEmpty(MARCH): GYP_ARGS += "-D arm_arch=\"$$MARCH\"" - - MTUNE = $$extractCFlag("-mtune=.*") - GYP_ARGS += "-D arm_tune=\"$$MTUNE\"" - - MFLOAT = $$extractCFlag("-mfloat-abi=.*") - !isEmpty(MFLOAT): GYP_ARGS += "-D arm_float_abi=\"$$MFLOAT\"" - - MARMV = $$replace(MARCH, "armv",) - !isEmpty(MARMV) { - MARMV = $$split(MARMV,) - MARMV = $$member(MARMV, 0) - lessThan(MARMV, 6): error("$$MARCH architecture is not supported") - GYP_ARGS += "-D arm_version=\"$$MARMV\"" - } - - MFPU = $$extractCFlag("-mfpu=.*") - !isEmpty(MFPU) { - # If the toolchain does not explicitly specify to use NEON instructions - # we use arm_neon_optional for ARMv7 and newer and let chromium decide - # about the mfpu option. - contains(MFPU, "neon")|contains(MFPU, "neon-vfpv4"): GYP_ARGS += "-D arm_fpu=\"$$MFPU\" -D arm_neon=1" - else:!lessThan(MARMV, 7): GYP_ARGS += "-D arm_neon=0 -D arm_neon_optional=1" - else: GYP_ARGS += "-D arm_fpu=\"$$MFPU\" -D arm_neon=0 -D arm_neon_optional=0" - } - - contains(QMAKE_CFLAGS, "-mthumb"): GYP_ARGS += "-D arm_thumb=1" + MTUNE = $$extractCFlag("-mtune=.*") + !isEmpty(MTUNE): GYP_CONFIG += arm_tune=\"$$MTUNE\" + + MFLOAT = $$extractCFlag("-mfloat-abi=.*") + !isEmpty(MFLOAT): GYP_CONFIG += arm_float_abi=\"$$MFLOAT\" + + MARMV = $$replace(MARCH, "armv",) + !isEmpty(MARMV) { + MARMV = $$split(MARMV,) + MARMV = $$member(MARMV, 0) + lessThan(MARMV, 6): error("$$MARCH architecture is not supported") + GYP_CONFIG += arm_version=\"$$MARMV\" } - # Needed for v8, see chromium/v8/build/toolchain.gypi - GYP_ARGS += "-D CXX=\"$$which($$QMAKE_CXX)\"" + MFPU = $$extractCFlag("-mfpu=.*") + !isEmpty(MFPU) { + # If the toolchain does not explicitly specify to use NEON instructions + # we use arm_neon_optional for ARMv7 and newer and let chromium decide + # about the mfpu option. + contains(MFPU, "neon")|contains(MFPU, "neon-vfpv4"): GYP_CONFIG += arm_fpu=\"$$MFPU\" arm_neon=1 + else:!lessThan(MARMV, 7): GYP_CONFIG += arm_neon=0 arm_neon_optional=1 + else: GYP_CONFIG += arm_fpu=\"$$MFPU\" arm_neon=0 arm_neon_optional=0 + } + + contains(QMAKE_CFLAGS, "-mthumb"): GYP_CONFIG += arm_thumb=1 } -contains(QT_ARCH, "x86_64"): GYP_ARGS += "-D target_arch=x64" -contains(QT_ARCH, "i386"): GYP_ARGS += "-D target_arch=ia32" +contains(QT_ARCH, "x86_64"): GYP_CONFIG += target_arch=x64 +contains(QT_ARCH, "i386"): GYP_CONFIG += target_arch=ia32 -contains(WEBENGINE_CONFIG, proprietary_codecs): GYP_ARGS += "-Dproprietary_codecs=1 -Dffmpeg_branding=Chrome -Duse_system_ffmpeg=0" +contains(WEBENGINE_CONFIG, use_proprietary_codecs): GYP_CONFIG += proprietary_codecs=1 ffmpeg_branding=Chrome !contains(QT_CONFIG, qt_framework): contains(QT_CONFIG, private_tests) { - GYP_ARGS += "-D qt_install_data=\"$$[QT_INSTALL_DATA/get]\"" - GYP_ARGS += "-D qt_install_translations=\"$$[QT_INSTALL_TRANSLATIONS/get]\"" + GYP_CONFIG += qt_install_data=\"$$[QT_INSTALL_DATA/get]\" + GYP_CONFIG += qt_install_translations=\"$$[QT_INSTALL_TRANSLATIONS/get]\" } +# Append additional platform options defined in GYP_CONFIG +for (config, GYP_CONFIG): GYP_ARGS += "-D $$config" + !build_pass { message("Running gyp_qtwebengine \"$$OUT_PWD\" $${GYP_ARGS}...") !system("python $$QTWEBENGINE_ROOT/tools/buildscripts/gyp_qtwebengine \"$$OUT_PWD\" $${GYP_ARGS}"): error("-- running gyp_qtwebengine failed --") diff --git a/src/core/javascript_dialog_manager_qt.cpp b/src/core/javascript_dialog_manager_qt.cpp index fdcd7bdbc..24d426098 100644 --- a/src/core/javascript_dialog_manager_qt.cpp +++ b/src/core/javascript_dialog_manager_qt.cpp @@ -67,6 +67,12 @@ void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webCon runDialogForContents(webContents, dialogType, toQt(messageText).toHtmlEscaped(), toQt(defaultPromptText).toHtmlEscaped(), toQt(originUrl), callback); } +void JavaScriptDialogManagerQt::RunBeforeUnloadDialog(content::WebContents *webContents, const base::string16 &messageText, + bool isReload, const content::JavaScriptDialogManager::DialogClosedCallback &callback) { + Q_UNUSED(isReload); + runDialogForContents(webContents, WebContentsAdapterClient::UnloadDialog, toQt(messageText).toHtmlEscaped(), QString() , QUrl(), callback); +} + bool JavaScriptDialogManagerQt::HandleJavaScriptDialog(content::WebContents *contents, bool accept, const base::string16 *promptOverride) { QSharedPointer<JavaScriptDialogController> dialog = m_activeDialogs.value(contents); diff --git a/src/core/javascript_dialog_manager_qt.h b/src/core/javascript_dialog_manager_qt.h index 4682ce5b8..fb47166c1 100644 --- a/src/core/javascript_dialog_manager_qt.h +++ b/src/core/javascript_dialog_manager_qt.h @@ -63,11 +63,10 @@ public: const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) Q_DECL_OVERRIDE; virtual void RunBeforeUnloadDialog(content::WebContents *, const base::string16 &messageText, bool isReload, - const content::JavaScriptDialogManager::DialogClosedCallback &callback) Q_DECL_OVERRIDE { Q_UNUSED(messageText); Q_UNUSED(isReload); Q_UNUSED(callback); } + const content::JavaScriptDialogManager::DialogClosedCallback &callback) Q_DECL_OVERRIDE; virtual bool HandleJavaScriptDialog(content::WebContents *, bool accept, const base::string16 *promptOverride) Q_DECL_OVERRIDE; virtual void CancelActiveAndPendingDialogs(content::WebContents *contents) Q_DECL_OVERRIDE { takeDialogForContents(contents); } - virtual void WebContentsDestroyed(content::WebContents *contents) Q_DECL_OVERRIDE { takeDialogForContents(contents); } - + virtual void ResetDialogState(content::WebContents *contents) Q_DECL_OVERRIDE { takeDialogForContents(contents); } void runDialogForContents(content::WebContents *, WebContentsAdapterClient::JavascriptDialogType, const QString &messageText, const QString &defaultPrompt , const QUrl &,const content::JavaScriptDialogManager::DialogClosedCallback &callback, const QString &title = QString()); diff --git a/src/core/location_provider_qt.cpp b/src/core/location_provider_qt.cpp index d17fc3d21..e3be01b36 100644 --- a/src/core/location_provider_qt.cpp +++ b/src/core/location_provider_qt.cpp @@ -60,7 +60,7 @@ public: QtPositioningHelper(LocationProviderQt *provider); ~QtPositioningHelper(); - bool start(bool highAccuracy); + void start(bool highAccuracy); void stop(); void refresh(); @@ -88,15 +88,20 @@ QtPositioningHelper::~QtPositioningHelper() m_locationProvider->m_positioningHelper = 0; } -bool QtPositioningHelper::start(bool highAccuracy) +void 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; + if (!m_positionInfoSource) { + qWarning("Failed to initialize location provider: The system either has no default " + "position source, no valid plugins could be found or the user does not have " + "the right permissions."); + error(QGeoPositionInfoSource::UnknownSourceError); + return; + } connect(m_positionInfoSource, &QGeoPositionInfoSource::positionUpdated, this, &QtPositioningHelper::updatePosition); // disambiguate the error getter and the signal in QGeoPositionInfoSource. @@ -105,7 +110,7 @@ bool QtPositioningHelper::start(bool highAccuracy) connect(m_positionInfoSource, &QGeoPositionInfoSource::updateTimeout, this, &QtPositioningHelper::timeout); m_positionInfoSource->startUpdates(); - return true; + return; } void QtPositioningHelper::stop() @@ -208,7 +213,7 @@ bool LocationProviderQt::StartProvider(bool highAccuracy) m_positioningHelper = new QtPositioningHelper(this); m_positioningHelper->moveToThread(guiThread); } - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(base::IgnoreResult(&QtPositioningHelper::start) + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&QtPositioningHelper::start , base::Unretained(m_positioningHelper), highAccuracy)); return true; } diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index 6866afc41..b31d22a76 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -91,9 +91,8 @@ scoped_ptr<content::MediaStreamUI> getDevicesForDesktopCapture(content::MediaStr devices.push_back(content::MediaStreamDevice( content::MEDIA_DESKTOP_VIDEO_CAPTURE, mediaId.ToString(), "Screen")); if (captureAudio) { - // Use the special loopback device ID for system audio capture. devices.push_back(content::MediaStreamDevice( - content::MEDIA_LOOPBACK_AUDIO_CAPTURE, + content::MEDIA_DESKTOP_AUDIO_CAPTURE, media::AudioManagerBase::kLoopbackInputDeviceId, "System Audio")); } @@ -225,7 +224,7 @@ void MediaCaptureDevicesDispatcher::processMediaAccessRequest(WebContentsAdapter if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE || request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE) return; - if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE) + if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) // It's still unclear what to make of screen capture. We can rely on existing javascript dialog infrastructure // to experiment with this without exposing it through our API yet. processDesktopCaptureAccessRequest(webContents, request, callback); @@ -279,7 +278,7 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content:: // Audio is only supported for screen capture streams. bool capture_audio = (mediaId.type == content::DesktopMediaID::TYPE_SCREEN && - request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE); + request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE); ui = getDevicesForDesktopCapture( devices, mediaId, capture_audio, true, @@ -305,8 +304,8 @@ void MediaCaptureDevicesDispatcher::processScreenCaptureAccessRequest(content::W base::Unretained(this), base::Unretained(webContents)); QUrl securityOrigin(toQt(request.security_origin)); - QString message = QObject::tr("Do you want %1 to share your screen?").arg(securityOrigin.toString()); - QString title = QObject::tr("%1 Screen Sharing request").arg(securityOrigin.toString()); + QString message = QCoreApplication::translate("MediaCaptureDevicesDispatcher", "Do you want %1 to share your screen?").arg(securityOrigin.toString()); + QString title = QCoreApplication::translate("MediaCaptureDevicesDispatcher", "%1 Screen Sharing request").arg(securityOrigin.toString()); JavaScriptDialogManagerQt::GetInstance()->runDialogForContents(webContents, WebContentsAdapterClient::InternalAuthorizationDialog, message , QString(), securityOrigin, dialogCallback, title); } else diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp index 4e726fec8..3f67e7c0d 100644 --- a/src/core/network_delegate_qt.cpp +++ b/src/core/network_delegate_qt.cpp @@ -36,13 +36,19 @@ #include "network_delegate_qt.h" +#include "browser_context_adapter.h" #include "content/public/browser/browser_thread.h" #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 "cookie_monster_delegate_qt.h" #include "ui/base/page_transition_types.h" +#include "url_request_context_getter_qt.h" #include "net/base/load_flags.h" #include "net/url_request/url_request.h" +#include "qwebengineurlrequestinfo.h" +#include "qwebengineurlrequestinfo_p.h" +#include "qwebengineurlrequestinterceptor.h" #include "type_conversion.h" #include "web_contents_adapter_client.h" #include "web_contents_view_qt.h" @@ -56,11 +62,11 @@ int pageTransitionToNavigationType(ui::PageTransition transition) if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK) return WebContentsAdapterClient::BackForwardNavigation; - ui::PageTransition stippedTransition = ui::PageTransitionStripQualifier(transition); + ui::PageTransition strippedTransition = ui::PageTransitionStripQualifier(transition); - switch (stippedTransition) { + switch (strippedTransition) { case ui::PAGE_TRANSITION_LINK: - return WebContentsAdapterClient::LinkClickedNavigation; + return WebContentsAdapterClient::LinkNavigation; case ui::PAGE_TRANSITION_TYPED: return WebContentsAdapterClient::TypedNavigation; case ui::PAGE_TRANSITION_FORM_SUBMIT: @@ -72,29 +78,69 @@ int pageTransitionToNavigationType(ui::PageTransition transition) } } -int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::CompletionCallback &callback, GURL *) +NetworkDelegateQt::NetworkDelegateQt(URLRequestContextGetterQt *requestContext) + : m_requestContextGetter(requestContext) +{ +} + +int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::CompletionCallback &callback, GURL *newUrl) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - const content::ResourceRequestInfo *info = content::ResourceRequestInfo::ForRequest(request); - if (!info) + Q_ASSERT(m_requestContextGetter); + Q_ASSERT(m_requestContextGetter->m_browserContext); + + const content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request); + + content::ResourceType resourceType = content::RESOURCE_TYPE_LAST_TYPE; + int navigationType = QWebEngineUrlRequestInfo::NavigationTypeOther; + + if (resourceInfo) { + resourceType = resourceInfo->GetResourceType(); + navigationType = pageTransitionToNavigationType(resourceInfo->GetPageTransition()); + } + + const QUrl qUrl = toQt(request->url()); + + QWebEngineUrlRequestInterceptor* interceptor = m_requestContextGetter->m_browserContext->requestInterceptor(); + if (interceptor) { + QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType) + , static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType) + , qUrl + , toQt(request->first_party_for_cookies()) + , QByteArray::fromStdString(request->method())); + QWebEngineUrlRequestInfo requestInfo(infoPrivate); + if (interceptor->interceptRequest(requestInfo)) { + int result = infoPrivate->shouldBlockRequest ? net::ERR_ABORTED : net::OK; + + if (qUrl != infoPrivate->url) + *newUrl = toGurl(infoPrivate->url); + + if (!infoPrivate->extraHeaders.isEmpty()) { + auto end = infoPrivate->extraHeaders.constEnd(); + for (auto header = infoPrivate->extraHeaders.constBegin(); header != end; ++header) + request->SetExtraRequestHeaderByName(header.key().toStdString(), header.value().toStdString(), /* overwrite */ true); + } + + return result; + } + } + + if (!resourceInfo) return net::OK; - content::ResourceType resourceType = info->GetResourceType(); int renderProcessId; int renderFrameId; // Only intercept MAIN_FRAME and SUB_FRAME with an associated render frame. - if (!content::IsResourceTypeFrame(resourceType) || !info->GetRenderFrameForRequest(request, &renderProcessId, &renderFrameId)) + if (!content::IsResourceTypeFrame(resourceType) || !resourceInfo->GetRenderFrameForRequest(request, &renderProcessId, &renderFrameId)) return net::OK; // Track active requests since |callback| and |new_url| are valid // only until OnURLRequestDestroyed is called for this request. m_activeRequests.insert(request); - int navigationType = pageTransitionToNavigationType(info->GetPageTransition()); - RequestParams params = { - toQt(request->url()), - info->IsMainFrame(), + qUrl, + resourceInfo->IsMainFrame(), navigationType, renderProcessId, renderFrameId @@ -172,4 +218,88 @@ void NetworkDelegateQt::NotifyNavigationRequestedOnUIThread(net::URLRequest *req ); } +bool NetworkDelegateQt::OnCanSetCookie(const net::URLRequest& request, + const std::string& cookie_line, + net::CookieOptions*) +{ + Q_ASSERT(m_requestContextGetter); + return m_requestContextGetter->m_cookieDelegate->canSetCookie(toQt(request.first_party_for_cookies()), QByteArray::fromStdString(cookie_line), toQt(request.url())); +} + +void NetworkDelegateQt::OnResolveProxy(const GURL&, int, const net::ProxyService&, net::ProxyInfo*) +{ +} + +void NetworkDelegateQt::OnProxyFallback(const net::ProxyServer&, int) +{ +} + +int NetworkDelegateQt::OnBeforeSendHeaders(net::URLRequest*, const net::CompletionCallback&, net::HttpRequestHeaders*) +{ + return net::OK; +} + +void NetworkDelegateQt::OnBeforeSendProxyHeaders(net::URLRequest*, const net::ProxyInfo&, net::HttpRequestHeaders*) +{ +} + +void NetworkDelegateQt::OnSendHeaders(net::URLRequest*, const net::HttpRequestHeaders&) +{ +} + +int NetworkDelegateQt::OnHeadersReceived(net::URLRequest*, const net::CompletionCallback&, const net::HttpResponseHeaders*, scoped_refptr<net::HttpResponseHeaders>*, GURL*) +{ + return net::OK; +} + +void NetworkDelegateQt::OnBeforeRedirect(net::URLRequest*, const GURL&) +{ +} + +void NetworkDelegateQt::OnResponseStarted(net::URLRequest*) +{ +} + +void NetworkDelegateQt::OnRawBytesRead(const net::URLRequest&, int) +{ +} + +void NetworkDelegateQt::OnCompleted(net::URLRequest*, bool) +{ +} + +void NetworkDelegateQt::OnPACScriptError(int, const base::string16&) +{ +} + +net::NetworkDelegate::AuthRequiredResponse NetworkDelegateQt::OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, const AuthCallback&, net::AuthCredentials*) +{ + return AUTH_REQUIRED_RESPONSE_NO_ACTION; +} + +bool NetworkDelegateQt::OnCanGetCookies(const net::URLRequest&, const net::CookieList&) +{ + return true; +} + +bool NetworkDelegateQt::OnCanAccessFile(const net::URLRequest& request, const base::FilePath& path) const +{ + return true; +} + +bool NetworkDelegateQt::OnCanEnablePrivacyMode(const GURL&, const GURL&) const +{ + return false; +} + +bool NetworkDelegateQt::OnFirstPartyOnlyCookieExperimentEnabled() const +{ + return false; +} + +bool NetworkDelegateQt::OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const +{ + return false; +} + } // namespace QtWebEngineCore diff --git a/src/core/network_delegate_qt.h b/src/core/network_delegate_qt.h index 4f4097fd3..41b5b98b6 100644 --- a/src/core/network_delegate_qt.h +++ b/src/core/network_delegate_qt.h @@ -42,19 +42,16 @@ #include <QUrl> #include <QSet> -#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE namespace QtWebEngineCore { +class URLRequestContextGetterQt; + class NetworkDelegateQt : public net::NetworkDelegate { + QSet<net::URLRequest *> m_activeRequests; + URLRequestContextGetterQt *m_requestContextGetter; public: - NetworkDelegateQt() {} - virtual ~NetworkDelegateQt() {} - - // net::NetworkDelegate implementation - virtual int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* new_url) Q_DECL_OVERRIDE; - virtual void OnURLRequestDestroyed(net::URLRequest* request) Q_DECL_OVERRIDE; - virtual bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& path) const Q_DECL_OVERRIDE { return true; } + NetworkDelegateQt(URLRequestContextGetterQt *requestContext); struct RequestParams { QUrl url; @@ -72,7 +69,27 @@ public: int navigationRequestAction, const net::CompletionCallback &callback); - QSet<net::URLRequest *> m_activeRequests; + // net::NetworkDelegate implementation + virtual int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* newUrl) override; + virtual void OnURLRequestDestroyed(net::URLRequest* request) override; + virtual bool OnCanSetCookie(const net::URLRequest&, const std::string&, net::CookieOptions*) override; + virtual void OnResolveProxy(const GURL&, int, const net::ProxyService&, net::ProxyInfo*) override; + virtual void OnProxyFallback(const net::ProxyServer&, int) override; + virtual int OnBeforeSendHeaders(net::URLRequest*, const net::CompletionCallback&, net::HttpRequestHeaders*) override; + virtual void OnBeforeSendProxyHeaders(net::URLRequest*, const net::ProxyInfo&, net::HttpRequestHeaders*) override; + virtual void OnSendHeaders(net::URLRequest*, const net::HttpRequestHeaders&) override; + virtual int OnHeadersReceived(net::URLRequest*, const net::CompletionCallback&, const net::HttpResponseHeaders*, scoped_refptr<net::HttpResponseHeaders>*, GURL*) override; + virtual void OnBeforeRedirect(net::URLRequest*, const GURL&) override; + virtual void OnResponseStarted(net::URLRequest*) override; + virtual void OnRawBytesRead(const net::URLRequest&, int) override; + virtual void OnCompleted(net::URLRequest*, bool) override; + virtual void OnPACScriptError(int, const base::string16&) override; + virtual net::NetworkDelegate::AuthRequiredResponse OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, const AuthCallback&, net::AuthCredentials*) override; + virtual bool OnCanGetCookies(const net::URLRequest&, const net::CookieList&) override; + virtual bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& path) const override; + virtual bool OnCanEnablePrivacyMode(const GURL&, const GURL&) const override; + virtual bool OnFirstPartyOnlyCookieExperimentEnabled() const override; + virtual bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const override; }; } // namespace QtWebEngineCore diff --git a/src/core/ozone_platform_eglfs.cpp b/src/core/ozone_platform_eglfs.cpp index 43a3e4a11..834e41fdf 100644 --- a/src/core/ozone_platform_eglfs.cpp +++ b/src/core/ozone_platform_eglfs.cpp @@ -45,6 +45,7 @@ #include "ui/events/ozone/events_ozone.h" #include "ui/events/platform/platform_event_dispatcher.h" #include "ui/ozone/common/native_display_delegate_ozone.h" +#include "ui/ozone/common/stub_overlay_manager.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/cursor_factory_ozone.h" #include "ui/ozone/public/gpu_platform_support.h" @@ -95,6 +96,7 @@ public: void Restore() override { } void SetCursor(PlatformCursor) override { } void MoveCursorTo(const gfx::Point&) override { } + void ConfineCursorToBounds(const gfx::Rect&) override { } // PlatformEventDispatcher: bool CanDispatchEvent(const PlatformEvent& event) override; @@ -160,6 +162,18 @@ scoped_ptr<PlatformWindow> OzonePlatformEglfs::CreatePlatformWindow( bounds)); } +ui::InputController* OzonePlatformEglfs::GetInputController() { + return input_controller_.get(); +} + +scoped_ptr<ui::SystemInputInjector> OzonePlatformEglfs::CreateSystemInputInjector() { + return nullptr; // no input injection support. +} + +ui::OverlayManagerOzone* OzonePlatformEglfs::GetOverlayManager() { + return overlay_manager_.get(); +} + scoped_ptr<ui::NativeDisplayDelegate> OzonePlatformEglfs::CreateNativeDisplayDelegate() { return scoped_ptr<NativeDisplayDelegate>(new NativeDisplayDelegateOzone()); @@ -168,10 +182,12 @@ scoped_ptr<ui::NativeDisplayDelegate> OzonePlatformEglfs::CreateNativeDisplayDel OzonePlatform* CreateOzonePlatformEglfs() { return new OzonePlatformEglfs; } void OzonePlatformEglfs::InitializeUI() { + overlay_manager_.reset(new StubOverlayManager()); device_manager_ = CreateDeviceManager(); cursor_factory_ozone_.reset(new CursorFactoryOzone()); - event_factory_ozone_.reset(new EventFactoryEvdev(NULL, device_manager_.get())); + event_factory_ozone_.reset(new EventFactoryEvdev(NULL, device_manager_.get(), NULL)); gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost()); + input_controller_ = CreateStubInputController(); } void OzonePlatformEglfs::InitializeGPU() { diff --git a/src/core/ozone_platform_eglfs.h b/src/core/ozone_platform_eglfs.h index 6954595dd..69ff2508f 100644 --- a/src/core/ozone_platform_eglfs.h +++ b/src/core/ozone_platform_eglfs.h @@ -62,6 +62,9 @@ class OzonePlatformEglfs : public OzonePlatform { PlatformWindowDelegate* delegate, const gfx::Rect& bounds) override; virtual scoped_ptr<ui::NativeDisplayDelegate> CreateNativeDisplayDelegate() override; + virtual ui::InputController* GetInputController() override; + virtual scoped_ptr<ui::SystemInputInjector> CreateSystemInputInjector() override; + virtual ui::OverlayManagerOzone* GetOverlayManager() override; private: virtual void InitializeUI() override; @@ -74,6 +77,8 @@ class OzonePlatformEglfs : public OzonePlatform { scoped_ptr<GpuPlatformSupport> gpu_platform_support_; scoped_ptr<GpuPlatformSupportHost> gpu_platform_support_host_; + scoped_ptr<InputController> input_controller_; + scoped_ptr<OverlayManagerOzone> overlay_manager_; DISALLOW_COPY_AND_ASSIGN(OzonePlatformEglfs); }; diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp new file mode 100644 index 000000000..d89b530ee --- /dev/null +++ b/src/core/permission_manager_qt.cpp @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "permission_manager_qt.h" + +#include "content/browser/renderer_host/render_view_host_delegate.h" +#include "content/public/browser/permission_type.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" + +#include "type_conversion.h" +#include "web_contents_delegate_qt.h" + +namespace QtWebEngineCore { + +BrowserContextAdapter::PermissionType toQt(content::PermissionType type) +{ + switch (type) { + case content::PermissionType::GEOLOCATION: + return BrowserContextAdapter::GeolocationPermission; + case content::PermissionType::NOTIFICATIONS: + case content::PermissionType::MIDI_SYSEX: + case content::PermissionType::PUSH_MESSAGING: + case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER: + case content::PermissionType::NUM: + break; + } + return BrowserContextAdapter::UnsupportedPermission; +} + +PermissionManagerQt::PermissionManagerQt(BrowserContextAdapter *contextAdapter) + : m_contextAdapter(contextAdapter) + , m_subscriberCount(0) +{ +} + +PermissionManagerQt::~PermissionManagerQt() +{ +} + +void PermissionManagerQt::permissionRequestReply(const QUrl &origin, BrowserContextAdapter::PermissionType type, bool reply) +{ + QPair<QUrl, BrowserContextAdapter::PermissionType> key(origin, type); + m_permissions[key] = reply; + content::PermissionStatus status = reply ? content::PERMISSION_STATUS_GRANTED : content::PERMISSION_STATUS_DENIED; + auto it = m_requests.begin(); + const auto end = m_requests.end(); + while (it != end) { + if (it->origin == origin && it->type == type) { + it->callback.Run(status); + it = m_requests.erase(it); + } else + ++it; + } + Q_FOREACH (const Subscriber &subscriber, m_subscribers) { + if (subscriber.origin == origin && subscriber.type == type) + subscriber.callback.Run(status); + } +} + +void PermissionManagerQt::RequestPermission(content::PermissionType permission, + content::RenderFrameHost *frameHost, + int request_id, + const GURL& requesting_origin, + bool user_gesture, + const base::Callback<void(content::PermissionStatus)>& callback) +{ + Q_UNUSED(user_gesture); + BrowserContextAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == BrowserContextAdapter::UnsupportedPermission) { + callback.Run(content::PERMISSION_STATUS_DENIED); + return; + } + + content::WebContents *webContents = frameHost->GetRenderViewHost()->GetDelegate()->GetAsWebContents(); + WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); + Q_ASSERT(contentsDelegate); + Request request = { + request_id, + permissionType, + toQt(requesting_origin), + callback + }; + m_requests.append(request); + if (permissionType == BrowserContextAdapter::GeolocationPermission) + contentsDelegate->requestGeolocationPermission(request.origin); +} + +void PermissionManagerQt::CancelPermissionRequest(content::PermissionType permission, + content::RenderFrameHost *frameHost, + int request_id, + const GURL& requesting_origin) +{ + Q_UNUSED(frameHost); + const BrowserContextAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == BrowserContextAdapter::UnsupportedPermission) + return; + + // Should we add API to cancel permissions in the UI level? + const QUrl origin = toQt(requesting_origin); + auto it = m_requests.begin(); + const auto end = m_requests.end(); + while (it != end) { + if (it->id == request_id && it->type == permissionType && it->origin == origin) { + m_requests.erase(it); + return; + } + } + qWarning() << "PermissionManagerQt::CancelPermissionRequest called on unknown request" << request_id << origin << permissionType; +} + +content::PermissionStatus PermissionManagerQt::GetPermissionStatus( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& /*embedding_origin*/) +{ + const BrowserContextAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == BrowserContextAdapter::UnsupportedPermission) + return content::PERMISSION_STATUS_DENIED; + + QPair<QUrl, BrowserContextAdapter::PermissionType> key(toQt(requesting_origin), permissionType); + if (!m_permissions.contains(key)) + return content::PERMISSION_STATUS_ASK; + if (m_permissions[key]) + return content::PERMISSION_STATUS_GRANTED; + return content::PERMISSION_STATUS_DENIED; +} + +void PermissionManagerQt::ResetPermission( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& /*embedding_origin*/) +{ + const BrowserContextAdapter::PermissionType permissionType = toQt(permission); + if (permissionType == BrowserContextAdapter::UnsupportedPermission) + return; + + QPair<QUrl, BrowserContextAdapter::PermissionType> key(toQt(requesting_origin), permissionType); + m_permissions.remove(key); +} + +void PermissionManagerQt::RegisterPermissionUsage( + content::PermissionType /*permission*/, + const GURL& /*requesting_origin*/, + const GURL& /*embedding_origin*/) +{ + // We do not currently track which permissions are used. +} + +int PermissionManagerQt::SubscribePermissionStatusChange( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& /*embedding_origin*/, + const base::Callback<void(content::PermissionStatus)>& callback) +{ + Subscriber subscriber = { + m_subscriberCount++, + toQt(permission), + toQt(requesting_origin), + callback + }; + m_subscribers.append(subscriber); + return subscriber.id; +} + +void PermissionManagerQt::UnsubscribePermissionStatusChange(int subscription_id) +{ + for (int i = 0; i < m_subscribers.count(); i++) { + if (m_subscribers[i].id == subscription_id) { + m_subscribers.removeAt(i); + return; + } + } + qWarning() << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id; +} + +} // namespace QtWebEngineCore diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h new file mode 100644 index 000000000..d4ee72bae --- /dev/null +++ b/src/core/permission_manager_qt.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 PERMISSION_MANAGER_QT_H +#define PERMISSION_MANAGER_QT_H + +#include "base/callback.h" +#include "content/public/browser/permission_manager.h" +#include "browser_context_adapter.h" + +#include <QHash> +#include <QList> + +namespace QtWebEngineCore { + +class PermissionManagerQt : public content::PermissionManager { + +public: + PermissionManagerQt(BrowserContextAdapter *); + ~PermissionManagerQt(); + typedef BrowserContextAdapter::PermissionType PermissionType; + + void permissionRequestReply(const QUrl &origin, PermissionType type, bool reply); + + // content::PermissionManager implementation: + void RequestPermission( + content::PermissionType permission, + content::RenderFrameHost* render_frame_host, + int request_id, + const GURL& requesting_origin, + bool user_gesture, + const base::Callback<void(content::PermissionStatus)>& callback) override; + + void CancelPermissionRequest( + content::PermissionType permission, + content::RenderFrameHost* render_frame_host, + int request_id, + const GURL& requesting_origin) override; + + content::PermissionStatus GetPermissionStatus( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) override; + + void ResetPermission( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) override; + + void RegisterPermissionUsage( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin) override; + + int SubscribePermissionStatusChange( + content::PermissionType permission, + const GURL& requesting_origin, + const GURL& embedding_origin, + const base::Callback<void(content::PermissionStatus)>& callback) override; + + void UnsubscribePermissionStatusChange(int subscription_id) override; + +private: + BrowserContextAdapter *m_contextAdapter; + QHash<QPair<QUrl, PermissionType>, bool> m_permissions; + struct Request { + int id; + PermissionType type; + QUrl origin; + base::Callback<void(content::PermissionStatus)> callback; + }; + QList<Request> m_requests; + struct Subscriber { + int id; + PermissionType type; + QUrl origin; + base::Callback<void(content::PermissionStatus)> callback; + }; + int m_subscriberCount; + QList<Subscriber> m_subscribers; + +}; + +} // namespace QtWebEngineCore + +#endif // PERMISSION_MANAGER_QT_H diff --git a/src/core/proxy_config_service_qt.cpp b/src/core/proxy_config_service_qt.cpp new file mode 100644 index 000000000..fc0959eef --- /dev/null +++ b/src/core/proxy_config_service_qt.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "proxy_config_service_qt.h" + +#include "base/bind.h" +#include "content/public/browser/browser_thread.h" + +using content::BrowserThread; + +net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qtProxy) +{ + net::ProxyServer::Scheme proxyScheme = net::ProxyServer::SCHEME_INVALID; + switch (qtProxy.type()) { + case QNetworkProxy::Socks5Proxy: + proxyScheme = net::ProxyServer::SCHEME_SOCKS5; + break; + case QNetworkProxy::HttpProxy: + case QNetworkProxy::HttpCachingProxy: + case QNetworkProxy::FtpCachingProxy: + proxyScheme = net::ProxyServer::SCHEME_HTTP; + break; + case QNetworkProxy::NoProxy: + default: + proxyScheme = net::ProxyServer::SCHEME_DIRECT; + break; + } + return net::ProxyServer(proxyScheme, net::HostPortPair(qtProxy.hostName().toStdString(), qtProxy.port())); +} + +//================ Based on ChromeProxyConfigService ======================= + +ProxyConfigServiceQt::ProxyConfigServiceQt(net::ProxyConfigService *baseService) + : m_baseService(baseService), + m_registeredObserver(false) +{ +} + +ProxyConfigServiceQt::~ProxyConfigServiceQt() +{ + if (m_registeredObserver && m_baseService.get()) + m_baseService->RemoveObserver(this); +} + +void ProxyConfigServiceQt::AddObserver(net::ProxyConfigService::Observer *observer) +{ + RegisterObserver(); + m_observers.AddObserver(observer); +} + +void ProxyConfigServiceQt::RemoveObserver(net::ProxyConfigService::Observer *observer) +{ + m_observers.RemoveObserver(observer); +} + +net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxyConfig(net::ProxyConfig *config) +{ + RegisterObserver(); + + // Ask the base service if available. + net::ProxyConfig systemConfig; + ConfigAvailability systemAvailability = net::ProxyConfigService::CONFIG_UNSET; + if (m_baseService.get()) + systemAvailability = m_baseService->GetLatestProxyConfig(&systemConfig); + + const QNetworkProxy &qtProxy = QNetworkProxy::applicationProxy(); + if (qtProxy == m_qtApplicationProxy && !m_qtProxyConfig.proxy_rules().empty()) { + *config = m_qtProxyConfig; + return CONFIG_VALID; + } + m_qtApplicationProxy = qtProxy; + m_qtProxyConfig = net::ProxyConfig(); + if (qtProxy.type() == QNetworkProxy::NoProxy) { + *config = systemConfig; + return systemAvailability; + } + + net::ProxyConfig::ProxyRules qtRules; + net::ProxyServer server = fromQNetworkProxy(qtProxy); + switch (qtProxy.type()) { + case QNetworkProxy::HttpProxy: + case QNetworkProxy::Socks5Proxy: + qtRules.type = net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY; + qtRules.single_proxies.SetSingleProxyServer(server); + break; + case QNetworkProxy::HttpCachingProxy: + qtRules.type = net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + qtRules.proxies_for_http.SetSingleProxyServer(server); + break; + case QNetworkProxy::FtpCachingProxy: + qtRules.type = net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME; + qtRules.proxies_for_ftp.SetSingleProxyServer(server); + break; + default: + qtRules.type = net::ProxyConfig::ProxyRules::TYPE_NO_RULES; + } + + m_qtProxyConfig.proxy_rules() = qtRules; + *config = m_qtProxyConfig; + return CONFIG_VALID; +} + +void ProxyConfigServiceQt::OnLazyPoll() +{ + if (m_qtApplicationProxy != QNetworkProxy::applicationProxy()) { + net::ProxyConfig unusedConfig; + OnProxyConfigChanged(unusedConfig, CONFIG_VALID); + } + if (m_baseService.get()) + m_baseService->OnLazyPoll(); +} + + +void ProxyConfigServiceQt::OnProxyConfigChanged(const net::ProxyConfig &config, ConfigAvailability availability) +{ + Q_UNUSED(config); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + if (m_qtApplicationProxy != QNetworkProxy::applicationProxy() + || m_qtApplicationProxy.type() == QNetworkProxy::NoProxy) { + net::ProxyConfig actual_config; + availability = GetLatestProxyConfig(&actual_config); + if (availability == CONFIG_PENDING) + return; + FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, m_observers, + OnProxyConfigChanged(actual_config, availability)); + } +} + +void ProxyConfigServiceQt::RegisterObserver() +{ + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (!m_registeredObserver && m_baseService.get()) { + m_baseService->AddObserver(this); + m_registeredObserver = true; + } +} diff --git a/src/core/proxy_config_service_qt.h b/src/core/proxy_config_service_qt.h new file mode 100644 index 000000000..ee4263314 --- /dev/null +++ b/src/core/proxy_config_service_qt.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 PROXY_CONFIG_SERVICE_QT_H +#define PROXY_CONFIG_SERVICE_QT_H + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" + +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_config_service.h" + +#include <QNetworkProxy> + +class ProxyConfigServiceQt + : public net::ProxyConfigService, + public net::ProxyConfigService::Observer { +public: + + static net::ProxyServer fromQNetworkProxy(const QNetworkProxy &); + + explicit ProxyConfigServiceQt(net::ProxyConfigService *baseService); + ~ProxyConfigServiceQt() override; + + // ProxyConfigService implementation: + void AddObserver(net::ProxyConfigService::Observer *observer) override; + void RemoveObserver(net::ProxyConfigService::Observer *observer) override; + ConfigAvailability GetLatestProxyConfig(net::ProxyConfig *config) override; + void OnLazyPoll() override; + +private: + // ProxyConfigService::Observer implementation: + void OnProxyConfigChanged(const net::ProxyConfig& config, + ConfigAvailability availability) override; + + // Makes sure that the observer registration with the base service is set up. + void RegisterObserver(); + + scoped_ptr<net::ProxyConfigService> m_baseService; + base::ObserverList<net::ProxyConfigService::Observer, true> m_observers; + + // Keep the last QNetworkProxy::applicationProxy state around. + QNetworkProxy m_qtApplicationProxy; + net::ProxyConfig m_qtProxyConfig; + + // Indicates whether the base service registration is done. + bool m_registeredObserver; + + DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceQt); +}; + +#endif // PROXY_CONFIG_SERVICE_QT_H diff --git a/src/core/qtwebengine.gypi b/src/core/qtwebengine.gypi index b8af2aca8..a420918a0 100644 --- a/src/core/qtwebengine.gypi +++ b/src/core/qtwebengine.gypi @@ -8,6 +8,8 @@ '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:devtools_discovery', + '<(chromium_src_dir)/components/components.gyp:devtools_http_handler', '<(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', @@ -16,6 +18,7 @@ '<(chromium_src_dir)/content/content.gyp:content_browser', '<(chromium_src_dir)/content/content.gyp:content_common', '<(chromium_src_dir)/content/content.gyp:content_gpu', + '<(chromium_src_dir)/content/content.gyp:content_ppapi_plugin', '<(chromium_src_dir)/content/content.gyp:content_renderer', '<(chromium_src_dir)/content/content.gyp:content_utility', '<(chromium_src_dir)/content/app/resources/content_resources.gyp:content_resources', @@ -81,6 +84,9 @@ ], }, }, + 'dependencies': [ + '<(chromium_src_dir)/ui/events/ozone/events_ozone.gyp:events_ozone_evdev' + ] }], ['qt_os=="win32" and qt_gl=="opengl"', { 'include_dirs': [ diff --git a/src/core/qtwebengine_extras.gypi b/src/core/qtwebengine_extras.gypi index e28d6436e..a5de08b55 100644 --- a/src/core/qtwebengine_extras.gypi +++ b/src/core/qtwebengine_extras.gypi @@ -57,6 +57,8 @@ ['exclude', 'win/accessibility_ids_win\\.h$'], ['exclude', 'win/accessibility_misc_utils\\.(cc|h)$'], ['exclude', 'win/atl_module\\.h$'], + ['exclude', 'platform/ax_platform_node_win\\.(cc|h)$'], + ['exclude', 'audio_classifier\\.(cc|h)$'], ], 'defines': [ 'TOOLKIT_QT', diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 7c5ed64e7..90c91fd47 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -36,10 +36,12 @@ #include "render_widget_host_view_qt.h" +#include "common/qt_messages.h" #include "browser_accessibility_manager_qt.h" #include "browser_accessibility_qt.h" #include "chromium_overrides.h" #include "delegated_frame_node.h" +#include "qtwebenginecoreglobal_p.h" #include "render_widget_host_view_qt_delegate.h" #include "type_conversion.h" #include "web_contents_adapter.h" @@ -60,10 +62,11 @@ #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/blink/blink_event_util.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" +#include "ui/gfx/geometry/size_conversions.h" #include <QEvent> #include <QFocusEvent> @@ -142,7 +145,7 @@ static inline int firstAvailableId(const QMap<int, int> &map) } static inline ui::GestureProvider::Config QtGestureProviderConfig() { - ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig(); + ui::GestureProvider::Config config = ui::GetGestureProviderConfig(ui::GestureProviderConfigType::CURRENT_PLATFORM); // Causes an assert in CreateWebGestureEventFromGestureEventData and we don't need them in Qt. config.gesture_begin_end_types_enabled = false; config.gesture_detector_config.swipe_enabled = false; @@ -180,12 +183,14 @@ static inline int flagsFromModifiers(Qt::KeyboardModifiers modifiers) return modifierFlags; } +static uint32 s_eventId = 0; class MotionEventQt : public ui::MotionEvent { public: MotionEventQt(const QList<QTouchEvent::TouchPoint> &touchPoints, const base::TimeTicks &eventTime, Action action, const Qt::KeyboardModifiers modifiers, float dpiScale, int index = -1) : touchPoints(touchPoints) , eventTime(eventTime) , action(action) + , eventId(++s_eventId) , flags(flagsFromModifiers(modifiers)) , index(index) , dpiScale(dpiScale) @@ -194,7 +199,7 @@ public: Q_ASSERT((action != ACTION_DOWN && action != ACTION_UP) || index == 0); } - virtual int GetId() const Q_DECL_OVERRIDE { return 0; } + virtual uint32 GetUniqueEventId() const Q_DECL_OVERRIDE { return eventId; } virtual Action GetAction() const Q_DECL_OVERRIDE { return action; } virtual int GetActionIndex() const Q_DECL_OVERRIDE { return index; } virtual size_t GetPointerCount() const Q_DECL_OVERRIDE { return touchPoints.size(); } @@ -233,6 +238,7 @@ private: QList<QTouchEvent::TouchPoint> touchPoints; base::TimeTicks eventTime; Action action; + const uint32 eventId; int flags; int index; float dpiScale; @@ -410,6 +416,14 @@ gfx::Rect RenderWidgetHostViewQt::GetViewBounds() const return gfx::BoundingRect(p1, p2); } +void RenderWidgetHostViewQt::SetBackgroundColor(SkColor color) { + RenderWidgetHostViewBase::SetBackgroundColor(color); + // Set the background of the compositor if necessary + m_delegate->setClearColor(toQt(color)); + // Set the background of the blink::FrameView + m_host->Send(new QtRenderViewObserver_SetBackgroundColor(m_host->GetRoutingID(), color)); +} + // Return value indicates whether the mouse is locked successfully or not. bool RenderWidgetHostViewQt::LockMouse() { @@ -428,27 +442,11 @@ void RenderWidgetHostViewQt::UnlockMouse() m_host->LostMouseLock(); } -void RenderWidgetHostViewQt::WasShown() -{ - m_host->WasShown(ui::LatencyInfo()); -} - -void RenderWidgetHostViewQt::WasHidden() -{ - m_host->WasHidden(); -} - void RenderWidgetHostViewQt::MovePluginWindows(const std::vector<content::WebPluginGeometry>&) { // QT_NOT_YET_IMPLEMENTED } -void RenderWidgetHostViewQt::Blur() -{ - m_host->SetInputMethodActive(false); - m_host->Blur(); -} - void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) { content::WebCursor::CursorInfo cursorInfo; @@ -571,8 +569,11 @@ void RenderWidgetHostViewQt::ImeCompositionRangeChanged(const gfx::Range&, const QT_NOT_YET_IMPLEMENTED } -void RenderWidgetHostViewQt::RenderProcessGone(base::TerminationStatus, int) +void RenderWidgetHostViewQt::RenderProcessGone(base::TerminationStatus terminationStatus, + int exitCode) { + m_adapterClient->renderProcessTerminated( + m_adapterClient->renderProcessExitStatus(terminationStatus), exitCode); Destroy(); } @@ -602,13 +603,13 @@ void RenderWidgetHostViewQt::SelectionBoundsChanged(const ViewHostMsg_SelectionB m_cursorRect = QRect(caretRect.x(), caretRect.y(), caretRect.width(), caretRect.height()); } -void RenderWidgetHostViewQt::CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, content::CopyFromCompositingSurfaceCallback& callback, const SkColorType color_type) +void RenderWidgetHostViewQt::CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, content::ReadbackRequestCallback& callback, const SkColorType color_type) { NOTIMPLEMENTED(); Q_UNUSED(src_subrect); Q_UNUSED(dst_size); Q_UNUSED(color_type); - callback.Run(false, SkBitmap()); + callback.Run(SkBitmap(), content::READBACK_FAILED); } void RenderWidgetHostViewQt::CopyFromCompositingSurfaceToVideoFrame(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(bool)>& callback) @@ -690,7 +691,7 @@ void RenderWidgetHostViewQt::SelectionChanged(const base::string16 &text, size_t void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture) { - m_host->ForwardGestureEvent(content::CreateWebGestureEventFromGestureEventData(gesture)); + m_host->ForwardGestureEvent(ui::CreateWebGestureEventFromGestureEventData(gesture)); } QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode) @@ -719,12 +720,12 @@ void RenderWidgetHostViewQt::notifyResize() void RenderWidgetHostViewQt::notifyShown() { - WasShown(); + m_host->WasShown(ui::LatencyInfo()); } void RenderWidgetHostViewQt::notifyHidden() { - WasHidden(); + m_host->WasHidden(); } void RenderWidgetHostViewQt::windowBoundsChanged() @@ -810,7 +811,7 @@ QVariant RenderWidgetHostViewQt::inputMethodQuery(Qt::InputMethodQuery query) co void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) { Q_UNUSED(touch); const bool eventConsumed = ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED; - m_gestureProvider.OnTouchEventAck(eventConsumed); + m_gestureProvider.OnTouchEventAck(touch.event.uniqueTouchEventId, eventConsumed); } void RenderWidgetHostViewQt::sendDelegatedFrameAck() @@ -824,16 +825,10 @@ void RenderWidgetHostViewQt::sendDelegatedFrameAck() void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEvent) { - if (!m_gestureProvider.OnTouchEvent(motionEvent)) + if (!m_gestureProvider.OnTouchEvent(motionEvent).succeeded) return; - // Short-circuit touch forwarding if no touch handlers exist. - if (!m_host->ShouldForwardTouchEvent()) { - const bool eventConsumed = false; - m_gestureProvider.OnTouchEventAck(eventConsumed); - return; - } - blink::WebTouchEvent touchEvent = content::CreateWebTouchEventFromMotionEvent(motionEvent); + blink::WebTouchEvent touchEvent = ui::CreateWebTouchEventFromMotionEvent(motionEvent, false); m_host->ForwardTouchEventWithLatencyInfo(touchEvent, CreateLatencyInfo(touchEvent)); } @@ -933,14 +928,9 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev) if (preeditString.isEmpty()) break; - 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, backgroundColor)); + underlines.push_back(blink::WebCompositionUnderline(start, end, /*color*/ SK_ColorBLACK, /*thick*/ false, /*backgroundColor*/ SK_ColorTRANSPARENT)); break; } case QInputMethodEvent::Cursor: diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 248c52f6e..274138dcf 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -47,6 +47,7 @@ #include "content/common/gpu/gpu_messages.h" #include "content/common/view_messages.h" #include "ui/events/gesture_detection/filtered_gesture_provider.h" +#include "qtwebenginecoreglobal_p.h" #include <QMap> #include <QPoint> #include <QRect> @@ -125,12 +126,10 @@ public: virtual void Hide() Q_DECL_OVERRIDE; virtual bool IsShowing() Q_DECL_OVERRIDE; virtual gfx::Rect GetViewBounds() const Q_DECL_OVERRIDE; + virtual void SetBackgroundColor(SkColor color) Q_DECL_OVERRIDE; virtual bool LockMouse() Q_DECL_OVERRIDE; virtual void UnlockMouse() Q_DECL_OVERRIDE; - virtual void WasShown() Q_DECL_OVERRIDE; - virtual void WasHidden() Q_DECL_OVERRIDE; virtual void MovePluginWindows(const std::vector<content::WebPluginGeometry>&) Q_DECL_OVERRIDE; - virtual void Blur() Q_DECL_OVERRIDE; virtual void UpdateCursor(const content::WebCursor&) Q_DECL_OVERRIDE; virtual void SetIsLoading(bool) Q_DECL_OVERRIDE; virtual void TextInputTypeChanged(ui::TextInputType type, ui::TextInputMode mode, bool can_compose_inline, int flags) Q_DECL_OVERRIDE; @@ -140,7 +139,7 @@ public: 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 CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, content::CopyFromCompositingSurfaceCallback& callback, const SkColorType color_type) Q_DECL_OVERRIDE; + virtual void CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, content::ReadbackRequestCallback& 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 bool HasAcceleratedSurface(const gfx::Size&) Q_DECL_OVERRIDE; diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h index da595b91f..f4aa9b27d 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -96,6 +96,7 @@ public: virtual void move(const QPoint &) = 0; virtual void inputMethodStateChanged(bool editorVisible) = 0; virtual void setTooltip(const QString &) = 0; + virtual void setClearColor(const QColor &color) = 0; }; } // namespace QtWebEngineCore diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index e1333144a..72ca29be9 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -44,13 +44,16 @@ #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "net/base/net_errors.h" +#include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURLError.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "third_party/WebKit/public/web/WebSecurityPolicy.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" #include "content/public/common/web_preferences.h" #include "renderer/web_channel_ipc_transport.h" +#include "renderer/qt_render_frame_observer.h" #include "renderer/qt_render_view_observer.h" #include "renderer/user_script_controller.h" @@ -59,6 +62,7 @@ namespace QtWebEngineCore { static const char kHttpErrorDomain[] = "http"; +static const char kQrcSchemeQt[] = "qrc"; ContentRendererClientQt::ContentRendererClientQt() { @@ -75,6 +79,9 @@ void ContentRendererClientQt::RenderThreadStarted() m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave); renderThread->AddObserver(m_visitedLinkSlave.data()); renderThread->AddObserver(UserScriptController::instance()); + + // mark qrc as a secure scheme (avoids deprecation warnings) + blink::WebSecurityPolicy::registerURLSchemeAsSecure(blink::WebString::fromLatin1(kQrcSchemeQt)); } void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view) @@ -85,6 +92,11 @@ void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view UserScriptController::instance()->renderViewCreated(render_view); } +void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_frame) +{ + new QtWebEngineCore::QtRenderFrameObserver(render_frame); +} + bool ContentRendererClientQt::HasErrorPage(int httpStatusCode, std::string *errorDomain) { // Use an internal error page, if we have one for the status code. @@ -105,7 +117,7 @@ bool ContentRendererClientQt::ShouldSuppressErrorPage(content::RenderFrame *fram void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderView* renderView, blink::WebFrame *frame, const blink::WebURLRequest &failedRequest, const blink::WebURLError &error, std::string *errorHtml, base::string16 *errorDescription) { Q_UNUSED(frame) - const bool isPost = EqualsASCII(failedRequest.httpMethod(), "POST"); + const bool isPost = base::EqualsASCII(failedRequest.httpMethod(), "POST"); if (errorHtml) { // Use a local error page. diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h index dcb4e7fcb..fab88441f 100644 --- a/src/core/renderer/content_renderer_client_qt.h +++ b/src/core/renderer/content_renderer_client_qt.h @@ -53,7 +53,7 @@ public: ~ContentRendererClientQt(); virtual void RenderThreadStarted() Q_DECL_OVERRIDE; virtual void RenderViewCreated(content::RenderView *render_view) Q_DECL_OVERRIDE; - + virtual void RenderFrameCreated(content::RenderFrame* render_frame) Q_DECL_OVERRIDE; virtual bool ShouldSuppressErrorPage(content::RenderFrame *, const GURL &) Q_DECL_OVERRIDE; virtual bool HasErrorPage(int httpStatusCode, std::string *errorDomain) Q_DECL_OVERRIDE; virtual void GetNavigationErrorStrings(content::RenderView* renderView, blink::WebFrame* frame, const blink::WebURLRequest& failedRequest diff --git a/src/core/renderer/pepper/pepper_flash_browser_host_qt.cpp b/src/core/renderer/pepper/pepper_flash_browser_host_qt.cpp new file mode 100644 index 000000000..625e89ae4 --- /dev/null +++ b/src/core/renderer/pepper/pepper_flash_browser_host_qt.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "pepper_flash_browser_host_qt.h" + +#include "base/time/time.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_ppapi_host.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" +#include "ipc/ipc_message_macros.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/private/ppb_flash.h" +#include "ppapi/host/dispatch_host_message.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/resource_message_params.h" +#include "ppapi/shared_impl/time_conversion.h" +#include "qtwebenginecoreglobal_p.h" +#include "url/gurl.h" + +#if defined(OS_WIN) +#include <windows.h> +#elif defined(OS_MACOSX) +#include <CoreServices/CoreServices.h> +#endif + +using content::BrowserPpapiHost; +using content::BrowserThread; +using content::RenderProcessHost; + +namespace QtWebEngineCore { + + +PepperFlashBrowserHostQt::PepperFlashBrowserHostQt(BrowserPpapiHost* host, + PP_Instance instance, + PP_Resource resource) + : ResourceHost(host->GetPpapiHost(), instance, resource), + host_(host), + weak_factory_(this) +{ + int unused; + host->GetRenderFrameIDsForInstance(instance, &render_process_id_, &unused); +} + +PepperFlashBrowserHostQt::~PepperFlashBrowserHostQt() {} + +int32_t PepperFlashBrowserHostQt::OnResourceMessageReceived( + const IPC::Message& msg, + ppapi::host::HostMessageContext* context) +{ + PPAPI_BEGIN_MESSAGE_MAP(PepperFlashBrowserHostQt, msg) + PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Flash_UpdateActivity, + OnUpdateActivity) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Flash_GetLocalTimeZoneOffset, + OnGetLocalTimeZoneOffset) + PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Flash_GetLocalDataRestrictions, + OnGetLocalDataRestrictions) + PPAPI_END_MESSAGE_MAP() + return PP_ERROR_FAILED; +} + +int32_t PepperFlashBrowserHostQt::OnUpdateActivity(ppapi::host::HostMessageContext* host_context) +{ +#if defined(OS_WIN) + // Reading then writing back the same value to the screensaver timeout system + // setting resets the countdown which prevents the screensaver from turning + // on "for a while". As long as the plugin pings us with this message faster + // than the screensaver timeout, it won't go on. + int value = 0; + if (SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0, &value, 0)) + SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, value, NULL, 0); +#elif defined(OS_MACOSX) + UpdateSystemActivity(OverallAct); +#endif + return PP_OK; +} + +int32_t PepperFlashBrowserHostQt::OnGetLocalTimeZoneOffset( + ppapi::host::HostMessageContext* host_context, + const base::Time& t) +{ + // The reason for this processing being in the browser process is that on + // Linux, the localtime calls require filesystem access prohibited by the + // sandbox. + host_context->reply_msg = PpapiPluginMsg_Flash_GetLocalTimeZoneOffsetReply( + ppapi::PPGetLocalTimeZoneOffset(t)); + return PP_OK; +} + +int32_t PepperFlashBrowserHostQt::OnGetLocalDataRestrictions( + ppapi::host::HostMessageContext* context) +{ + QT_NOT_YET_IMPLEMENTED + return PP_OK; +} + +} // namespace QtWebEngineCore diff --git a/src/core/renderer/pepper/pepper_flash_browser_host_qt.h b/src/core/renderer/pepper/pepper_flash_browser_host_qt.h new file mode 100644 index 000000000..c5165a1b0 --- /dev/null +++ b/src/core/renderer/pepper/pepper_flash_browser_host_qt.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 PEPPER_FLASH_BROWSER_HOST_QT_H +#define PEPPER_FLASH_BROWSER_HOST_QT_H + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "ppapi/host/host_message_context.h" +#include "ppapi/host/resource_host.h" + +namespace base { +class Time; +} + +namespace content { +class BrowserPpapiHost; +class ResourceContext; +} + +class GURL; + +namespace QtWebEngineCore { + +class PepperFlashBrowserHostQt : public ppapi::host::ResourceHost { +public: + PepperFlashBrowserHostQt(content::BrowserPpapiHost* host, + PP_Instance instance, + PP_Resource resource); + ~PepperFlashBrowserHostQt() override; + + // ppapi::host::ResourceHost override. + int32_t OnResourceMessageReceived( + const IPC::Message& msg, + ppapi::host::HostMessageContext* context) override; + +private: + int32_t OnUpdateActivity(ppapi::host::HostMessageContext* host_context); + int32_t OnGetLocalTimeZoneOffset( + ppapi::host::HostMessageContext* host_context, + const base::Time& t); + int32_t OnGetLocalDataRestrictions(ppapi::host::HostMessageContext* context); + + void GetLocalDataRestrictions(ppapi::host::ReplyMessageContext reply_context, + const GURL& document_url, + const GURL& plugin_url); + + content::BrowserPpapiHost* host_; + int render_process_id_; + base::WeakPtrFactory<PepperFlashBrowserHostQt> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(PepperFlashBrowserHostQt); +}; + +} // namespace QtWebEngineCore + +#endif // PEPPER_FLASH_BROWSER_HOST_QT_H diff --git a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp new file mode 100644 index 000000000..8e68d1682 --- /dev/null +++ b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp @@ -0,0 +1,349 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "pepper_flash_renderer_host_qt.h" + +#include <map> +#include <vector> + +#include "base/lazy_instance.h" +#include "base/metrics/histogram.h" +#include "base/strings/string_util.h" +#include "content/public/renderer/pepper_plugin_instance.h" +#include "content/public/renderer/render_thread.h" +#include "content/public/renderer/renderer_ppapi_host.h" +#include "ipc/ipc_message_macros.h" +#include "net/http/http_util.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/trusted/ppb_browser_font_trusted.h" +#include "ppapi/host/dispatch_host_message.h" +#include "ppapi/proxy/host_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/resource_message_params.h" +#include "ppapi/proxy/serialized_structs.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_image_data_api.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkMatrix.h" +#include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/core/SkPoint.h" +#include "third_party/skia/include/core/SkTemplates.h" +#include "third_party/skia/include/core/SkTypeface.h" +#include "ui/gfx/geometry/rect.h" +#include "url/gurl.h" + +using ppapi::thunk::EnterResourceNoLock; +using ppapi::thunk::PPB_ImageData_API; + +namespace { + +// Some non-simple HTTP request headers that Flash may set. +// (Please see http://www.w3.org/TR/cors/#simple-header for the definition of +// simple headers.) +// +// The list and the enum defined below are used to collect data about request +// headers used in PPB_Flash.Navigate() calls, in order to understand the impact +// of rejecting PPB_Flash.Navigate() requests with non-simple headers. +// +// TODO(yzshen): We should be able to remove the histogram recording code once +// we get the answer. +const char* const kRejectedHttpRequestHeaders[] = { + "authorization", // + "cache-control", // + "content-encoding", // + "content-md5", // + "content-type", // If the media type is not one of those covered by the + // simple header definition. + "expires", // + "from", // + "if-match", // + "if-none-match", // + "if-range", // + "if-unmodified-since", // + "pragma", // + "referer" // +}; + +// Please note that new entries should be added right above +// FLASH_NAVIGATE_USAGE_ENUM_COUNT, and existing entries shouldn't be re-ordered +// or removed, since this ordering is used in a histogram. +enum FlashNavigateUsage { + // This section must be in the same order as kRejectedHttpRequestHeaders. + REJECT_AUTHORIZATION = 0, + REJECT_CACHE_CONTROL, + REJECT_CONTENT_ENCODING, + REJECT_CONTENT_MD5, + REJECT_CONTENT_TYPE, + REJECT_EXPIRES, + REJECT_FROM, + REJECT_IF_MATCH, + REJECT_IF_NONE_MATCH, + REJECT_IF_RANGE, + REJECT_IF_UNMODIFIED_SINCE, + REJECT_PRAGMA, + REJECT_REFERER, + + // The navigate request is rejected because of headers not listed above + // (e.g., custom headers). + REJECT_OTHER_HEADERS, + + // Total number of rejected navigate requests. + TOTAL_REJECTED_NAVIGATE_REQUESTS, + + // Total number of navigate requests. + TOTAL_NAVIGATE_REQUESTS, + FLASH_NAVIGATE_USAGE_ENUM_COUNT +}; + +static base::LazyInstance<std::map<std::string, FlashNavigateUsage> > +g_rejected_headers = LAZY_INSTANCE_INITIALIZER; + +bool IsSimpleHeader(const std::string& lower_case_header_name, + const std::string& header_value) +{ + if (lower_case_header_name == "accept" || + lower_case_header_name == "accept-language" || + lower_case_header_name == "content-language") + return true; + + if (lower_case_header_name == "content-type") { + std::string lower_case_mime_type; + std::string lower_case_charset; + bool had_charset = false; + net::HttpUtil::ParseContentType(header_value, + &lower_case_mime_type, + &lower_case_charset, + &had_charset, + NULL); + return lower_case_mime_type == "application/x-www-form-urlencoded" || + lower_case_mime_type == "multipart/form-data" || + lower_case_mime_type == "text/plain"; + } + + return false; +} + +void RecordFlashNavigateUsage(FlashNavigateUsage usage) +{ + DCHECK_NE(FLASH_NAVIGATE_USAGE_ENUM_COUNT, usage); + UMA_HISTOGRAM_ENUMERATION( + "Plugin.FlashNavigateUsage", + usage, + FLASH_NAVIGATE_USAGE_ENUM_COUNT); +} + +} // namespace + +namespace QtWebEngineCore { + +PepperFlashRendererHostQt::PepperFlashRendererHostQt( + content::RendererPpapiHost* host, + PP_Instance instance, + PP_Resource resource) + : ResourceHost(host->GetPpapiHost(), instance, resource), + host_(host), + weak_factory_(this) +{ +} + +PepperFlashRendererHostQt::~PepperFlashRendererHostQt() { + // This object may be destroyed in the middle of a sync message. If that is + // the case, make sure we respond to all the pending navigate calls. + std::vector<ppapi::host::ReplyMessageContext>::reverse_iterator it; + for (it = navigate_replies_.rbegin(); it != navigate_replies_.rend(); ++it) + SendReply(*it, IPC::Message()); +} + +int32_t PepperFlashRendererHostQt::OnResourceMessageReceived( + const IPC::Message& msg, + ppapi::host::HostMessageContext* context) +{ + PPAPI_BEGIN_MESSAGE_MAP(PepperFlashRendererHostQt, msg) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Flash_GetProxyForURL, + OnGetProxyForURL) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Flash_SetInstanceAlwaysOnTop, + OnSetInstanceAlwaysOnTop) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Flash_DrawGlyphs, + OnDrawGlyphs) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Flash_Navigate, OnNavigate) + PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Flash_IsRectTopmost, + OnIsRectTopmost) + PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Flash_InvokePrinting, + OnInvokePrinting) + PPAPI_END_MESSAGE_MAP() + return PP_ERROR_FAILED; +} + +int32_t PepperFlashRendererHostQt::OnGetProxyForURL( + ppapi::host::HostMessageContext* host_context, + const std::string& url) +{ + GURL gurl(url); + if (!gurl.is_valid()) + return PP_ERROR_FAILED; + std::string proxy; + bool result = content::RenderThread::Get()->ResolveProxy(gurl, &proxy); + if (!result) + return PP_ERROR_FAILED; + host_context->reply_msg = PpapiPluginMsg_Flash_GetProxyForURLReply(proxy); + return PP_OK; +} + +int32_t PepperFlashRendererHostQt::OnSetInstanceAlwaysOnTop( + ppapi::host::HostMessageContext* host_context, + bool on_top) +{ + content::PepperPluginInstance* plugin_instance = + host_->GetPluginInstance(pp_instance()); + if (plugin_instance) + plugin_instance->SetAlwaysOnTop(on_top); + return PP_OK; +} + +int32_t PepperFlashRendererHostQt::OnDrawGlyphs( + ppapi::host::HostMessageContext* host_context, + ppapi::proxy::PPBFlash_DrawGlyphs_Params params) +{ + if (params.glyph_indices.size() != params.glyph_advances.size() || + params.glyph_indices.empty()) + return PP_ERROR_FAILED; + + return PP_OK; +} + +// CAUTION: This code is subtle because Navigate is a sync call which may +// cause re-entrancy or cause the instance to be destroyed. If the instance +// is destroyed we need to ensure that we respond to all outstanding sync +// messages so that the plugin process does not remain blocked. +int32_t PepperFlashRendererHostQt::OnNavigate( + ppapi::host::HostMessageContext* host_context, + const ppapi::URLRequestInfoData& data, + const std::string& target, + bool from_user_action) +{ + // If our PepperPluginInstance is already destroyed, just return a failure. + content::PepperPluginInstance* plugin_instance = + host_->GetPluginInstance(pp_instance()); + if (!plugin_instance) + return PP_ERROR_FAILED; + + std::map<std::string, FlashNavigateUsage>& rejected_headers = + g_rejected_headers.Get(); + if (rejected_headers.empty()) { + for (size_t i = 0; i < arraysize(kRejectedHttpRequestHeaders); ++i) + rejected_headers[kRejectedHttpRequestHeaders[i]] = + static_cast<FlashNavigateUsage>(i); + } + + net::HttpUtil::HeadersIterator header_iter( + data.headers.begin(), data.headers.end(), "\n\r"); + bool rejected = false; + while (header_iter.GetNext()) { + std::string lower_case_header_name = + base::StringToLowerASCII(header_iter.name()); + if (!IsSimpleHeader(lower_case_header_name, header_iter.values())) { + rejected = true; + + std::map<std::string, FlashNavigateUsage>::const_iterator iter = + rejected_headers.find(lower_case_header_name); + FlashNavigateUsage usage = + iter != rejected_headers.end() ? iter->second : REJECT_OTHER_HEADERS; + RecordFlashNavigateUsage(usage); + } + } + + RecordFlashNavigateUsage(TOTAL_NAVIGATE_REQUESTS); + if (rejected) { + RecordFlashNavigateUsage(TOTAL_REJECTED_NAVIGATE_REQUESTS); + return PP_ERROR_NOACCESS; + } + + // Navigate may call into Javascript (e.g. with a "javascript:" URL), + // or do things like navigate away from the page, either one of which will + // need to re-enter into the plugin. It is safe, because it is essentially + // equivalent to NPN_GetURL, where Flash would expect re-entrancy. + ppapi::proxy::HostDispatcher* host_dispatcher = + ppapi::proxy::HostDispatcher::GetForInstance(pp_instance()); + host_dispatcher->set_allow_plugin_reentrancy(); + + // Grab a weak pointer to ourselves on the stack so we can check if we are + // still alive. + base::WeakPtr<PepperFlashRendererHostQt> weak_ptr = weak_factory_.GetWeakPtr(); + // Keep track of reply contexts in case we are destroyed during a Navigate + // call. Even if we are destroyed, we still need to send these replies to + // unblock the plugin process. + navigate_replies_.push_back(host_context->MakeReplyMessageContext()); + plugin_instance->Navigate(data, target.c_str(), from_user_action); + // This object might have been destroyed by this point. If it is destroyed + // the reply will be sent in the destructor. Otherwise send the reply here. + if (weak_ptr.get()) { + SendReply(navigate_replies_.back(), IPC::Message()); + navigate_replies_.pop_back(); + } + + // Return PP_OK_COMPLETIONPENDING so that no reply is automatically sent. + return PP_OK_COMPLETIONPENDING; +} + +int32_t PepperFlashRendererHostQt::OnIsRectTopmost( + ppapi::host::HostMessageContext* host_context, + const PP_Rect& rect) +{ + content::PepperPluginInstance* plugin_instance = + host_->GetPluginInstance(pp_instance()); + if (plugin_instance && + plugin_instance->IsRectTopmost( + gfx::Rect( + rect.point.x, + rect.point.y, + rect.size.width, + rect.size.height))) + return PP_OK; + return PP_ERROR_FAILED; +} + +int32_t PepperFlashRendererHostQt::OnInvokePrinting( + ppapi::host::HostMessageContext* host_context) +{ + return PP_ERROR_FAILED; +} + +} //QtWebEngineCore diff --git a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.h b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.h new file mode 100644 index 000000000..4a731fad4 --- /dev/null +++ b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 PEPPER_FLASH_RENDERER_HOST_QT_H +#define PEPPER_FLASH_RENDERER_HOST_QT_H + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/weak_ptr.h" +#include "ppapi/host/host_message_context.h" +#include "ppapi/host/resource_host.h" + +struct PP_Rect; + +namespace ppapi { +struct URLRequestInfoData; +} + +namespace ppapi { +namespace proxy { +struct PPBFlash_DrawGlyphs_Params; +} +} + +namespace content { +class RendererPpapiHost; +} + +namespace QtWebEngineCore { + +class PepperFlashRendererHostQt : public ppapi::host::ResourceHost { +public: + PepperFlashRendererHostQt(content::RendererPpapiHost* host, + PP_Instance instance, + PP_Resource resource); + ~PepperFlashRendererHostQt() override; + + // ppapi::host::ResourceHost override. + int32_t OnResourceMessageReceived( + const IPC::Message& msg, + ppapi::host::HostMessageContext* context) override; + +private: + int32_t OnGetProxyForURL(ppapi::host::HostMessageContext* host_context, + const std::string& url); + int32_t OnSetInstanceAlwaysOnTop( + ppapi::host::HostMessageContext* host_context, + bool on_top); + int32_t OnDrawGlyphs(ppapi::host::HostMessageContext* host_context, + ppapi::proxy::PPBFlash_DrawGlyphs_Params params); + int32_t OnNavigate(ppapi::host::HostMessageContext* host_context, + const ppapi::URLRequestInfoData& data, + const std::string& target, + bool from_user_action); + int32_t OnIsRectTopmost(ppapi::host::HostMessageContext* host_context, + const PP_Rect& rect); + int32_t OnInvokePrinting(ppapi::host::HostMessageContext* host_context); + + // A stack of ReplyMessageContexts to track Navigate() calls which have not + // yet been replied to. + std::vector<ppapi::host::ReplyMessageContext> navigate_replies_; + + content::RendererPpapiHost* host_; + base::WeakPtrFactory<PepperFlashRendererHostQt> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(PepperFlashRendererHostQt); +}; + +} //QtWebEngineCore +#endif // PEPPER_FLASH_RENDERER_HOST_QT_H diff --git a/src/core/renderer/pepper/pepper_host_factory_qt.cpp b/src/core/renderer/pepper/pepper_host_factory_qt.cpp new file mode 100644 index 000000000..61eeac9a0 --- /dev/null +++ b/src/core/renderer/pepper/pepper_host_factory_qt.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "pepper_host_factory_qt.h" + +#include "build/build_config.h" +#include "content/public/browser/browser_ppapi_host.h" +#include "ppapi/host/message_filter_host.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/host/resource_host.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/ppapi_permissions.h" +#include "pepper_flash_browser_host_qt.h" + +using ppapi::host::MessageFilterHost; +using ppapi::host::ResourceHost; +using ppapi::host::ResourceMessageFilter; + +namespace QtWebEngineCore { + +PepperHostFactoryQt::PepperHostFactoryQt(content::BrowserPpapiHost* host) + : host_(host) +{ +} + +PepperHostFactoryQt::~PepperHostFactoryQt() {} + +scoped_ptr<ppapi::host::ResourceHost> PepperHostFactoryQt::CreateResourceHost(ppapi::host::PpapiHost* host, + PP_Resource resource, + PP_Instance instance, + const IPC::Message& message) +{ + DCHECK(host == host_->GetPpapiHost()); + + + if (!host_->IsValidInstance(instance)) + return scoped_ptr<ppapi::host::ResourceHost>(); + + if (host_->GetPpapiHost()->permissions().HasPermission(ppapi::PERMISSION_FLASH) + && message.type() == PpapiHostMsg_Flash_Create::ID) + return scoped_ptr<ppapi::host::ResourceHost>( + new PepperFlashBrowserHostQt(host_, + instance, + resource)); + + return scoped_ptr<ppapi::host::ResourceHost>(); +} + +} // namespace QtWebEngineCore diff --git a/src/core/renderer/pepper/pepper_host_factory_qt.h b/src/core/renderer/pepper/pepper_host_factory_qt.h new file mode 100644 index 000000000..22bf87b1b --- /dev/null +++ b/src/core/renderer/pepper/pepper_host_factory_qt.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 PEPPER_HOST_FACTORY_QT_H +#define PEPPER_HOST_FACTORY_QT_H + +#include "base/compiler_specific.h" +#include "ppapi/host/host_factory.h" +#include "ppapi/host/resource_host.h" +#include "ppapi/host/ppapi_host.h" + +namespace content { +class BrowserPpapiHost; +} // namespace content + +namespace QtWebEngineCore { + +class PepperHostFactoryQt final : public ppapi::host::HostFactory { +public: + // Non-owning pointer to the filter must outlive this class. + explicit PepperHostFactoryQt(content::BrowserPpapiHost* host); + ~PepperHostFactoryQt() override; + + virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost( + ppapi::host::PpapiHost* host, + PP_Resource resource, + PP_Instance instance, + const IPC::Message& message) override; +private: + // Non-owning pointer. + content::BrowserPpapiHost* host_; + + DISALLOW_COPY_AND_ASSIGN(PepperHostFactoryQt); +}; +} // namespace QtWebEngineCore + +#endif // PEPPER_HOST_FACTORY_QT_H diff --git a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp new file mode 100644 index 000000000..51416d698 --- /dev/null +++ b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "pepper_renderer_host_factory_qt.h" +#include "pepper_flash_renderer_host_qt.h" +#include "content/public/renderer/renderer_ppapi_host.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/host/resource_host.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppapi_message_utils.h" +#include "ppapi/shared_impl/ppapi_permissions.h" + + +namespace QtWebEngineCore { + +PepperRendererHostFactoryQt::PepperRendererHostFactoryQt(content::RendererPpapiHost* host) + : host_(host) +{ +} + +PepperRendererHostFactoryQt::~PepperRendererHostFactoryQt() +{ +} + +scoped_ptr<ppapi::host::ResourceHost> PepperRendererHostFactoryQt::CreateResourceHost( + ppapi::host::PpapiHost* host, + PP_Resource resource, + PP_Instance instance, + const IPC::Message& message) +{ + DCHECK_EQ(host_->GetPpapiHost(), host); + + if (!host_->IsValidInstance(instance)) + return scoped_ptr<ppapi::host::ResourceHost>(); + + if (host_->GetPpapiHost()->permissions().HasPermission(ppapi::PERMISSION_FLASH) + && message.type() == PpapiHostMsg_Flash_Create::ID) + return scoped_ptr<ppapi::host::ResourceHost>( + new PepperFlashRendererHostQt(host_, + instance, + resource)); + + return scoped_ptr<ppapi::host::ResourceHost>(); +} + +} // QtWebEngineCore diff --git a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.h b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.h new file mode 100644 index 000000000..8631c1e03 --- /dev/null +++ b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 PEPPER_RENDERER_HOST_FACTORY_QT_H +#define PEPPER_RENDERER_HOST_FACTORY_QT_H + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ppapi/host/host_factory.h" +#include "content/public/renderer/render_frame_observer.h" + + +namespace content { +class RenderFrame; +} + +namespace QtWebEngineCore { + +class PepperRendererHostFactoryQt : public ppapi::host::HostFactory { +public: + explicit PepperRendererHostFactoryQt(content::RendererPpapiHost* host); + ~PepperRendererHostFactoryQt(); + + // HostFactory. + scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost( + ppapi::host::PpapiHost* host, + PP_Resource resource, + PP_Instance instance, + const IPC::Message& message) override; + +private: + // Not owned by this object. + content::RendererPpapiHost* host_; + + DISALLOW_COPY_AND_ASSIGN(PepperRendererHostFactoryQt); +}; + +} // namespace QtWebEngineCore + +#endif // PEPPER_RENDERER_HOST_FACTORY_QT_H diff --git a/src/core/renderer/qt_render_frame_observer.cpp b/src/core/renderer/qt_render_frame_observer.cpp new file mode 100644 index 000000000..5f06d1e4e --- /dev/null +++ b/src/core/renderer/qt_render_frame_observer.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 "qt_render_frame_observer.h" + +#include "content/public/renderer/renderer_ppapi_host.h" +#include "ppapi/host/ppapi_host.h" + +#include "renderer/pepper/pepper_renderer_host_factory_qt.h" +#include "renderer/pepper/pepper_flash_renderer_host_qt.h" + +namespace QtWebEngineCore { + +QtRenderFrameObserver::QtRenderFrameObserver(content::RenderFrame* render_frame) + : RenderFrameObserver(render_frame) +{ +} + +QtRenderFrameObserver::~QtRenderFrameObserver() +{ +} + +#if defined(ENABLE_PLUGINS) +void QtRenderFrameObserver::DidCreatePepperPlugin(content::RendererPpapiHost* host) +{ + host->GetPpapiHost()->AddHostFactoryFilter( + scoped_ptr<ppapi::host::HostFactory>( + new PepperRendererHostFactoryQt(host))); +} +#endif + +} // namespace QtWebEngineCore diff --git a/src/core/custom_url_scheme_handler.h b/src/core/renderer/qt_render_frame_observer.h index 745f0eb4c..42f2b7464 100644 --- a/src/core/custom_url_scheme_handler.h +++ b/src/core/renderer/qt_render_frame_observer.h @@ -34,38 +34,33 @@ ** ****************************************************************************/ -#ifndef CUSTOM_URL_SCHEME_HANDLER_H_ -#define CUSTOM_URL_SCHEME_HANDLER_H_ +#ifndef QT_RENDER_FRAME_OBSERVER_H +#define QT_RENDER_FRAME_OBSERVER_H -#include "qtwebenginecoreglobal.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "content/public/renderer/render_frame_observer.h" -#include <QtCore/QByteArray> -#include <QtCore/QScopedPointer> -QT_FORWARD_DECLARE_CLASS(QIODevice) +namespace content { +class RenderFrame; +} namespace QtWebEngineCore { -class BrowserContextAdapter; -class CustomProtocolHandler; -class URLRequestCustomJobDelegate; - -class QWEBENGINE_EXPORT CustomUrlSchemeHandler { +class QtRenderFrameObserver : public content::RenderFrameObserver { public: - explicit CustomUrlSchemeHandler(const QByteArray &); - ~CustomUrlSchemeHandler(); - - QByteArray scheme() const; - void setScheme(const QByteArray &); - CustomProtocolHandler *createProtocolHandler(); + explicit QtRenderFrameObserver(content::RenderFrame* render_frame); + ~QtRenderFrameObserver(); - virtual bool handleJob(URLRequestCustomJobDelegate*) = 0; +#if defined(ENABLE_PLUGINS) + void DidCreatePepperPlugin(content::RendererPpapiHost* host) override; +#endif private: - QByteArray m_scheme; + DISALLOW_COPY_AND_ASSIGN(QtRenderFrameObserver); }; +} // namespace QtWebEngineCore -} // namespace - -#endif // CUSTOM_URL_SCHEME_HANDLER_H_ +#endif // QT_RENDER_FRAME_OBSERVER_H diff --git a/src/core/renderer/qt_render_view_observer.cpp b/src/core/renderer/qt_render_view_observer.cpp index 83534dadd..ba91e54ae 100644 --- a/src/core/renderer/qt_render_view_observer.cpp +++ b/src/core/renderer/qt_render_view_observer.cpp @@ -65,6 +65,11 @@ void QtRenderViewObserver::onFetchDocumentInnerText(quint64 requestId) render_view()->GetWebView()->mainFrame()->contentAsText(std::numeric_limits<std::size_t>::max()))); } +void QtRenderViewObserver::onSetBackgroundColor(quint32 color) +{ + render_view()->GetWebView()->setBaseBackgroundColor(color); +} + void QtRenderViewObserver::OnFirstVisuallyNonEmptyLayout() { Send(new QtRenderViewObserverHost_DidFirstVisuallyNonEmptyLayout(routing_id())); @@ -76,6 +81,7 @@ bool QtRenderViewObserver::OnMessageReceived(const IPC::Message& message) IPC_BEGIN_MESSAGE_MAP(QtRenderViewObserver, message) IPC_MESSAGE_HANDLER(QtRenderViewObserver_FetchDocumentMarkup, onFetchDocumentMarkup) IPC_MESSAGE_HANDLER(QtRenderViewObserver_FetchDocumentInnerText, onFetchDocumentInnerText) + IPC_MESSAGE_HANDLER(QtRenderViewObserver_SetBackgroundColor, onSetBackgroundColor) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; diff --git a/src/core/renderer/qt_render_view_observer.h b/src/core/renderer/qt_render_view_observer.h index cb77cd0c9..3f7829a92 100644 --- a/src/core/renderer/qt_render_view_observer.h +++ b/src/core/renderer/qt_render_view_observer.h @@ -47,6 +47,7 @@ public: private: void onFetchDocumentMarkup(quint64 requestId); void onFetchDocumentInnerText(quint64 requestId); + void onSetBackgroundColor(quint32 color); void OnFirstVisuallyNonEmptyLayout() Q_DECL_OVERRIDE; diff --git a/src/core/resource_dispatcher_host_delegate_qt.cpp b/src/core/resource_dispatcher_host_delegate_qt.cpp index faed58954..0213daa3a 100644 --- a/src/core/resource_dispatcher_host_delegate_qt.cpp +++ b/src/core/resource_dispatcher_host_delegate_qt.cpp @@ -46,22 +46,20 @@ #include "content/public/browser/resource_request_info.h" #include "net/url_request/url_request.h" +#include "authentication_dialog_controller.h" +#include "authentication_dialog_controller_p.h" #include "type_conversion.h" #include "web_contents_view_qt.h" namespace QtWebEngineCore { ResourceDispatcherHostLoginDelegateQt::ResourceDispatcherHostLoginDelegateQt(net::AuthChallengeInfo *authInfo, net::URLRequest *request) - : m_request(request) + : m_authInfo(authInfo) + , m_request(request) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); content::ResourceRequestInfo::GetRenderFrameForRequest(request, &m_renderProcessId, &m_renderFrameId); - m_url = toQt(request->url()); - m_realm = QString::fromStdString(authInfo->realm); - m_isProxy = authInfo->is_proxy; - m_host = QString::fromStdString(authInfo->challenger.ToString()); - content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::Bind(&ResourceDispatcherHostLoginDelegateQt::triggerDialog, this)); @@ -69,33 +67,49 @@ ResourceDispatcherHostLoginDelegateQt::ResourceDispatcherHostLoginDelegateQt(net ResourceDispatcherHostLoginDelegateQt::~ResourceDispatcherHostLoginDelegateQt() { + Q_ASSERT(m_dialogController.isNull()); // We must have called ClearLoginDelegateForRequest if we didn't receive an OnRequestCancelled. Q_ASSERT(!m_request); } void ResourceDispatcherHostLoginDelegateQt::OnRequestCancelled() { - m_request = 0; + destroy(); +} + +QUrl ResourceDispatcherHostLoginDelegateQt::url() const +{ + return toQt(m_request->url()); +} + +QString ResourceDispatcherHostLoginDelegateQt::realm() const +{ + return QString::fromStdString(m_authInfo->realm); +} + +QString ResourceDispatcherHostLoginDelegateQt::host() const +{ + return QString::fromStdString(m_authInfo->challenger.ToString()); +} + +bool ResourceDispatcherHostLoginDelegateQt::isProxy() const +{ + return m_authInfo->is_proxy; } void ResourceDispatcherHostLoginDelegateQt::triggerDialog() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - content::RenderViewHost* renderViewHost = content::RenderFrameHost::FromID(m_renderProcessId, m_renderFrameId)->GetRenderViewHost(); + content::RenderFrameHost *renderFrameHost = content::RenderFrameHost::FromID(m_renderProcessId, m_renderFrameId); + if (!renderFrameHost) + return; + content::RenderViewHost *renderViewHost = renderFrameHost->GetRenderViewHost(); content::WebContentsImpl *webContents = static_cast<content::WebContentsImpl *>(content::WebContents::FromRenderViewHost(renderViewHost)); WebContentsAdapterClient *client = WebContentsViewQt::from(webContents->GetView())->client(); - // The widgets API will ask for credentials synchronouly, keep it simple for now. - // We'll have to figure out a mechanism to keep a ref to the ResourceDispatcherHostLoginDelegateQt - // to avoid crashing in the OnRequestCancelled case if we want to allow the credentials to - // come back asynchronously in the QtQuick API. - QString user, password; - client->authenticationRequired(m_url , m_realm , m_isProxy , m_host, &user, &password); - - bool success = !user.isEmpty() || !password.isEmpty(); - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::Bind(&ResourceDispatcherHostLoginDelegateQt::sendAuthToRequester, this, success, user, password)); + AuthenticationDialogControllerPrivate *dialogControllerData = new AuthenticationDialogControllerPrivate(this); + m_dialogController.reset(new AuthenticationDialogController(dialogControllerData)); + client->authenticationRequired(m_dialogController); } void ResourceDispatcherHostLoginDelegateQt::sendAuthToRequester(bool success, const QString &user, const QString &password) @@ -110,9 +124,44 @@ void ResourceDispatcherHostLoginDelegateQt::sendAuthToRequester(bool success, co m_request->CancelAuth(); content::ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(m_request); + destroy(); +} + +void ResourceDispatcherHostLoginDelegateQt::destroy() +{ + m_dialogController.reset(); m_request = 0; } +static void LaunchURL(const GURL& url, int render_process_id, int render_view_id, + ui::PageTransition page_transition, bool is_main_frame) +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + content::RenderViewHost *render_view_host = content::RenderViewHost::FromID(render_process_id, render_view_id); + if (!render_view_host) + return; + content::WebContents* webContents = content::WebContents::FromRenderViewHost(render_view_host); + if (!webContents) + return; + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); + contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame); +} + +bool ResourceDispatcherHostDelegateQt::HandleExternalProtocol(const GURL& url, int child_id, int route_id, + bool is_main_frame, ui::PageTransition page_transition, bool has_user_gesture) +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + // We don't want to launch external applications unless it is based on a user action + if (!has_user_gesture) + return false; + + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::Bind(&LaunchURL, url, child_id, route_id, page_transition, is_main_frame)); + return true; +} + content::ResourceDispatcherHostLoginDelegate *ResourceDispatcherHostDelegateQt::CreateLoginDelegate(net::AuthChallengeInfo *authInfo, net::URLRequest *request) { // ResourceDispatcherHostLoginDelegateQt is ref-counted and will be released after we called ClearLoginDelegateForRequest. diff --git a/src/core/resource_dispatcher_host_delegate_qt.h b/src/core/resource_dispatcher_host_delegate_qt.h index 2cba210d3..57eaa3bc5 100644 --- a/src/core/resource_dispatcher_host_delegate_qt.h +++ b/src/core/resource_dispatcher_host_delegate_qt.h @@ -44,6 +44,8 @@ namespace QtWebEngineCore { +class AuthenticationDialogController; + class ResourceDispatcherHostLoginDelegateQt : public content::ResourceDispatcherHostLoginDelegate { public: ResourceDispatcherHostLoginDelegateQt(net::AuthChallengeInfo *authInfo, net::URLRequest *request); @@ -52,9 +54,16 @@ public: // ResourceDispatcherHostLoginDelegate implementation virtual void OnRequestCancelled(); + QUrl url() const; + QString realm() const; + QString host() const; + bool isProxy() const; + + void sendAuthToRequester(bool success, const QString &user, const QString &password); + private: void triggerDialog(); - void sendAuthToRequester(bool success, const QString &user, const QString &password); + void destroy(); QUrl m_url; QString m_realm; @@ -64,13 +73,22 @@ private: int m_renderProcessId; int m_renderFrameId; + net::AuthChallengeInfo *m_authInfo; + // The request that wants login data. // Must only be accessed on the IO thread. net::URLRequest *m_request; + + // This member is used to keep authentication dialog controller alive until + // authorization is sent or cancelled. + QSharedPointer<AuthenticationDialogController> m_dialogController; }; class ResourceDispatcherHostDelegateQt : public content::ResourceDispatcherHostDelegate { public: + virtual bool HandleExternalProtocol(const GURL& url, int child_id, int route_id, + bool is_main_frame, ui::PageTransition page_transition, bool has_user_gesture) Q_DECL_OVERRIDE; + virtual content::ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(net::AuthChallengeInfo *authInfo, net::URLRequest *request) Q_DECL_OVERRIDE; }; diff --git a/src/core/resources/resources.gyp b/src/core/resources/resources.gyp index 4d653df12..6293cdf3b 100644 --- a/src/core/resources/resources.gyp +++ b/src/core/resources/resources.gyp @@ -15,7 +15,7 @@ }, 'dependencies': [ '<(chromium_src_dir)/content/app/strings/content_strings.gyp:content_strings', - '<(chromium_src_dir)/webkit/blink_resources.gyp:blink_resources', + '<(chromium_src_dir)/blink/public/blink_resources.gyp:blink_resources', '<(chromium_src_dir)/content/browser/devtools/devtools_resources.gyp:devtools_resources', '../chrome_qt.gyp:chrome_resources', ], @@ -29,7 +29,7 @@ 'variables': { 'pak_inputs': [ '<(SHARED_INTERMEDIATE_DIR)/net/net_resources.pak', - '<(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak', + '<(SHARED_INTERMEDIATE_DIR)/blink/devtools_resources.pak', '<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak', '<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_resources.pak', '<(SHARED_INTERMEDIATE_DIR)/ui/resources/webui_resources.pak', diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index 66fcd4dd0..9e5461888 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -41,15 +41,17 @@ #include <QDateTime> #include <QDir> #include <QMatrix4x4> +#include <QNetworkCookie> #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 "net/cookies/canonical_cookie.h" #include "third_party/skia/include/utils/SkMatrix44.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/rect.h" +#include "ui/gfx/geometry/rect.h" #include "url/gurl.h" namespace QtWebEngineCore { @@ -92,6 +94,11 @@ inline QPoint toQt(const gfx::Point &point) return QPoint(point.x(), point.y()); } +inline gfx::Point toGfx(const QPoint& point) +{ + return gfx::Point(point.x(), point.y()); +} + inline QRect toQt(const gfx::Rect &rect) { return QRect(rect.x(), rect.y(), rect.width(), rect.height()); @@ -122,6 +129,11 @@ inline QColor toQt(const SkColor &c) return QColor(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c), SkColorGetA(c)); } +inline SkColor toSk(const QColor &c) +{ + return c.rgba(); +} + inline QMatrix4x4 toQt(const SkMatrix44 &m) { QMatrix4x4 qtMatrix( @@ -142,6 +154,18 @@ inline base::Time toTime(const QDateTime &dateTime) { return base::Time::FromInternalValue(dateTime.toMSecsSinceEpoch()); } +inline QNetworkCookie toQt(const net::CanonicalCookie & cookie) +{ + QNetworkCookie qCookie = QNetworkCookie(QByteArray::fromStdString(cookie.Name()), QByteArray::fromStdString(cookie.Value())); + qCookie.setDomain(toQt(cookie.Domain())); + if (!cookie.ExpiryDate().is_null()) + qCookie.setExpirationDate(toQt(cookie.ExpiryDate())); + qCookie.setHttpOnly(cookie.IsHttpOnly()); + qCookie.setPath(toQt(cookie.Path())); + qCookie.setSecure(cookie.IsSecure()); + return qCookie; +} + inline base::FilePath::StringType toFilePathString(const QString &str) { #if defined(OS_WIN) diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index 10923e4cb..26e1dbea8 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -41,7 +41,6 @@ #include "base/threading/worker_pool.h" #include "base/threading/sequenced_worker_pool.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/cookie_crypto_delegate.h" #include "content/public/browser/cookie_store_factory.h" #include "content/public/common/content_switches.h" #include "net/base/cache_type.h" @@ -67,12 +66,16 @@ #include "net/url_request/ftp_protocol_handler.h" #include "net/ftp/ftp_network_layer.h" +#include "api/qwebengineurlschemehandler.h" #include "browser_context_adapter.h" #include "custom_protocol_handler.h" -#include "custom_url_scheme_handler.h" +#include "cookie_monster_delegate_qt.h" #include "content_client_qt.h" #include "network_delegate_qt.h" +#include "proxy_config_service_qt.h" #include "qrc_protocol_handler_qt.h" +#include "qwebenginecookiestoreclient.h" +#include "qwebenginecookiestoreclient_p.h" #include "type_conversion.h" namespace QtWebEngineCore { @@ -84,6 +87,7 @@ using content::BrowserThread; URLRequestContextGetterQt::URLRequestContextGetterQt(BrowserContextAdapter *browserContext, content::ProtocolHandlerMap *protocolHandlers) : m_ignoreCertificateErrors(false) , m_browserContext(browserContext) + , m_cookieDelegate(new CookieMonsterDelegateQt()) { std::swap(m_protocolHandlers, *protocolHandlers); @@ -100,7 +104,7 @@ net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() if (!m_urlRequestContext) { m_urlRequestContext.reset(new net::URLRequestContext()); - m_networkDelegate.reset(new NetworkDelegateQt); + m_networkDelegate.reset(new NetworkDelegateQt(this)); m_urlRequestContext->set_network_delegate(m_networkDelegate.get()); generateStorage(); @@ -117,10 +121,10 @@ void URLRequestContextGetterQt::updateStorageSettings() // 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 = net::ProxyService::CreateSystemProxyConfigService( + m_proxyConfigService = new ProxyConfigServiceQt(net::ProxyService::CreateSystemProxyConfigService( content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), content::BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) - ); + )); if (m_storage) content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateStorage, this)); } @@ -150,34 +154,27 @@ void URLRequestContextGetterQt::generateStorage() generateCookieStore(); generateUserAgent(); - m_storage->set_channel_id_service(new net::ChannelIDService( + m_storage->set_channel_id_service(scoped_ptr<net::ChannelIDService>(new net::ChannelIDService( new net::DefaultChannelIDStore(NULL), - base::WorkerPool::GetTaskRunner(true))); + base::WorkerPool::GetTaskRunner(true)))); m_storage->set_cert_verifier(net::CertVerifier::CreateDefault()); scoped_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); // The System Proxy Resolver has issues on Windows with unconfigured network cards, - // which is why we want to use the v8 one. However, V8ProxyResolver doesn't work reliably with - // --single-process (See also the warnings in net/proxy/proxy_resolver_v8.h). - base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kSingleProcess)) { - m_storage->set_proxy_service( - net::ProxyService::CreateUsingSystemProxyResolver(proxyConfigService, 0, NULL)); - } else { - if (!m_dhcpProxyScriptFetcherFactory) - m_dhcpProxyScriptFetcherFactory.reset(new net::DhcpProxyScriptFetcherFactory); - - net::ProxyResolverV8::EnsureIsolateCreated(); - m_storage->set_proxy_service(net::CreateProxyServiceUsingV8ProxyResolver( - proxyConfigService, - new net::ProxyScriptFetcherImpl(m_urlRequestContext.get()), - m_dhcpProxyScriptFetcherFactory->Create(m_urlRequestContext.get()), - host_resolver.get(), - NULL /* NetLog */, - m_networkDelegate.get())); - } + // which is why we want to use the v8 one + if (!m_dhcpProxyScriptFetcherFactory) + m_dhcpProxyScriptFetcherFactory.reset(new net::DhcpProxyScriptFetcherFactory); + + m_storage->set_proxy_service(net::CreateProxyServiceUsingV8ProxyResolver( + proxyConfigService, + new net::ProxyScriptFetcherImpl(m_urlRequestContext.get()), + m_dhcpProxyScriptFetcherFactory->Create(m_urlRequestContext.get()), + host_resolver.get(), + NULL /* NetLog */, + m_networkDelegate.get())); + m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); m_storage->set_transport_security_state(new net::TransportSecurityState()); @@ -206,6 +203,8 @@ void URLRequestContextGetterQt::generateCookieStore() // 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_cookieDelegate->setCookieMonster(0); + m_cookieDelegate->setClient(m_browserContext->cookieStoreClient()); net::CookieStore* cookieStore = 0; switch (m_browserContext->persistentCookiesPolicy()) { @@ -214,7 +213,8 @@ void URLRequestContextGetterQt::generateCookieStore() content::CreateCookieStore(content::CookieStoreConfig( base::FilePath(), content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES, - NULL, NULL) + NULL, + m_cookieDelegate.get()) ); break; case BrowserContextAdapter::AllowPersistentCookies: @@ -222,7 +222,8 @@ void URLRequestContextGetterQt::generateCookieStore() content::CreateCookieStore(content::CookieStoreConfig( toFilePath(m_browserContext->cookiesPath()), content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, - NULL, NULL) + NULL, + m_cookieDelegate.get()) ); break; case BrowserContextAdapter::ForcePersistentCookies: @@ -230,11 +231,16 @@ void URLRequestContextGetterQt::generateCookieStore() content::CreateCookieStore(content::CookieStoreConfig( toFilePath(m_browserContext->cookiesPath()), content::CookieStoreConfig::RESTORED_SESSION_COOKIES, - NULL, NULL) + NULL, + m_cookieDelegate.get()) ); break; } m_storage->set_cookie_store(cookieStore); + + net::CookieMonster * const cookieMonster = cookieStore->GetCookieMonster(); + cookieMonster->SetCookieableSchemes(kCookieableSchemes, arraysize(kCookieableSchemes)); + m_cookieDelegate->setCookieMonster(cookieMonster); } void URLRequestContextGetterQt::updateUserAgent() @@ -243,13 +249,32 @@ void URLRequestContextGetterQt::updateUserAgent() content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateUserAgent, this)); } +class HttpUserAgentSettingsQt : public net::HttpUserAgentSettings +{ + const BrowserContextAdapter *m_browserContext; +public: + HttpUserAgentSettingsQt(const BrowserContextAdapter *ctx) + : m_browserContext(ctx) + { + } + + std::string GetAcceptLanguage() const Q_DECL_OVERRIDE + { + return m_browserContext->httpAcceptLanguage().toStdString(); + } + + std::string GetUserAgent() const Q_DECL_OVERRIDE + { + return m_browserContext->httpUserAgent().toStdString(); + } +}; + void URLRequestContextGetterQt::generateUserAgent() { Q_ASSERT(m_urlRequestContext); Q_ASSERT(m_storage); - m_storage->set_http_user_agent_settings( - new net::StaticHttpUserAgentSettings("en-us,en", m_browserContext->httpUserAgent().toStdString())); + m_storage->set_http_user_agent_settings(new HttpUserAgentSettingsQt(m_browserContext)); } void URLRequestContextGetterQt::updateHttpCache() @@ -311,11 +336,13 @@ void URLRequestContextGetterQt::generateJobFactory() 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(); + { + // 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( @@ -325,9 +352,10 @@ void URLRequestContextGetterQt::generateJobFactory() m_jobFactory->SetProtocolHandler(url::kFtpScheme, new net::FtpProtocolHandler(new net::FtpNetworkLayer(m_urlRequestContext->host_resolver()))); - Q_FOREACH (CustomUrlSchemeHandler* handler, m_browserContext->customUrlSchemeHandlers()) { - m_jobFactory->SetProtocolHandler(handler->scheme().toStdString(), handler->createProtocolHandler()); - } + QHash<QByteArray, QWebEngineUrlSchemeHandler*>::const_iterator it = m_browserContext->customUrlSchemeHandlers().constBegin(); + const QHash<QByteArray, QWebEngineUrlSchemeHandler*>::const_iterator end = m_browserContext->customUrlSchemeHandlers().constEnd(); + for (; it != end; ++it) + m_jobFactory->SetProtocolHandler(it.key().toStdString(), new CustomProtocolHandler(it.value())); m_urlRequestContext->set_job_factory(m_jobFactory.get()); } diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h index 38cfd7957..c7a4366ec 100644 --- a/src/core/url_request_context_getter_qt.h +++ b/src/core/url_request_context_getter_qt.h @@ -49,12 +49,14 @@ #include "net/url_request/url_request_job_factory_impl.h" #include "net/proxy/dhcp_proxy_script_fetcher_factory.h" +#include "cookie_monster_delegate_qt.h" +#include "network_delegate_qt.h" + #include "qglobal.h" #include <qatomic.h> namespace net { class MappedHostResolver; -class NetworkDelegate; class ProxyConfigService; } @@ -93,10 +95,12 @@ private: QAtomicPointer<net::ProxyConfigService> m_proxyConfigService; scoped_ptr<net::URLRequestContext> m_urlRequestContext; - scoped_ptr<net::NetworkDelegate> m_networkDelegate; + scoped_ptr<NetworkDelegateQt> m_networkDelegate; scoped_ptr<net::URLRequestContextStorage> m_storage; scoped_ptr<net::URLRequestJobFactoryImpl> m_jobFactory; scoped_ptr<net::DhcpProxyScriptFetcherFactory> m_dhcpProxyScriptFetcherFactory; + scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate; + friend class NetworkDelegateQt; }; } // namespace QtWebEngineCore diff --git a/src/core/url_request_custom_job.cpp b/src/core/url_request_custom_job.cpp index afdcecdfe..0a81d04a1 100644 --- a/src/core/url_request_custom_job.cpp +++ b/src/core/url_request_custom_job.cpp @@ -37,7 +37,8 @@ #include "url_request_custom_job.h" #include "url_request_custom_job_delegate.h" -#include "custom_url_scheme_handler.h" +#include "api/qwebengineurlrequestjob.h" +#include "api/qwebengineurlschemehandler.h" #include "type_conversion.h" #include "content/public/browser/browser_thread.h" @@ -53,7 +54,7 @@ using namespace net; namespace QtWebEngineCore { -URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, NetworkDelegate *networkDelegate, CustomUrlSchemeHandler *schemeHandler) +URLRequestCustomJob::URLRequestCustomJob(URLRequest *request, NetworkDelegate *networkDelegate, QWebEngineUrlSchemeHandler *schemeHandler) : URLRequestJob(request, networkDelegate) , m_device(0) , m_schemeHandler(schemeHandler) @@ -236,7 +237,8 @@ void URLRequestCustomJob::startAsync() QMutexLocker lock(&m_mutex); m_delegate = new URLRequestCustomJobDelegate(this); lock.unlock(); - m_schemeHandler->handleJob(m_delegate); + QWebEngineUrlRequestJob *requestJob = new QWebEngineUrlRequestJob(m_delegate); + m_schemeHandler->requestStarted(requestJob); } } // namespace diff --git a/src/core/url_request_custom_job.h b/src/core/url_request_custom_job.h index 60a1d60b9..a994c467a 100644 --- a/src/core/url_request_custom_job.h +++ b/src/core/url_request_custom_job.h @@ -45,16 +45,16 @@ #include <QtCore/QPointer> QT_FORWARD_DECLARE_CLASS(QIODevice) +QT_FORWARD_DECLARE_CLASS(QWebEngineUrlSchemeHandler) namespace QtWebEngineCore { -class CustomUrlSchemeHandler; class URLRequestCustomJobDelegate; // A request job that handles reading custom URL schemes class URLRequestCustomJob : public net::URLRequestJob { public: - URLRequestCustomJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate, CustomUrlSchemeHandler *schemeHandler); + URLRequestCustomJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate, QWebEngineUrlSchemeHandler *schemeHandler); virtual void Start() Q_DECL_OVERRIDE; virtual void Kill() Q_DECL_OVERRIDE; virtual bool ReadRawData(net::IOBuffer *buf, int bufSize, int *bytesRead) Q_DECL_OVERRIDE; @@ -81,7 +81,7 @@ private: QMutex m_mutex; QPointer<QIODevice> m_device; QPointer<URLRequestCustomJobDelegate> m_delegate; - CustomUrlSchemeHandler *m_schemeHandler; + QWebEngineUrlSchemeHandler *m_schemeHandler; std::string m_mimeType; std::string m_charset; int m_error; diff --git a/src/core/url_request_custom_job_delegate.cpp b/src/core/url_request_custom_job_delegate.cpp index 8d344c862..0650242c8 100644 --- a/src/core/url_request_custom_job_delegate.cpp +++ b/src/core/url_request_custom_job_delegate.cpp @@ -58,6 +58,11 @@ QUrl URLRequestCustomJobDelegate::url() const return toQt(m_job->request()->url()); } +QByteArray URLRequestCustomJobDelegate::method() const +{ + return QByteArray::fromStdString(m_job->request()->method()); +} + void URLRequestCustomJobDelegate::setReply(const QByteArray &contentType, QIODevice *device) { m_job->setReplyMimeType(contentType.toStdString()); diff --git a/src/core/url_request_custom_job_delegate.h b/src/core/url_request_custom_job_delegate.h index 6c1600592..5b6137820 100644 --- a/src/core/url_request_custom_job_delegate.h +++ b/src/core/url_request_custom_job_delegate.h @@ -63,6 +63,7 @@ public: }; QUrl url() const; + QByteArray method() const; void setReply(const QByteArray &contentType, QIODevice *device); void redirect(const QUrl& url); diff --git a/src/core/user_script.cpp b/src/core/user_script.cpp index fb293c56a..179febc48 100644 --- a/src/core/user_script.cpp +++ b/src/core/user_script.cpp @@ -168,14 +168,3 @@ UserScriptData &UserScript::data() const } } // namespace QtWebEngineCore - -QT_BEGIN_NAMESPACE -uint qHash(const QtWebEngineCore::UserScript &script, uint seed) -{ - if (script.isNull()) - return 0; - return qHash(script.sourceCode(), seed) ^ qHash(script.name(), seed) - ^ (script.injectionPoint() | (script.runsOnSubFrames() << 4)) - ^ script.worldId(); -} -QT_END_NAMESPACE diff --git a/src/core/user_script.h b/src/core/user_script.h index 7aeba9131..69c32c7ba 100644 --- a/src/core/user_script.h +++ b/src/core/user_script.h @@ -93,8 +93,4 @@ private: } // namespace QtWebEngineCore -QT_BEGIN_NAMESPACE -uint qHash(const QtWebEngineCore::UserScript &, uint seed = 0); -QT_END_NAMESPACE - #endif // USER_SCRIPT_H diff --git a/src/core/user_script_controller_host.cpp b/src/core/user_script_controller_host.cpp index 227a639b1..a0d3f6fed 100644 --- a/src/core/user_script_controller_host.cpp +++ b/src/core/user_script_controller_host.cpp @@ -52,9 +52,12 @@ namespace QtWebEngineCore { class UserScriptControllerHost::WebContentsObserverHelper : public content::WebContentsObserver { public: WebContentsObserverHelper(UserScriptControllerHost *, content::WebContents *); - virtual void AboutToNavigateRenderView(content::RenderViewHost* renderViewHost) Q_DECL_OVERRIDE; - virtual void WebContentsDestroyed() Q_DECL_OVERRIDE; + // WebContentsObserver overrides: + void RenderViewCreated(content::RenderViewHost *renderViewHost) override; + void RenderViewHostChanged(content::RenderViewHost *oldHost, content::RenderViewHost *newHost) override; + void WebContentsDestroyed() override; + private: UserScriptControllerHost *m_controllerHost; }; @@ -65,13 +68,23 @@ UserScriptControllerHost::WebContentsObserverHelper::WebContentsObserverHelper(U { } -void UserScriptControllerHost::WebContentsObserverHelper::AboutToNavigateRenderView(content::RenderViewHost *renderViewHost) +void UserScriptControllerHost::WebContentsObserverHelper::RenderViewCreated(content::RenderViewHost *renderViewHost) { content::WebContents *contents = web_contents(); Q_FOREACH (const UserScript &script, m_controllerHost->m_perContentsScripts.value(contents)) renderViewHost->Send(new RenderViewObserverHelper_AddScript(renderViewHost->GetRoutingID(), script.data())); } +void UserScriptControllerHost::WebContentsObserverHelper::RenderViewHostChanged(content::RenderViewHost *oldHost, + content::RenderViewHost *newHost) +{ + oldHost->Send(new RenderViewObserverHelper_ClearScripts(oldHost->GetRoutingID())); + + content::WebContents *contents = web_contents(); + Q_FOREACH (const UserScript &script, m_controllerHost->m_perContentsScripts.value(contents)) + newHost->Send(new RenderViewObserverHelper_AddScript(newHost->GetRoutingID(), script.data())); +} + void UserScriptControllerHost::WebContentsObserverHelper::WebContentsDestroyed() { m_controllerHost->webContentsDestroyed(web_contents()); @@ -103,9 +116,11 @@ void UserScriptControllerHost::addUserScript(const UserScript &script, WebConten return; // Global scripts should be dispatched to all our render processes. if (!adapter) { - m_profileWideScripts.insert(script); - Q_FOREACH (content::RenderProcessHost *renderer, m_observedProcesses) - renderer->Send(new UserScriptController_AddScript(script.data())); + if (!m_profileWideScripts.contains(script)) { + m_profileWideScripts.append(script); + Q_FOREACH (content::RenderProcessHost *renderer, m_observedProcesses) + renderer->Send(new UserScriptController_AddScript(script.data())); + } } else { content::WebContents *contents = adapter->webContents(); ContentsScriptsMap::iterator it = m_perContentsScripts.find(contents); @@ -113,11 +128,13 @@ void UserScriptControllerHost::addUserScript(const UserScript &script, WebConten // We need to keep track of RenderView/RenderViewHost changes for a given contents // in order to make sure the scripts stay in sync new WebContentsObserverHelper(this, contents); - it = m_perContentsScripts.insert(contents, (QSet<UserScript>() << script)); + it = m_perContentsScripts.insert(contents, (QList<UserScript>() << script)); } else { - QSet<UserScript> currentScripts = it.value(); - currentScripts.insert(script); - m_perContentsScripts.insert(contents, currentScripts); + QList<UserScript> currentScripts = it.value(); + if (!currentScripts.contains(script)) { + currentScripts.append(script); + m_perContentsScripts.insert(contents, currentScripts); + } } contents->Send(new RenderViewObserverHelper_AddScript(contents->GetRoutingID(), script.data())); } @@ -138,7 +155,8 @@ bool UserScriptControllerHost::removeUserScript(const UserScript &script, WebCon if (script.isNull()) return false; if (!adapter) { - QSet<UserScript>::iterator it = m_profileWideScripts.find(script); + QList<UserScript>::iterator it + = std::find(m_profileWideScripts.begin(), m_profileWideScripts.end(), script); if (it == m_profileWideScripts.end()) return false; Q_FOREACH (content::RenderProcessHost *renderer, m_observedProcesses) @@ -148,12 +166,12 @@ bool UserScriptControllerHost::removeUserScript(const UserScript &script, WebCon content::WebContents *contents = adapter->webContents(); if (!m_perContentsScripts.contains(contents)) return false; - QSet<UserScript> &set(m_perContentsScripts[contents]); - QSet<UserScript>::iterator it = set.find(script); - if (it == set.end()) + QList<UserScript> &list(m_perContentsScripts[contents]); + QList<UserScript>::iterator it = std::find(list.begin(), list.end(), script); + if (it == list.end()) return false; contents->Send(new RenderViewObserverHelper_RemoveScript(contents->GetRoutingID(), (*it).data())); - set.erase(it); + list.erase(it); } return true; } @@ -171,7 +189,7 @@ void UserScriptControllerHost::clearAllScripts(WebContentsAdapter *adapter) } } -const QSet<UserScript> UserScriptControllerHost::registeredScripts(WebContentsAdapter *adapter) const +const QList<UserScript> UserScriptControllerHost::registeredScripts(WebContentsAdapter *adapter) const { if (!adapter) return m_profileWideScripts; diff --git a/src/core/user_script_controller_host.h b/src/core/user_script_controller_host.h index 49c96b333..3884fb3b9 100644 --- a/src/core/user_script_controller_host.h +++ b/src/core/user_script_controller_host.h @@ -64,7 +64,7 @@ public: bool removeUserScript(const UserScript &script, WebContentsAdapter *adapter); void clearAllScripts(WebContentsAdapter *adapter); void reserve(WebContentsAdapter *adapter, int count); - const QSet<UserScript> registeredScripts(WebContentsAdapter *adapter) const; + const QList<UserScript> registeredScripts(WebContentsAdapter *adapter) const; void renderProcessStartedWithHost(content::RenderProcessHost *renderer); @@ -75,8 +75,8 @@ private: void webContentsDestroyed(content::WebContents *); - QSet<UserScript> m_profileWideScripts; - typedef QHash<content::WebContents *, QSet<UserScript>> ContentsScriptsMap; + QList<UserScript> m_profileWideScripts; + typedef QHash<content::WebContents *, QList<UserScript>> ContentsScriptsMap; ContentsScriptsMap m_perContentsScripts; QSet<content::RenderProcessHost *> m_observedProcesses; QScopedPointer<RenderProcessObserverHelper> m_renderProcessObserver; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index e35319fdd..31ebb1244 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -46,6 +46,7 @@ #include "browser_context_qt.h" #include "media_capture_devices_dispatcher.h" #include "qt_render_view_observer_host.h" +#include "qwebenginecallback_p.h" #include "type_conversion.h" #include "web_channel_ipc_transport_host.h" #include "web_contents_adapter_client.h" @@ -57,6 +58,8 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/child_process_security_policy.h" +#include "content/public/browser/devtools_agent_host.h" +#include <content/public/browser/download_manager.h> #include "content/public/browser/host_zoom_map.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_view_host.h" @@ -66,7 +69,6 @@ #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 <QDir> @@ -165,19 +167,6 @@ static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint6 adapterClient->didRunJavaScript(requestId, fromJSValue(result)); } -static QStringList listRecursively(const QDir& dir) { - QStringList ret; - QFileInfoList infoList(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot |QDir::Hidden)); - Q_FOREACH (const QFileInfo &fileInfo, infoList) { - if (fileInfo.isDir()) { - ret.append(fileInfo.absolutePath() + QStringLiteral("/.")); // Match chromium's behavior. See chrome/browser/file_select_helper.cc - ret.append(listRecursively(QDir(fileInfo.absoluteFilePath()))); - } else - ret.append(fileInfo.absoluteFilePath()); - } - return ret; -} - static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext) { content::WebContents::CreateParams create_params(browserContext, NULL); @@ -217,14 +206,11 @@ static void serializeNavigationHistory(const content::NavigationController &cont output << entry->GetIsOverridingUserAgent(); output << static_cast<qint64>(entry->GetTimestamp().ToInternalValue()); output << entry->GetHttpStatusCode(); - // If you want to navigate a named frame in Chrome, you will first need to - // add support for persisting it. It is currently only used for layout tests. - CHECK(entry->GetFrameToNavigate().empty()); } } } -static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, std::vector<content::NavigationEntry*> *entries, content::BrowserContext *browserContext) +static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, ScopedVector<content::NavigationEntry> *entries, content::BrowserContext *browserContext) { int version; input >> version; @@ -265,13 +251,13 @@ static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, // If we couldn't unpack the entry successfully, abort everything. if (input.status() != QDataStream::Ok) { *currentIndex = -1; - Q_FOREACH (content::NavigationEntry *entry, *entries) + for (content::NavigationEntry *entry : *entries) delete entry; entries->clear(); return; } - content::NavigationEntry *entry = content::NavigationController::CreateNavigationEntry( + scoped_ptr<content::NavigationEntry> entry = content::NavigationController::CreateNavigationEntry( toGurl(virtualUrl), content::Referrer(toGurl(referrerUrl), static_cast<blink::WebReferrerPolicy>(referrerPolicy)), // Use a transition type of reload so that we don't incorrectly @@ -290,7 +276,7 @@ static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, entry->SetIsOverridingUserAgent(isOverridingUserAgent); entry->SetTimestamp(base::Time::FromInternalValue(timestamp)); entry->SetHttpStatusCode(httpStatusCode); - entries->push_back(entry); + entries->push_back(entry.release()); } } @@ -323,7 +309,7 @@ WebContentsAdapterPrivate::WebContentsAdapterPrivate() : engineContext(WebEngineContext::current()) , webChannel(0) , adapterClient(0) - , nextRequestId(1) + , nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) , lastFindRequestId(0) { } @@ -337,7 +323,7 @@ WebContentsAdapterPrivate::~WebContentsAdapterPrivate() QExplicitlySharedDataPointer<WebContentsAdapter> WebContentsAdapter::createFromSerializedNavigationHistory(QDataStream &input, WebContentsAdapterClient *adapterClient) { int currentIndex; - std::vector<content::NavigationEntry*> entries; + ScopedVector<content::NavigationEntry> entries; deserializeNavigationHistory(input, ¤tIndex, &entries, adapterClient->browserContextAdapter()->browserContext()); if (currentIndex == -1) @@ -394,6 +380,7 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) const int qtCursorFlashTime = QGuiApplication::styleHints()->cursorFlashTime(); rendererPrefs->caret_blink_interval = 0.5 * static_cast<double>(qtCursorFlashTime) / 1000; rendererPrefs->user_agent_override = d->browserContextAdapter->httpUserAgent().toStdString(); + rendererPrefs->accept_languages = d->browserContextAdapter->httpAcceptLanguageWithoutQualities().toStdString(); d->webContents->GetRenderViewHost()->SyncRendererPrefs(); // Create and attach observers to the WebContents. @@ -411,7 +398,7 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); Q_ASSERT(rvh); if (!rvh->IsRenderViewLive()) - static_cast<content::WebContentsImpl*>(d->webContents.get())->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, true); + static_cast<content::WebContentsImpl*>(d->webContents.get())->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, content::FrameReplicationState(), true); } void WebContentsAdapter::reattachRWHV() @@ -497,7 +484,9 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT params.base_url_for_data_url = toGurl(baseUrl); params.virtual_url_for_data_url = baseUrl.isEmpty() ? GURL(url::kAboutBlankURL) : toGurl(baseUrl); params.can_load_local_resources = true; + params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_API); d->webContents->GetController().LoadURLWithParams(params); + d->webContents->Focus(); } QUrl WebContentsAdapter::activeUrl() const @@ -587,6 +576,12 @@ void WebContentsAdapter::selectAll() d->webContents->SelectAll(); } +void WebContentsAdapter::requestClose() +{ + Q_D(WebContentsAdapter); + d->webContents->DispatchBeforeUnload(false); +} + void WebContentsAdapter::navigateToIndex(int offset) { Q_D(WebContentsAdapter); @@ -774,6 +769,66 @@ void WebContentsAdapter::updateWebPreferences(const content::WebPreferences & we d->webContents->GetRenderViewHost()->UpdateWebkitPreferences(webPreferences); } +void WebContentsAdapter::download(const QUrl &url, const QString &suggestedFileName) +{ + content::BrowserContext *bctx = webContents()->GetBrowserContext(); + content::DownloadManager *dlm = content::BrowserContext::GetDownloadManager(bctx); + if (!dlm) + return; + + scoped_ptr<content::DownloadUrlParameters> params( + content::DownloadUrlParameters::FromWebContents(webContents(), toGurl(url))); + params->set_suggested_name(toString16(suggestedFileName)); + dlm->DownloadUrl(params.Pass()); +} + +void WebContentsAdapter::copyImageAt(const QPoint &location) +{ + Q_D(WebContentsAdapter); + d->webContents->GetRenderViewHost()->CopyImageAt(location.x(), location.y()); +} + +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerNoAction, blink::WebMediaPlayerAction::Unknown) +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerPlay, blink::WebMediaPlayerAction::Play) +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerMute, blink::WebMediaPlayerAction::Mute) +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerLoop, blink::WebMediaPlayerAction::Loop) +ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerControls, blink::WebMediaPlayerAction::Controls) + +void WebContentsAdapter::executeMediaPlayerActionAt(const QPoint &location, MediaPlayerAction action, bool enable) +{ + Q_D(WebContentsAdapter); + blink::WebMediaPlayerAction blinkAction((blink::WebMediaPlayerAction::Type)action, enable); + d->webContents->GetRenderViewHost()->ExecuteMediaPlayerActionAtLocation(toGfx(location), blinkAction); +} + +void WebContentsAdapter::inspectElementAt(const QPoint &location) +{ + Q_D(WebContentsAdapter); + if (content::DevToolsAgentHost::HasFor(d->webContents.get())) { + content::DevToolsAgentHost::GetOrCreateFor(d->webContents.get())->InspectElement(location.x(), location.y()); + } +} + +bool WebContentsAdapter::hasInspector() const +{ + const Q_D(WebContentsAdapter); + if (content::DevToolsAgentHost::HasFor(d->webContents.get())) + return content::DevToolsAgentHost::GetOrCreateFor(d->webContents.get())->IsAttached(); + return false; +} + +void WebContentsAdapter::exitFullScreen() +{ + Q_D(WebContentsAdapter); + d->webContents->ExitFullscreen(); +} + +void WebContentsAdapter::changedFullScreen() +{ + Q_D(WebContentsAdapter); + d->webContents->NotifyFullscreenChanged(); +} + void WebContentsAdapter::wasShown() { Q_D(WebContentsAdapter); @@ -795,7 +850,7 @@ void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, void WebContentsAdapter::runGeolocationRequestCallback(const QUrl &securityOrigin, bool allowed) { Q_D(WebContentsAdapter); - d->webContentsDelegate->geolocationPermissionReply(securityOrigin, allowed); + d->browserContextAdapter->permissionRequestReply(securityOrigin, BrowserContextAdapter::GeolocationPermission, allowed); } void WebContentsAdapter::grantMouseLockPermission(bool granted) @@ -822,21 +877,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) +void WebContentsAdapter::backgroundColorChanged() { Q_D(WebContentsAdapter); - content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); - Q_ASSERT(rvh); - QStringList files(fileList); - if (mode == WebContentsAdapterClient::UploadFolder && !fileList.isEmpty() - && QFileInfo(fileList.first()).isDir()) // Enumerate the directory - files = listRecursively(QDir(fileList.first())); - rvh->FilesSelectedInChooser(toVector<content::FileChooserFileInfo>(files), static_cast<content::FileChooserParams::Mode>(mode)); + if (content::RenderWidgetHostView *rwhv = d->webContents->GetRenderWidgetHostView()) + rwhv->SetBackgroundColor(toSk(d->adapterClient->backgroundColor())); } content::WebContents *WebContentsAdapter::webContents() const @@ -869,4 +914,36 @@ void WebContentsAdapter::setWebChannel(QWebChannel *channel) channel->connectTo(d->webChannelTransport.get()); } +WebContentsAdapterClient::RenderProcessTerminationStatus +WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) { + auto status = WebContentsAdapterClient::RenderProcessTerminationStatus(-1); + switch (terminationStatus) { + case base::TERMINATION_STATUS_NORMAL_TERMINATION: + status = WebContentsAdapterClient::NormalTerminationStatus; + break; + case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: + status = WebContentsAdapterClient::AbnormalTerminationStatus; + break; + case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: +#if defined(OS_CHROMEOS) + case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM: +#endif + status = WebContentsAdapterClient::KilledTerminationStatus; + break; + case base::TERMINATION_STATUS_PROCESS_CRASHED: +#if defined(OS_ANDROID) + case base::TERMINATION_STATUS_OOM_PROTECTED: +#endif + status = WebContentsAdapterClient::CrashedTerminationStatus; + break; + case base::TERMINATION_STATUS_STILL_RUNNING: + case base::TERMINATION_STATUS_MAX_ENUM: + // should be unreachable since Chromium asserts status != TERMINATION_STATUS_STILL_RUNNING + // before calling this method + break; + } + + return status; +} + } // namespace QtWebEngineCore diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 5ea55c1b8..ce033bdb4 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -104,7 +104,6 @@ public: void serializeNavigationHistory(QDataStream &output); void setZoomFactor(qreal); qreal currentZoomFactor() const; - void filesSelectedInChooser(const QStringList &fileList, WebContentsAdapterClient::FileChooserMode); void runJavaScript(const QString &javaScript); quint64 runJavaScriptCallbackResult(const QString &javaScript); quint64 fetchDocumentMarkup(); @@ -112,6 +111,25 @@ public: quint64 findText(const QString &subString, bool caseSensitively, bool findBackward); void stopFinding(); void updateWebPreferences(const content::WebPreferences &webPreferences); + void download(const QUrl &url, const QString &suggestedFileName); + + // Must match blink::WebMediaPlayerAction::Type. + enum MediaPlayerAction { + MediaPlayerNoAction, + MediaPlayerPlay, + MediaPlayerMute, + MediaPlayerLoop, + MediaPlayerControls, + MediaPlayerTypeLast = MediaPlayerControls + }; + void copyImageAt(const QPoint &location); + void executeMediaPlayerActionAt(const QPoint &location, MediaPlayerAction action, bool enable); + + void inspectElementAt(const QPoint &location); + bool hasInspector() const; + void exitFullScreen(); + void requestClose(); + void changedFullScreen(); void wasShown(); void wasHidden(); @@ -120,6 +138,7 @@ public: void grantMouseLockPermission(bool granted); void dpiScaleChanged(); + void backgroundColorChanged(); QAccessibleInterface *browserAccessible(); BrowserContextQt* browserContext(); BrowserContextAdapter* browserContextAdapter(); diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 3ed3ab9ab..f2a05c575 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -52,7 +52,9 @@ QT_FORWARD_DECLARE_CLASS(CertificateErrorController) namespace QtWebEngineCore { +class AuthenticationDialogController; class BrowserContextAdapter; +class FilePickerController; class JavaScriptDialogController; class RenderWidgetHostViewQt; class RenderWidgetHostViewQtDelegate; @@ -65,10 +67,55 @@ class WebEngineSettings; class WebEngineContextMenuData { public: + WebEngineContextMenuData() + : mediaType(MediaTypeNone) + , hasImageContent(false) + , mediaFlags(0) + { + } + + // Must match blink::WebContextMenuData::MediaType: + enum MediaType { + // No special node is in context. + MediaTypeNone, + // An image node is selected. + MediaTypeImage, + // A video node is selected. + MediaTypeVideo, + // An audio node is selected. + MediaTypeAudio, + // A canvas node is selected. + MediaTypeCanvas, + // A file node is selected. + MediaTypeFile, + // A plugin node is selected. + MediaTypePlugin, + MediaTypeLast = MediaTypePlugin + }; + // Must match blink::WebContextMenuData::MediaFlags: + enum MediaFlags { + MediaNone = 0x0, + MediaInError = 0x1, + MediaPaused = 0x2, + MediaMuted = 0x4, + MediaLoop = 0x8, + MediaCanSave = 0x10, + MediaHasAudio = 0x20, + MediaCanToggleControls = 0x40, + MediaControls = 0x80, + MediaCanPrint = 0x100, + MediaCanRotate = 0x200, + }; + QPoint pos; QUrl linkUrl; QString linkText; QString selectedText; + QUrl mediaUrl; + MediaType mediaType; + bool hasImageContent; + uint mediaFlags; + QString suggestedFileName; // Some likely candidates for future additions as we add support for the related actions: // bool isImageBlocked; // bool isEditable; @@ -100,18 +147,11 @@ public: AlertDialog, ConfirmDialog, PromptDialog, + UnloadDialog, // Leave room for potential new specs InternalAuthorizationDialog = 0x10, }; - // Must match the ones in file_chooser_params.h - enum FileChooserMode { - Open, - OpenMultiple, - UploadFolder, - Save - }; - enum NavigationRequestAction { AcceptRequest, // Make room in the valid range of the enum for extra actions exposed in Experimental. @@ -119,7 +159,7 @@ public: }; enum NavigationType { - LinkClickedNavigation, + LinkNavigation, TypedNavigation, FormSubmittedNavigation, BackForwardNavigation, @@ -133,6 +173,13 @@ public: Error }; + enum RenderProcessTerminationStatus { + NormalTerminationStatus = 0, + AbnormalTerminationStatus, + CrashedTerminationStatus, + KilledTerminationStatus + }; + enum MediaRequestFlag { MediaNone = 0, MediaAudioCapture = 0x01, @@ -152,6 +199,7 @@ public: virtual void selectionChanged() = 0; virtual QRectF viewportRect() const = 0; virtual qreal dpiScale() const = 0; + virtual QColor backgroundColor() const = 0; virtual void loadStarted(const QUrl &provisionalUrl, bool isErrorPage = false) = 0; virtual void loadCommitted() = 0; virtual void loadVisuallyCommitted() = 0; @@ -160,12 +208,13 @@ public: virtual void unhandledKeyEvent(QKeyEvent *event) = 0; virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect & initialGeometry) = 0; virtual void close() = 0; + virtual void windowCloseRejected() = 0; virtual bool contextMenuRequested(const WebEngineContextMenuData&) = 0; virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) = 0; - virtual void requestFullScreen(bool) = 0; - virtual bool isFullScreen() const = 0; + virtual void requestFullScreenMode(const QUrl &origin, bool fullscreen) = 0; + virtual bool isFullScreenMode() const = 0; virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) = 0; - virtual void runFileChooser(FileChooserMode, const QString &defaultFileName, const QStringList &acceptedMimeTypes) = 0; + virtual void runFileChooser(FilePickerController *controller) = 0; virtual void didRunJavaScript(quint64 requestId, const QVariant& result) = 0; virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) = 0; virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) = 0; @@ -177,7 +226,7 @@ public: 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 authenticationRequired(QSharedPointer<AuthenticationDialogController>) = 0; virtual void runGeolocationPermissionRequest(const QUrl &securityOrigin) = 0; virtual void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) = 0; virtual void runMouseLockPermissionRequest(const QUrl &securityOrigin) = 0; @@ -185,6 +234,8 @@ public: virtual void showValidationMessage(const QRect &anchor, const QString &mainText, const QString &subText) = 0; virtual void hideValidationMessage() = 0; virtual void moveValidationMessage(const QRect &anchor) = 0; + RenderProcessTerminationStatus renderProcessExitStatus(int); + virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) = 0; virtual void allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) = 0; diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index c16c76f75..1f789161a 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -41,7 +41,9 @@ #include "web_contents_delegate_qt.h" #include "browser_context_adapter.h" +#include "file_picker_controller.h" #include "media_capture_devices_dispatcher.h" +#include "network_delegate_qt.h" #include "type_conversion.h" #include "web_contents_adapter_client.h" #include "web_contents_adapter_p.h" @@ -63,6 +65,8 @@ #include "content/public/common/web_preferences.h" #include "ui/events/latency_info.h" +#include <QDesktopServices> + namespace QtWebEngineCore { // Maps the LogSeverity defines in base/logging.h to the web engines message levels. @@ -107,7 +111,7 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents return target; } -void WebContentsDelegateQt::NavigationStateChanged(const content::WebContents* source, content::InvalidateTypes changed_flags) +void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags) { if (changed_flags & content::INVALIDATE_TYPE_URL) m_viewClient->urlChanged(toQt(source->GetVisibleURL())); @@ -126,7 +130,7 @@ void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content void WebContentsDelegateQt::CloseContents(content::WebContents *source) { m_viewClient->close(); - GetJavaScriptDialogManager()->CancelActiveAndPendingDialogs(source); + GetJavaScriptDialogManager(source)->CancelActiveAndPendingDialogs(source); } void WebContentsDelegateQt::LoadProgressChanged(content::WebContents* source, double progress) @@ -176,13 +180,14 @@ void WebContentsDelegateQt::DidCommitProvisionalLoadForFrame(content::RenderFram m_viewClient->loadCommitted(); } -void WebContentsDelegateQt::DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description) +void WebContentsDelegateQt::DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description, bool was_ignored_by_handler) { - DidFailLoad(render_frame_host, validated_url, error_code, error_description); + DidFailLoad(render_frame_host, validated_url, error_code, error_description, was_ignored_by_handler); } -void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description) +void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description, bool was_ignored_by_handler) { + Q_UNUSED(was_ignored_by_handler); if (m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID()) || render_frame_host->GetParent()) return; @@ -233,36 +238,44 @@ void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::Favic } } -content::JavaScriptDialogManager *WebContentsDelegateQt::GetJavaScriptDialogManager() +content::JavaScriptDialogManager *WebContentsDelegateQt::GetJavaScriptDialogManager(content::WebContents *) { return JavaScriptDialogManagerQt::GetInstance(); } -void WebContentsDelegateQt::ToggleFullscreenModeForTab(content::WebContents* web_contents, bool enter_fullscreen) +void WebContentsDelegateQt::EnterFullscreenModeForTab(content::WebContents *web_contents, const GURL& origin) { - if (m_viewClient->isFullScreen() != enter_fullscreen) { - m_viewClient->requestFullScreen(enter_fullscreen); - web_contents->GetRenderViewHost()->WasResized(); - } + Q_UNUSED(web_contents); + if (!m_viewClient->isFullScreenMode()) + m_viewClient->requestFullScreenMode(toQt(origin), true); +} + +void WebContentsDelegateQt::ExitFullscreenModeForTab(content::WebContents *web_contents) +{ + if (m_viewClient->isFullScreenMode()) + m_viewClient->requestFullScreenMode(toQt(web_contents->GetLastCommittedURL().GetOrigin()), false); } bool WebContentsDelegateQt::IsFullscreenForTabOrPending(const content::WebContents* web_contents) const { - return m_viewClient->isFullScreen(); + Q_UNUSED(web_contents); + return m_viewClient->isFullScreenMode(); } -ASSERT_ENUMS_MATCH(WebContentsAdapterClient::Open, content::FileChooserParams::Open) -ASSERT_ENUMS_MATCH(WebContentsAdapterClient::Save, content::FileChooserParams::Save) +ASSERT_ENUMS_MATCH(FilePickerController::Open, content::FileChooserParams::Open) +ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, content::FileChooserParams::OpenMultiple) +ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, content::FileChooserParams::UploadFolder) +ASSERT_ENUMS_MATCH(FilePickerController::Save, content::FileChooserParams::Save) void WebContentsDelegateQt::RunFileChooser(content::WebContents *web_contents, const content::FileChooserParams ¶ms) { - Q_UNUSED(web_contents) QStringList acceptedMimeTypes; acceptedMimeTypes.reserve(params.accept_types.size()); for (std::vector<base::string16>::const_iterator it = params.accept_types.begin(); it < params.accept_types.end(); ++it) acceptedMimeTypes.append(toQt(*it)); - m_viewClient->runFileChooser(static_cast<WebContentsAdapterClient::FileChooserMode>(params.mode), toQt(params.default_file_name.value()), acceptedMimeTypes); + FilePickerController *controller = new FilePickerController(static_cast<FilePickerController::FileChooserMode>(params.mode), web_contents, toQt(params.default_file_name.value()), acceptedMimeTypes); + m_viewClient->runFileChooser(controller); } bool WebContentsDelegateQt::AddMessageToConsole(content::WebContents *source, int32 level, const base::string16 &message, int32 line_no, const base::string16 &source_id) @@ -339,28 +352,21 @@ void WebContentsDelegateQt::allowCertificateError(const QSharedPointer<Certifica m_viewClient->allowCertificateError(errorController); } -void WebContentsDelegateQt::requestGeolocationPermission(const GURL &requestingFrameOrigin, const base::Callback<void (bool)> &resultCallback) +void WebContentsDelegateQt::requestGeolocationPermission(const QUrl &requestingOrigin) { - QUrl url = toQt(requestingFrameOrigin); - bool newRequest = !m_geolocationPermissionRequests.contains(url); - m_geolocationPermissionRequests[url] = resultCallback; - if (newRequest) - m_viewClient->runGeolocationPermissionRequest(url); + m_viewClient->runGeolocationPermissionRequest(requestingOrigin); } -void WebContentsDelegateQt::cancelGeolocationPermissionRequest(const GURL &requestingFrameOrigin) -{ - m_geolocationPermissionRequests.remove(toQt(requestingFrameOrigin)); - // FIXME: Tell the API layer to cancel the permission request? -} +extern int pageTransitionToNavigationType(ui::PageTransition transition); -void WebContentsDelegateQt::geolocationPermissionReply(const QUrl &origin, bool permission) +void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame) { - auto it = m_geolocationPermissionRequests.find(origin); - if (it != m_geolocationPermissionRequests.end()) { - (*it).Run(permission); - m_geolocationPermissionRequests.erase(it); - } + int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; + m_viewClient->navigationRequested(pageTransitionToNavigationType(page_transition), url, navigationRequestAction, is_main_frame); +#ifndef QT_NO_DESKTOPSERVICES + if (navigationRequestAction == WebContentsAdapterClient::AcceptRequest) + QDesktopServices::openUrl(url); +#endif } void WebContentsDelegateQt::ShowValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view, const base::string16 &main_text, const base::string16 &sub_text) @@ -381,4 +387,13 @@ void WebContentsDelegateQt::MoveValidationMessage(content::WebContents *web_cont m_viewClient->moveValidationMessage(toQt(anchor_in_root_view)); } +void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool proceed, bool *proceed_to_fire_unload) +{ + Q_UNUSED(tab); + Q_ASSERT(proceed_to_fire_unload); + *proceed_to_fire_unload = proceed; + if (!proceed) + m_viewClient->windowCloseRejected(); +} + } // namespace QtWebEngineCore diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 41acf7c84..abdf75fe5 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -39,6 +39,7 @@ #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" +#include "content/public/common/permission_status.mojom.h" #include "base/callback.h" @@ -72,13 +73,14 @@ public: // WebContentsDelegate overrides virtual content::WebContents *OpenURLFromTab(content::WebContents *source, const content::OpenURLParams ¶ms) Q_DECL_OVERRIDE; - virtual void NavigationStateChanged(const content::WebContents* source, content::InvalidateTypes changed_flags) Q_DECL_OVERRIDE; + virtual void NavigationStateChanged(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 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 content::JavaScriptDialogManager *GetJavaScriptDialogManager(content::WebContents *source) Q_DECL_OVERRIDE; + virtual void EnterFullscreenModeForTab(content::WebContents* web_contents, const GURL& origin) Q_DECL_OVERRIDE; + virtual void ExitFullscreenModeForTab(content::WebContents*) Q_DECL_OVERRIDE; virtual bool IsFullscreenForTabOrPending(const content::WebContents* web_contents) const Q_DECL_OVERRIDE; virtual void RunFileChooser(content::WebContents *, const content::FileChooserParams ¶ms) Q_DECL_OVERRIDE; virtual bool AddMessageToConsole(content::WebContents* source, int32 level, const base::string16& message, int32 line_no, const base::string16& source_id) Q_DECL_OVERRIDE; @@ -89,28 +91,28 @@ public: virtual void ShowValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view, const base::string16 &main_text, const base::string16 &sub_text) Q_DECL_OVERRIDE; virtual void HideValidationMessage(content::WebContents *web_contents) Q_DECL_OVERRIDE; virtual void MoveValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view) Q_DECL_OVERRIDE; + void BeforeUnloadFired(content::WebContents* tab, bool proceed, bool* proceed_to_fire_unload) Q_DECL_OVERRIDE; // WebContentsObserver overrides virtual void RenderFrameDeleted(content::RenderFrameHost *render_frame_host) Q_DECL_OVERRIDE; 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 DidFailProvisionalLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url, + int error_code, const base::string16 &error_description, bool was_ignored_by_handler) Q_DECL_OVERRIDE; + virtual void DidFailLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url, + int error_code, const base::string16 &error_description, bool was_ignored_by_handler) 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); + void requestGeolocationPermission(const QUrl &requestingOrigin); + void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame); 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 af0c1fe38..67addacd5 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -53,8 +53,10 @@ void WebContentsViewQt::initialize(WebContentsAdapterClient* client) m_factoryClient = client; // Check if a RWHV was created before the initialization. - if (m_webContents->GetRenderWidgetHostView()) - static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())->setAdapterClient(client); + if (auto rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) { + rwhv->setAdapterClient(client); + rwhv->SetBackgroundColor(toSk(client->backgroundColor())); + } } content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForWidget(content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) @@ -82,6 +84,14 @@ content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForPopupWidget(c return view; } +void WebContentsViewQt::RenderViewCreated(content::RenderViewHost* host) +{ + // The render process is done creating the RenderView and it's ready to be routed + // messages at this point. + if (m_client) + host->GetView()->SetBackgroundColor(toSk(m_client->backgroundColor())); +} + void WebContentsViewQt::CreateView(const gfx::Size& initial_size, gfx::NativeView context) { // This is passed through content::WebContents::CreateParams::context either as the native view's client @@ -103,6 +113,8 @@ void WebContentsViewQt::GetContainerBounds(gfx::Rect* out) const void WebContentsViewQt::Focus() { + if (content::RenderWidgetHostView *rwhv = m_webContents->GetRenderWidgetHostView()) + rwhv->Focus(); m_client->focusContainer(); } @@ -111,6 +123,26 @@ void WebContentsViewQt::SetInitialFocus() Focus(); } +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeNone, blink::WebContextMenuData::MediaTypeNone) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeImage, blink::WebContextMenuData::MediaTypeImage) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeVideo, blink::WebContextMenuData::MediaTypeVideo) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeAudio, blink::WebContextMenuData::MediaTypeAudio) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeCanvas, blink::WebContextMenuData::MediaTypeCanvas) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypeFile, blink::WebContextMenuData::MediaTypeFile) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaTypePlugin, blink::WebContextMenuData::MediaTypePlugin) + +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaNone, blink::WebContextMenuData::MediaNone) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaInError, blink::WebContextMenuData::MediaInError) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaPaused, blink::WebContextMenuData::MediaPaused) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaMuted, blink::WebContextMenuData::MediaMuted) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaLoop, blink::WebContextMenuData::MediaLoop) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanSave, blink::WebContextMenuData::MediaCanSave) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaHasAudio, blink::WebContextMenuData::MediaHasAudio) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanToggleControls, blink::WebContextMenuData::MediaCanToggleControls) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaControls, blink::WebContextMenuData::MediaControls) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanPrint, blink::WebContextMenuData::MediaCanPrint) +ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanRotate, blink::WebContextMenuData::MediaCanRotate) + static WebEngineContextMenuData fromParams(const content::ContextMenuParams ¶ms) { WebEngineContextMenuData ret; @@ -118,6 +150,11 @@ static WebEngineContextMenuData fromParams(const content::ContextMenuParams &par ret.linkUrl = toQt(params.link_url); ret.linkText = toQt(params.link_text.data()); ret.selectedText = toQt(params.selection_text.data()); + ret.mediaUrl = toQt(params.src_url); + ret.mediaType = (WebEngineContextMenuData::MediaType)params.media_type; + ret.hasImageContent = params.has_image_contents; + ret.mediaFlags = params.media_flags; + ret.suggestedFileName = toQt(params.suggested_filename.data()); return ret; } diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index 896955f7d..cbbca2371 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -43,8 +43,9 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" -#include "web_contents_adapter_client.h" +#include "qtwebenginecoreglobal_p.h" #include "render_widget_host_view_qt.h" +#include "web_contents_adapter_client.h" #include "web_contents_delegate_qt.h" #include "web_engine_context.h" @@ -75,7 +76,7 @@ public: virtual void SetPageTitle(const base::string16& title) Q_DECL_OVERRIDE { } - virtual void RenderViewCreated(content::RenderViewHost* host) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } + virtual void RenderViewCreated(content::RenderViewHost* host) Q_DECL_OVERRIDE; virtual void RenderViewSwappedIn(content::RenderViewHost* host) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED } diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 8bc047321..4e4159cef 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -153,6 +153,7 @@ void WebEngineContext::destroy() // Flush the UI message loop before quitting. while (delegate->DoWork()) { } GLContextHelper::destroy(); + m_devtools.reset(0); m_runLoop->AfterRun(); // Force to destroy RenderProcessHostImpl by destroying BrowserMainRunner. @@ -202,34 +203,35 @@ WebEngineContext::WebEngineContext() Q_FOREACH (const QString& arg, QCoreApplication::arguments()) args << arg.toUtf8(); + bool useEmbeddedSwitches = args.removeAll("--enable-embedded-switches"); +#if defined(QTWEBENGINE_EMBEDDED_SWITCHES) + useEmbeddedSwitches = !args.removeAll("--disable-embedded-switches"); +#endif + QVector<const char*> argv(args.size()); for (int i = 0; i < args.size(); ++i) argv[i] = args[i].constData(); - CommandLine::Init(argv.size(), argv.constData()); + base::CommandLine::Init(argv.size(), argv.constData()); - CommandLine* parsedCommandLine = CommandLine::ForCurrentProcess(); + base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess(); parsedCommandLine->AppendSwitchPath(switches::kBrowserSubprocessPath, WebEngineLibraryInfo::getPath(content::CHILD_PROCESS_EXE)); parsedCommandLine->AppendSwitch(switches::kNoSandbox); - parsedCommandLine->AppendSwitch(switches::kDisablePlugins); parsedCommandLine->AppendSwitch(switches::kEnableDelegatedRenderer); parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); parsedCommandLine->AppendSwitch(switches::kInProcessGPU); -#if defined(QTWEBENGINE_MOBILE_SWITCHES) - // Inspired by the Android port's default switches - parsedCommandLine->AppendSwitch(switches::kEnableOverlayScrollbar); - parsedCommandLine->AppendSwitch(switches::kEnablePinch); - parsedCommandLine->AppendSwitch(switches::kEnableViewport); - parsedCommandLine->AppendSwitch(switches::kEnableViewportMeta); - parsedCommandLine->AppendSwitch(switches::kMainFrameResizesAreOrientationChanges); - parsedCommandLine->AppendSwitch(switches::kDisableAcceleratedVideoDecode); - parsedCommandLine->AppendSwitch(switches::kDisableGpuShaderDiskCache); - parsedCommandLine->AppendSwitch(switches::kDisable2dCanvasAntialiasing); - parsedCommandLine->AppendSwitch(switches::kEnableImplSidePainting); - parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing); - - parsedCommandLine->AppendSwitchASCII(switches::kProfilerTiming, switches::kProfilerTimingDisabledValue); -#endif + if (useEmbeddedSwitches) { + // Inspired by the Android port's default switches + parsedCommandLine->AppendSwitch(switches::kEnableOverlayScrollbar); + parsedCommandLine->AppendSwitch(switches::kEnablePinch); + parsedCommandLine->AppendSwitch(switches::kEnableViewport); + parsedCommandLine->AppendSwitch(switches::kMainFrameResizesAreOrientationChanges); + parsedCommandLine->AppendSwitch(switches::kDisableAcceleratedVideoDecode); + parsedCommandLine->AppendSwitch(switches::kDisableGpuShaderDiskCache); + parsedCommandLine->AppendSwitch(switches::kDisable2dCanvasAntialiasing); + parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing); + parsedCommandLine->AppendSwitchASCII(switches::kProfilerTiming, switches::kProfilerTimingDisabledValue); + } GLContextHelper::initialize(); @@ -260,13 +262,13 @@ WebEngineContext::WebEngineContext() contentMainParams.sandbox_info = &sandbox_info; #endif m_contentRunner->Initialize(contentMainParams); - m_browserRunner->Initialize(content::MainFunctionParams(*CommandLine::ForCurrentProcess())); + m_browserRunner->Initialize(content::MainFunctionParams(*base::CommandLine::ForCurrentProcess())); // Once the MessageLoop has been created, attach a top-level RunLoop. m_runLoop.reset(new base::RunLoop); m_runLoop->BeforeRun(); - m_devtools.reset(new DevToolsHttpHandlerDelegateQt); + m_devtools = createDevToolsHttpHandler(); // 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. diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index dea54ef8a..8f034f18f 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -41,6 +41,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "components/devtools_http_handler/devtools_http_handler.h" #include <QExplicitlySharedDataPointer> @@ -59,7 +61,6 @@ namespace QtWebEngineCore { class BrowserContextAdapter; class ContentMainDelegateQt; -class DevToolsHttpHandlerDelegateQt; class SurfaceFactoryQt; } // namespace @@ -84,7 +85,7 @@ private: scoped_ptr<content::BrowserMainRunner> m_browserRunner; QObject* m_globalQObject; QExplicitlySharedDataPointer<QtWebEngineCore::BrowserContextAdapter> m_defaultBrowserContext; - scoped_ptr<QtWebEngineCore::DevToolsHttpHandlerDelegateQt> m_devtools; + scoped_ptr<devtools_http_handler::DevToolsHttpHandler> 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 980e9a39a..bc030d8f7 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -162,7 +162,6 @@ QString pluginsPath() if (!initialized) { initialized = true; - const QStringList directories = QCoreApplication::libraryPaths(); Q_FOREACH (const QString &dir, directories) { const QString candidate = dir % "/" % QLatin1String("qtwebengine"); @@ -173,7 +172,6 @@ QString pluginsPath() } if (pluginsPath.isEmpty()) { - qWarning("Qt WebEngine Plugins directory not found. Trying fallback directory... Plugins as for example video codecs MAY NOT work."); pluginsPath = fallbackDir(); } } @@ -276,7 +274,7 @@ base::string16 WebEngineLibraryInfo::getApplicationName() std::string WebEngineLibraryInfo::getApplicationLocale() { - CommandLine *parsedCommandLine = CommandLine::ForCurrentProcess(); + base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); if (!parsedCommandLine->HasSwitch(switches::kLang)) return QLocale().bcp47Name().toStdString(); diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 74c60b778..19558980b 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -213,6 +213,8 @@ void WebEngineSettings::initDefaults(bool offTheRecord) m_attributes.insert(HyperlinkAuditingEnabled, false); m_attributes.insert(ScrollAnimatorEnabled, false); m_attributes.insert(ErrorPageEnabled, true); + m_attributes.insert(PluginsEnabled, false); + m_attributes.insert(FullScreenSupportEnabled, false); // Default fonts QFont defaultFont; @@ -277,6 +279,8 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p prefs->hyperlink_auditing_enabled = testAttribute(HyperlinkAuditingEnabled); prefs->enable_scroll_animator = testAttribute(ScrollAnimatorEnabled); prefs->enable_error_page = testAttribute(ErrorPageEnabled); + prefs->plugins_enabled = testAttribute(PluginsEnabled); + prefs->fullscreen_supported = testAttribute(FullScreenSupportEnabled); // Fonts settings. prefs->standard_font_family_map[content::kCommonScript] = toString16(fontFamily(StandardFont)); diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index e9d8010a8..29ef079b7 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -71,6 +71,8 @@ public: HyperlinkAuditingEnabled, ScrollAnimatorEnabled, ErrorPageEnabled, + PluginsEnabled, + FullScreenSupportEnabled, }; // Must match the values from the public API in qwebenginesettings.h. diff --git a/src/core/yuv_video_node.cpp b/src/core/yuv_video_node.cpp index 23528c8ec..815ea7d51 100644 --- a/src/core/yuv_video_node.cpp +++ b/src/core/yuv_video_node.cpp @@ -61,12 +61,16 @@ protected: "attribute highp vec4 a_position;\n" "attribute mediump vec2 a_texCoord;\n" "uniform highp mat4 matrix;\n" - "varying mediump vec2 v_texCoord;\n" - "uniform mediump vec2 texScale;\n" - "uniform mediump vec2 texOffset;\n" + "varying mediump vec2 v_yaTexCoord;\n" + "varying mediump vec2 v_uvTexCoord;\n" + "uniform mediump vec2 yaTexScale;\n" + "uniform mediump vec2 yaTexOffset;\n" + "uniform mediump vec2 uvTexScale;\n" + "uniform mediump vec2 uvTexOffset;\n" "void main() {\n" " gl_Position = matrix * a_position;\n" - " v_texCoord = a_texCoord * texScale + texOffset;\n" + " v_yaTexCoord = a_texCoord * yaTexScale + yaTexOffset;\n" + " v_uvTexCoord = a_texCoord * uvTexScale + uvTexOffset;\n" "}"; return shader; } @@ -74,19 +78,26 @@ protected: virtual const char *fragmentShader() const Q_DECL_OVERRIDE { // Keep in sync with cc::FragmentShaderYUVVideo static const char *shader = - "varying mediump vec2 v_texCoord;\n" + "varying mediump vec2 v_yaTexCoord;\n" + "varying mediump vec2 v_uvTexCoord;\n" "uniform sampler2D y_texture;\n" "uniform sampler2D u_texture;\n" "uniform sampler2D v_texture;\n" - "uniform lowp float alpha;\n" - "uniform lowp vec3 yuv_adj;\n" - "uniform lowp mat3 yuv_matrix;\n" + "uniform mediump float alpha;\n" + "uniform mediump vec3 yuv_adj;\n" + "uniform mediump mat3 yuv_matrix;\n" + "uniform mediump vec4 ya_clamp_rect;\n" + "uniform mediump vec4 uv_clamp_rect;\n" "void main() {\n" - " lowp float y_raw = texture2D(y_texture, v_texCoord).x;\n" - " lowp float u_unsigned = texture2D(u_texture, v_texCoord).x;\n" - " lowp float v_unsigned = texture2D(v_texture, v_texCoord).x;\n" - " lowp vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;\n" - " lowp vec3 rgb = yuv_matrix * yuv;\n" + " mediump vec2 ya_clamped =\n" + " max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));\n" + " mediump float y_raw = texture2D(y_texture, ya_clamped).x;\n" + " mediump vec2 uv_clamped =\n" + " max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));\n" + " mediump float u_unsigned = texture2D(u_texture, uv_clamped).x;\n" + " mediump float v_unsigned = texture2D(v_texture, uv_clamped).x;\n" + " mediump vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;\n" + " mediump vec3 rgb = yuv_matrix * yuv;\n" " gl_FragColor = vec4(rgb, 1.0) * alpha;\n" "}"; return shader; @@ -94,8 +105,12 @@ protected: virtual void initialize() Q_DECL_OVERRIDE { m_id_matrix = program()->uniformLocation("matrix"); - m_id_texScale = program()->uniformLocation("texScale"); - m_id_texOffset = program()->uniformLocation("texOffset"); + m_id_yaTexScale = program()->uniformLocation("yaTexScale"); + m_id_uvTexScale = program()->uniformLocation("uvTexScale"); + m_id_yaTexOffset = program()->uniformLocation("yaTexOffset"); + m_id_uvTexOffset = program()->uniformLocation("uvTexOffset"); + m_id_yaClampRect = program()->uniformLocation("ya_clamp_rect"); + m_id_uvClampRect = program()->uniformLocation("uv_clamp_rect"); m_id_yTexture = program()->uniformLocation("y_texture"); m_id_uTexture = program()->uniformLocation("u_texture"); m_id_vTexture = program()->uniformLocation("v_texture"); @@ -105,8 +120,12 @@ protected: } int m_id_matrix; - int m_id_texScale; - int m_id_texOffset; + int m_id_yaTexScale; + int m_id_uvTexScale; + int m_id_yaTexOffset; + int m_id_uvTexOffset; + int m_id_yaClampRect; + int m_id_uvClampRect; int m_id_yTexture; int m_id_uTexture; int m_id_vTexture; @@ -123,21 +142,28 @@ protected: virtual const char *fragmentShader() const Q_DECL_OVERRIDE { // Keep in sync with cc::FragmentShaderYUVAVideo static const char *shader = - "varying mediump vec2 v_texCoord;\n" + "varying mediump vec2 v_yaTexCoord;\n" + "varying mediump vec2 v_uvTexCoord;\n" "uniform sampler2D y_texture;\n" "uniform sampler2D u_texture;\n" "uniform sampler2D v_texture;\n" "uniform sampler2D a_texture;\n" - "uniform lowp float alpha;\n" - "uniform lowp vec3 yuv_adj;\n" - "uniform lowp mat3 yuv_matrix;\n" + "uniform mediump float alpha;\n" + "uniform mediump vec3 yuv_adj;\n" + "uniform mediump mat3 yuv_matrix;\n" + "uniform mediump vec4 ya_clamp_rect;\n" + "uniform mediump vec4 uv_clamp_rect;\n" "void main() {\n" - " lowp float y_raw = texture2D(y_texture, v_texCoord).x;\n" - " lowp float u_unsigned = texture2D(u_texture, v_texCoord).x;\n" - " lowp float v_unsigned = texture2D(v_texture, v_texCoord).x;\n" - " lowp float a_raw = texture2D(a_texture, v_texCoord).x;\n" - " lowp vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;\n" - " lowp vec3 rgb = yuv_matrix * yuv;\n" + " mediump vec2 ya_clamped =\n" + " max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));\n" + " mediump float y_raw = texture2D(y_texture, ya_clamped).x;\n" + " mediump vec2 uv_clamped =\n" + " max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));\n" + " mediump float u_unsigned = texture2D(u_texture, uv_clamped).x;\n" + " mediump float v_unsigned = texture2D(v_texture, uv_clamped).x;\n" + " mediump float a_raw = texture2D(a_texture, ya_clamped).x;\n" + " mediump vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;\n" + " mediump vec3 rgb = yuv_matrix * yuv;\n" " gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);\n" "}"; return shader; @@ -156,6 +182,8 @@ void YUVVideoMaterialShader::updateState(const RenderState &state, QSGMaterial * { Q_UNUSED(oldMaterial); + // Keep logic in sync with logic in GLRenderer::DrawYUVVideoQuad: + YUVVideoMaterial *mat = static_cast<YUVVideoMaterial *>(newMaterial); program()->setUniformValue(m_id_yTexture, 0); program()->setUniformValue(m_id_uTexture, 1); @@ -170,18 +198,47 @@ void YUVVideoMaterialShader::updateState(const RenderState &state, QSGMaterial * glFuncs.glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit mat->m_yTexture->bind(); - program()->setUniformValue(m_id_texOffset, mat->m_texCoordRect.topLeft()); - program()->setUniformValue(m_id_texScale, mat->m_texCoordRect.size()); + const QSizeF yaSizeScale(1.0f / mat->m_yaTexSize.width(), 1.0f / mat->m_yaTexSize.height()); + const QSizeF uvSizeScale(1.0f / mat->m_uvTexSize.width(), 1.0f / mat->m_uvTexSize.height()); + + const QPointF yaTexOffset(mat->m_yaTexCoordRect.left() * yaSizeScale.width(), mat->m_yaTexCoordRect.top() * yaSizeScale.height()); + const QPointF uvTexOffset(mat->m_uvTexCoordRect.left() * uvSizeScale.width(), mat->m_uvTexCoordRect.top() * uvSizeScale.height()); + const QSizeF yaTexScale(mat->m_yaTexCoordRect.width() * yaSizeScale.width(), mat->m_yaTexCoordRect.height() * yaSizeScale.height()); + const QSizeF uvTexScale(mat->m_uvTexCoordRect.width() * uvSizeScale.width(), mat->m_uvTexCoordRect.height() * uvSizeScale.height()); + program()->setUniformValue(m_id_yaTexOffset, yaTexOffset); + program()->setUniformValue(m_id_uvTexOffset, uvTexOffset); + program()->setUniformValue(m_id_yaTexScale, yaTexScale); + program()->setUniformValue(m_id_uvTexScale, uvTexScale); + QRectF yaClampRect(yaTexOffset, yaTexScale); + QRectF uvClampRect(uvTexOffset, uvTexScale); + yaClampRect = yaClampRect.marginsRemoved(QMarginsF(yaSizeScale.width() * 0.5f, yaSizeScale.height() * 0.5f, + yaSizeScale.width() * 0.5f, yaSizeScale.height() * 0.5f)); + uvClampRect = uvClampRect.marginsRemoved(QMarginsF(uvSizeScale.width() * 0.5f, uvSizeScale.height() * 0.5f, + uvSizeScale.width() * 0.5f, uvSizeScale.height() * 0.5f)); + + const QVector4D yaClampV(yaClampRect.left(), yaClampRect.top(), yaClampRect.right(), yaClampRect.bottom()); + const QVector4D uvClampV(uvClampRect.left(), uvClampRect.top(), uvClampRect.right(), uvClampRect.bottom()); + program()->setUniformValue(m_id_yaClampRect, yaClampV); + program()->setUniformValue(m_id_uvClampRect, uvClampV); // These values are magic numbers that are used in the transformation from YUV // to RGB color values. They are taken from the following webpage: // http://www.fourcc.org/fccyvrgb.php - const float yuv_to_rgb[9] = { + const float yuv_to_rgb_rec601[9] = { 1.164f, 0.0f, 1.596f, 1.164f, -.391f, -.813f, 1.164f, 2.018f, 0.0f, }; - const QMatrix3x3 yuvMatrix(yuv_to_rgb); + const float yuv_to_rgb_rec709[9] = { + 1.164f, 0.0f, 1.793f, + 1.164f, -0.213f, -0.533f, + 1.164f, 2.112f, 0.0f, + }; + const float yuv_to_rgb_jpeg[9] = { + 1.f, 0.0f, 1.402f, + 1.f, -.34414f, -.71414f, + 1.f, 1.772f, 0.0f, + }; // These values map to 16, 128, and 128 respectively, and are computed // as a fraction over 256 (e.g. 16 / 256 = 0.0625). @@ -189,9 +246,35 @@ void YUVVideoMaterialShader::updateState(const RenderState &state, QSGMaterial * // Y - 16 : Gives 16 values of head and footroom for overshooting // U - 128 : Turns unsigned U into signed U [-128,127] // V - 128 : Turns unsigned V into signed V [-128,127] - const QVector3D yuvAdjust(-0.0625f, -0.5f, -0.5f); - program()->setUniformValue(m_id_yuvMatrix, yuvMatrix); - program()->setUniformValue(m_id_yuvAdjust, yuvAdjust); + const float yuv_adjust_constrained[3] = { + -0.0625f, -0.5f, -0.5f, + }; + + // Same as above, but without the head and footroom. + const float yuv_adjust_full[3] = { + 0.0f, -0.5f, -0.5f, + }; + + const float *yuv_to_rgb = 0; + const float *yuv_adjust = 0; + + switch (mat->m_colorSpace) { + case YUVVideoMaterial::REC_601: + yuv_to_rgb = yuv_to_rgb_rec601; + yuv_adjust = yuv_adjust_constrained; + break; + case YUVVideoMaterial::REC_709: + yuv_to_rgb = yuv_to_rgb_rec709; + yuv_adjust = yuv_adjust_constrained; + break; + case YUVVideoMaterial::JPEG: + yuv_to_rgb = yuv_to_rgb_jpeg; + yuv_adjust = yuv_adjust_full; + break; + } + + program()->setUniformValue(m_id_yuvMatrix, QMatrix3x3(yuv_to_rgb)); + program()->setUniformValue(m_id_yuvAdjust, QVector3D(yuv_adjust[0], yuv_adjust[1], yuv_adjust[2])); if (state.isOpacityDirty()) program()->setUniformValue(m_id_opacity, state.opacity()); @@ -217,11 +300,17 @@ void YUVAVideoMaterialShader::updateState(const RenderState &state, QSGMaterial } -YUVVideoMaterial::YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, const QRectF &texCoordRect) +YUVVideoMaterial::YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, + const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, + YUVVideoMaterial::ColorSpace colorspace) : m_yTexture(yTexture) , m_uTexture(uTexture) , m_vTexture(vTexture) - , m_texCoordRect(texCoordRect) + , m_yaTexCoordRect(yaTexCoordRect) + , m_uvTexCoordRect(uvTexCoordRect) + , m_yaTexSize(yaTexSize) + , m_uvTexSize(uvTexSize) + , m_colorSpace(colorspace) { } @@ -240,8 +329,10 @@ int YUVVideoMaterial::compare(const QSGMaterial *other) const return m_vTexture->textureId() - m->m_vTexture->textureId(); } -YUVAVideoMaterial::YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, const QRectF &texCoordRect) - : YUVVideoMaterial(yTexture, uTexture, vTexture, texCoordRect) +YUVAVideoMaterial::YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, + const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, + YUVVideoMaterial::ColorSpace colorspace) + : YUVVideoMaterial(yTexture, uTexture, vTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace) , m_aTexture(aTexture) { setFlag(Blending, aTexture); @@ -260,15 +351,17 @@ int YUVAVideoMaterial::compare(const QSGMaterial *other) const return (m_aTexture ? m_aTexture->textureId() : 0) - (m->m_aTexture ? m->m_aTexture->textureId() : 0); } -YUVVideoNode::YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, const QRectF &texCoordRect) +YUVVideoNode::YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, + const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, + YUVVideoMaterial::ColorSpace colorspace) : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) { setGeometry(&m_geometry); setFlag(QSGNode::OwnsMaterial); if (aTexture) - m_material = new YUVAVideoMaterial(yTexture, uTexture, vTexture, aTexture, texCoordRect); + m_material = new YUVAVideoMaterial(yTexture, uTexture, vTexture, aTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace); else - m_material = new YUVVideoMaterial(yTexture, uTexture, vTexture, texCoordRect); + m_material = new YUVVideoMaterial(yTexture, uTexture, vTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace); setMaterial(m_material); } diff --git a/src/core/yuv_video_node.h b/src/core/yuv_video_node.h index f96df56ce..457c2c7fe 100644 --- a/src/core/yuv_video_node.h +++ b/src/core/yuv_video_node.h @@ -50,7 +50,14 @@ QT_END_NAMESPACE class YUVVideoMaterial : public QSGMaterial { public: - YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, const QRectF &texCoordRect); + enum ColorSpace { + REC_601, // SDTV standard with restricted "studio swing" color range. + REC_709, // HDTV standard with restricted "studio swing" color range. + JPEG // Full color range [0, 255] JPEG color space. + }; + YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, + const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, + ColorSpace colorspace); virtual QSGMaterialType *type() const Q_DECL_OVERRIDE { static QSGMaterialType theType; @@ -63,13 +70,20 @@ public: QSGTexture *m_yTexture; QSGTexture *m_uTexture; QSGTexture *m_vTexture; - QRectF m_texCoordRect; + QRectF m_yaTexCoordRect; + QRectF m_uvTexCoordRect; + QSizeF m_yaTexSize; + QSizeF m_uvTexSize; + ColorSpace m_colorSpace; + }; class YUVAVideoMaterial : public YUVVideoMaterial { public: - YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, const QRectF &texCoordRect); + YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, + const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, + ColorSpace colorspace); virtual QSGMaterialType *type() const Q_DECL_OVERRIDE{ static QSGMaterialType theType; @@ -85,7 +99,9 @@ public: class YUVVideoNode : public QSGGeometryNode { public: - YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, const QRectF &texCoordRect); + YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture, + const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize, + YUVVideoMaterial::ColorSpace colorspace); void setRect(const QRectF &rect); private: |