diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 605a6dc3bd0458df9a4ad6b730554b487cd6ee46..d72b27229854d5a9e984ae67202578f26212c4c3 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -35,6 +35,10 @@ HEADERS = \ qtwebenginecoreglobal_p.h \ qwebenginecookiestoreclient.h \ qwebenginecookiestoreclient_p.h \ + qwebengineurlrequestinterceptor.h \ + qwebengineurlrequestinfo.h \ + qwebengineurlrequestinfo_p.h SOURCES = \ qwebenginecookiestoreclient.cpp \ + qwebengineurlrequestinfo.cpp diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e97b0c7b92f0b73857ec485ad60ece937706a46a --- /dev/null +++ b/src/core/api/qwebengineurlrequestinfo.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** 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) + +QWebEngineUrlRequestInfoPrivate::QWebEngineUrlRequestInfoPrivate(QWebEngineUrlRequestInfo::ResourceType resource, QWebEngineUrlRequestInfo::NavigationType navigation, const QUrl &u, const QByteArray &m) + : resourceType(resource) + , navigationType(navigation) + , shouldBlockRequest(false) + , url(u) + , method(m) +{ +} + +QWebEngineUrlRequestInfo::~QWebEngineUrlRequestInfo() +{ + +} + +QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPrivate *p) + : d_ptr(p) +{ + d_ptr->q_ptr = this; +} + +QWebEngineUrlRequestInfo::ResourceType QWebEngineUrlRequestInfo::resourceType() const +{ + Q_D(const QWebEngineUrlRequestInfo); + return d->resourceType; +} + +QWebEngineUrlRequestInfo::NavigationType QWebEngineUrlRequestInfo::navigationType() const +{ + Q_D(const QWebEngineUrlRequestInfo); + return d->navigationType; +} + +const QUrl &QWebEngineUrlRequestInfo::url() const +{ + Q_D(const QWebEngineUrlRequestInfo); + return d->url; +} + +const QByteArray &QWebEngineUrlRequestInfo::method() const +{ + Q_D(const QWebEngineUrlRequestInfo); + return d->method; +} + +void QWebEngineUrlRequestInfo::redirectTo(const QUrl &url) +{ + Q_D(QWebEngineUrlRequestInfo); + d->url = url; +} + +void QWebEngineUrlRequestInfo::blockRequest(bool shouldBlock) +{ + Q_D(QWebEngineUrlRequestInfo); + d->shouldBlockRequest = shouldBlock; +} + +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 0000000000000000000000000000000000000000..8ef787995c8de05b9e118020a29dd2c34bbb177e --- /dev/null +++ b/src/core/api/qwebengineurlrequestinfo.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 QWEBENGINEURLREQUESTINFO_H +#define QWEBENGINEURLREQUESTINFO_H + +#include "qtwebenginecoreglobal.h" + +#include <QScopedPointer> +#include <QUrl> + +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; + + const QUrl &url() const; + const QByteArray &method() const; + + void blockRequest(bool shouldBlock); + void redirectTo(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 0000000000000000000000000000000000000000..b6a304a039cecf2b1f418785def2d085180d1bef --- /dev/null +++ b/src/core/api/qwebengineurlrequestinfo_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 QByteArray &m); + + QWebEngineUrlRequestInfo::ResourceType resourceType; + QWebEngineUrlRequestInfo::NavigationType navigationType; + bool shouldBlockRequest; + + QUrl url; + 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 0000000000000000000000000000000000000000..a38a697af3dbe1bbb47d5f82b496ff10990ee989 --- /dev/null +++ b/src/core/api/qwebengineurlrequestinterceptor.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 <QByteArray> +#include <QHash> +#include <QObject> +#include <QUrl> + +QT_BEGIN_NAMESPACE + +class QWEBENGINE_EXPORT QWebEngineUrlRequestInterceptor : public QObject +{ + Q_OBJECT +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/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp index 4c5e7fdc177914174862127237b1e7c22ecb85d0..fdb410e66e1e226c73c4f8a257eda697bbe246b6 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/browser_context_adapter.cpp @@ -145,6 +145,16 @@ void BrowserContextAdapter::setCookieStoreClient(QWebEngineCookieStoreClient *cl m_browserContext->url_request_getter_->updateStorageSettings(); } +QWebEngineUrlRequestInterceptor *BrowserContextAdapter::requestInterceptor() +{ + return m_requestInterceptor.data(); +} + +void BrowserContextAdapter::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) +{ + m_requestInterceptor = interceptor; +} + void BrowserContextAdapter::addClient(BrowserContextAdapterClient *adapterClient) { m_clients.append(adapterClient); diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h index 717450184f4a855515252e71591808873b9d73a6..d8609108ccf22b4725b4d79ab45f1515796de5f6 100644 --- a/src/core/browser_context_adapter.h +++ b/src/core/browser_context_adapter.h @@ -47,6 +47,7 @@ #include <QVector> #include "api/qwebenginecookiestoreclient.h" +#include "api/qwebengineurlrequestinterceptor.h" QT_FORWARD_DECLARE_CLASS(QObject) @@ -75,6 +76,9 @@ public: QWebEngineCookieStoreClient *cookieStoreClient(); void setCookieStoreClient(QWebEngineCookieStoreClient *client); + QWebEngineUrlRequestInterceptor* requestInterceptor(); + void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); + QList<BrowserContextAdapterClient*> clients() { return m_clients; } void addClient(BrowserContextAdapterClient *adapterClient); void removeClient(BrowserContextAdapterClient *adapterClient); @@ -155,6 +159,7 @@ private: QScopedPointer<DownloadManagerDelegateQt> m_downloadManagerDelegate; QScopedPointer<UserScriptControllerHost> m_userScriptController; QPointer<QWebEngineCookieStoreClient> m_cookieStoreClient; + QPointer<QWebEngineUrlRequestInterceptor> m_requestInterceptor; QString m_dataPath; QString m_cachePath; diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp index 0d1b2b558019cdb844ee86b35b7e588cfc8f50e8..5af781007b5ce0af86a29ef7fbaed881dc81a17e 100644 --- a/src/core/network_delegate_qt.cpp +++ b/src/core/network_delegate_qt.cpp @@ -36,31 +36,37 @@ #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" namespace QtWebEngineCore { -int pageTransitionToNavigationType(ui::PageTransition transition) +static int pageTransitionToNavigationType(ui::PageTransition transition) { int32 qualifier = ui::PageTransitionGetQualifier(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,68 @@ 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 + , 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 diff --git a/src/core/network_delegate_qt.h b/src/core/network_delegate_qt.h index 7fbaf8c5aea3cd75d5ee8e7f8af6c96498b48b48..1176f99d96c26fa7b368605e1d050f400f860597 100644 --- a/src/core/network_delegate_qt.h +++ b/src/core/network_delegate_qt.h @@ -45,10 +45,13 @@ namespace QtWebEngineCore { +class URLRequestContextGetterQt; class NetworkDelegateQt : public net::NetworkDelegate { QSet<net::URLRequest *> m_activeRequests; + URLRequestContextGetterQt *m_requestContextGetter; public: + NetworkDelegateQt(URLRequestContextGetterQt *requestContext); struct RequestParams { QUrl url; diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index caad543ff7c022a76854107a3274438d7686e568..7db1fa0947e6636c7bf1421126fb3204afb04d33 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -99,7 +99,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(); diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h index 78fb5a1abd51b58452c9b130f4fbdbb841b1a446..be9567f4bb4ede4558fdc08dac01357487bc8e11 100644 --- a/src/core/url_request_context_getter_qt.h +++ b/src/core/url_request_context_getter_qt.h @@ -49,13 +49,13 @@ #include "net/url_request/url_request_job_factory_impl.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; } @@ -94,11 +94,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_refptr<CookieMonsterDelegateQt> m_cookieDelegate; + friend class NetworkDelegateQt; }; } // namespace QtWebEngineCore diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 210704148c2e5d1b021c4f862e85516857632764..999fc881c437d0764439a80c02e3afc9c40b1a50 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -480,6 +480,7 @@ 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); } diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 20a5ad7af9714320e33ec748af2290454a73fd6e..86b5d1b79f81cfaca8b73f84b360194b2d7fe198 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -157,7 +157,7 @@ public: }; enum NavigationType { - LinkClickedNavigation, + LinkNavigation, TypedNavigation, FormSubmittedNavigation, BackForwardNavigation, diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index afe2277f2fe2c9044f611b068e930f763b266350..b73355ac20933deffefc9fab6835a64d637f0ea5 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -416,6 +416,12 @@ void QWebEngineProfile::setCookieStoreClient(QWebEngineCookieStoreClient *client d->browserContext()->setCookieStoreClient(client); } +void QWebEngineProfile::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) +{ + Q_D(QWebEngineProfile); + d->browserContext()->setRequestInterceptor(interceptor); +} + /*! Clears all links from the visited links database. diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h index b13f3d631ce4dd6128a2cf35d4ec7a940dce4f04..c90ea01e5ec89d7612d6730656061643f85cab47 100644 --- a/src/webenginewidgets/api/qwebengineprofile.h +++ b/src/webenginewidgets/api/qwebengineprofile.h @@ -54,6 +54,7 @@ class QWebEnginePagePrivate; class QWebEngineProfilePrivate; class QWebEngineSettings; class QWebEngineScriptCollection; +class QWebEngineUrlRequestInterceptor; class QWEBENGINEWIDGETS_EXPORT QWebEngineProfile : public QObject { Q_OBJECT @@ -96,6 +97,7 @@ public: QWebEngineCookieStoreClient* cookieStoreClient(); void setCookieStoreClient(QWebEngineCookieStoreClient *client); + void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); void clearAllVisitedLinks(); void clearVisitedLinks(const QList<QUrl> &urls); diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro index c727bc9ccefa28d17b190bebf26b5baa290b7a55..ed0a6153215a612d2dc7ed4ba1c3f5d844e91078 100644 --- a/tests/auto/core/core.pro +++ b/tests/auto/core/core.pro @@ -4,3 +4,4 @@ CONFIG += ordered SUBDIRS += \ qwebenginecookiestoreclient \ + qwebengineurlrequestinterceptor \ diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/qwebengineurlrequestinterceptor.pro b/tests/auto/core/qwebengineurlrequestinterceptor/qwebengineurlrequestinterceptor.pro new file mode 100644 index 0000000000000000000000000000000000000000..ff6c4962896e4c056799ef1640cb1560781caa5b --- /dev/null +++ b/tests/auto/core/qwebengineurlrequestinterceptor/qwebengineurlrequestinterceptor.pro @@ -0,0 +1,2 @@ +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/content.html b/tests/auto/core/qwebengineurlrequestinterceptor/resources/content.html new file mode 100644 index 0000000000000000000000000000000000000000..360ad65ef89a97a0bea572f629b28a9a5abb7b19 --- /dev/null +++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/content.html @@ -0,0 +1,5 @@ +<html> +<body> +<a>This is test content</a> +</body> +</html> diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/index.html b/tests/auto/core/qwebengineurlrequestinterceptor/resources/index.html new file mode 100644 index 0000000000000000000000000000000000000000..a744dbd998c27ee512017e5bd044b33b98c20fcf --- /dev/null +++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/index.html @@ -0,0 +1,16 @@ +<html> + <head> + <script type="text/javascript"> + function post() { + var form = document.createElement("form"); + form.setAttribute("method", "POST"); + document.body.appendChild(form); + form.submit(); + return true; + } +</script> + </head> + <body> + <h1>Test page</h1> + </body> +</html> diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0ef9a1baea488b78a2a77a8699f4fdbf2f50f01 --- /dev/null +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** 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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../../widgets/util.h" +#include <QtTest/QtTest> +#include <QtWebEngineCore/qwebengineurlrequestinterceptor.h> +#include <QtWebEngineWidgets/qwebenginepage.h> +#include <QtWebEngineWidgets/qwebengineprofile.h> +#include <QtWebEngineWidgets/qwebengineview.h> + +class tst_QWebEngineUrlRequestInterceptor : public QObject +{ + Q_OBJECT + +public: + tst_QWebEngineUrlRequestInterceptor(); + ~tst_QWebEngineUrlRequestInterceptor(); + +public Q_SLOTS: + void init(); + void cleanup(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void interceptRequest(); +}; + +tst_QWebEngineUrlRequestInterceptor::tst_QWebEngineUrlRequestInterceptor() +{ +} + +tst_QWebEngineUrlRequestInterceptor::~tst_QWebEngineUrlRequestInterceptor() +{ +} + +void tst_QWebEngineUrlRequestInterceptor::init() +{ +} + +void tst_QWebEngineUrlRequestInterceptor::cleanup() +{ +} + +void tst_QWebEngineUrlRequestInterceptor::initTestCase() +{ +} + +void tst_QWebEngineUrlRequestInterceptor::cleanupTestCase() +{ +} + +class TestRequestInterceptor: public QWebEngineUrlRequestInterceptor +{ +public: + QList<QUrl> observedUrls; + bool shouldIntercept; + + bool interceptRequest(QWebEngineUrlRequestInfo &info) override + { + info.blockRequest(info.method() != QByteArrayLiteral("GET")); + if (info.url().toString().endsWith(QLatin1String("__placeholder__"))) + info.redirectTo(QUrl("qrc:///resources/content.html")); + + observedUrls.append(info.url()); + return shouldIntercept; + } + TestRequestInterceptor(bool intercept) + : shouldIntercept(intercept) + { + } +}; + +void tst_QWebEngineUrlRequestInterceptor::interceptRequest() +{ + QWebEngineView view; + TestRequestInterceptor interceptor(/* intercept */ true); + + QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool))); + view.page()->profile()->setRequestInterceptor(&interceptor); + view.load(QUrl("qrc:///resources/index.html")); + QTRY_COMPARE(loadSpy.count(), 1); + QVariant success = loadSpy.takeFirst().takeFirst(); + QVERIFY(success.toBool()); + loadSpy.clear(); + QVariant ok; + + view.page()->runJavaScript("post();", [&ok](const QVariant result){ ok = result; }); + QTRY_VERIFY(ok.toBool()); + QTRY_COMPARE(loadSpy.count(), 1); + success = loadSpy.takeFirst().takeFirst(); + // We block non-GET requests, so this should not succeed. + QVERIFY(!success.toBool()); + loadSpy.clear(); + + view.load(QUrl("qrc:///resources/__placeholder__")); + QTRY_COMPARE(loadSpy.count(), 1); + success = loadSpy.takeFirst().takeFirst(); + // The redirection for __placeholder__ should succeed. + QVERIFY(success.toBool()); + loadSpy.clear(); + QCOMPARE(interceptor.observedUrls.count(), 4); + + + // Make sure that registering an observer does not modify the request. + TestRequestInterceptor observer(/* intercept */ false); + view.page()->profile()->setRequestInterceptor(&observer); + view.load(QUrl("qrc:///resources/__placeholder__")); + QTRY_COMPARE(loadSpy.count(), 1); + success = loadSpy.takeFirst().takeFirst(); + // Since we do not intercept, loading an invalid path should not succeed. + QVERIFY(!success.toBool()); + QCOMPARE(observer.observedUrls.count(), 1); +} + +QTEST_MAIN(tst_QWebEngineUrlRequestInterceptor) +#include "tst_qwebengineurlrequestinterceptor.moc" diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc new file mode 100644 index 0000000000000000000000000000000000000000..afeae268ba0fb99221a7097e534343eba4b8d750 --- /dev/null +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>resources/index.html</file> + <file>resources/content.html</file> +</qresource> +</RCC>