summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@theqtcompany.com>2015-07-10 17:27:45 +0200
committerAndras Becsi <andras.becsi@theqtcompany.com>2015-08-03 20:46:55 +0000
commite11cd75ff506e8dcbfc990d70baeec821f1f0563 (patch)
treedb4e58d9b0c66656e5eccb368dd61cdb36034c75
parent853d5867644fd53f2d779c3c7b39a34803a3e566 (diff)
Add API for intercepting url requests
This patch is adding a QWebEngineUrlRequestInterceptor interface that can be subclassed to observe or intercept all resource requests making it possible to implement browser features like adblocking and setting custom request headers for url requests. The interceptRequest virtual function is executed on the IO thread. This patch also includes a unit test for the testable API parts. Change-Id: Ibe740fc55551a9a5da40794088ccb6d03d913631 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com> Reviewed-by: Martin Rotter <rotter.martinos@gmail.com> Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
-rw-r--r--src/core/api/core_api.pro4
-rw-r--r--src/core/api/qwebengineurlrequestinfo.cpp133
-rw-r--r--src/core/api/qwebengineurlrequestinfo.h107
-rw-r--r--src/core/api/qwebengineurlrequestinfo_p.h76
-rw-r--r--src/core/api/qwebengineurlrequestinterceptor.h67
-rw-r--r--src/core/browser_context_adapter.cpp10
-rw-r--r--src/core/browser_context_adapter.h5
-rw-r--r--src/core/network_delegate_qt.cpp71
-rw-r--r--src/core/network_delegate_qt.h3
-rw-r--r--src/core/url_request_context_getter_qt.cpp2
-rw-r--r--src/core/url_request_context_getter_qt.h5
-rw-r--r--src/core/web_contents_adapter.cpp1
-rw-r--r--src/core/web_contents_adapter_client.h2
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp6
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.h2
-rw-r--r--tests/auto/core/core.pro1
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/qwebengineurlrequestinterceptor.pro2
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/resources/content.html5
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/resources/index.html16
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp155
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc6
21 files changed, 662 insertions, 17 deletions
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index 605a6dc3b..d72b27229 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 000000000..e97b0c7b9
--- /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 000000000..8ef787995
--- /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 000000000..b6a304a03
--- /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 000000000..a38a697af
--- /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 4c5e7fdc1..fdb410e66 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 717450184..d8609108c 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 0d1b2b558..5af781007 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 7fbaf8c5a..1176f99d9 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 caad543ff..7db1fa094 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 78fb5a1ab..be9567f4b 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 210704148..999fc881c 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 20a5ad7af..86b5d1b79 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 afe2277f2..b73355ac2 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 b13f3d631..c90ea01e5 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 c727bc9cc..ed0a61532 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 000000000..ff6c49628
--- /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 000000000..360ad65ef
--- /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 000000000..a744dbd99
--- /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 000000000..b0ef9a1ba
--- /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 000000000..afeae268b
--- /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>