summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-07-24 09:41:25 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-17 12:34:30 +0000
commit17bd9d9de2d424ef7f7a193e17d1619d6effec7b (patch)
tree049a423c6a2f091e1d0f9e2c8a2531ebbd9412fc
parent0b1025b8aea4aa0336671f7e908287d65490d120 (diff)
Add setRequestInterceptor to QWebEnginePage
Makes it possible to make page specific intercepts, and is at the same time safer by running in the UI-thread. [ChangeLog][QtWebEngineWidgets][QWebEnginePage] Added setRequestInterceptor, similar to the same call on profile except it operates on a per-page basis and on the UI-thread. Change-Id: Id5a7173156c25d0f030f00b6ef314d283c7c8cdd Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io>
-rw-r--r--src/core/api/qwebengineurlrequestinfo.cpp24
-rw-r--r--src/core/api/qwebengineurlrequestinfo.h5
-rw-r--r--src/core/net/network_delegate_qt.cpp118
-rw-r--r--src/core/profile_adapter.cpp18
-rw-r--r--src/core/profile_adapter.h5
-rw-r--r--src/core/profile_io_data_qt.cpp8
-rw-r--r--src/core/profile_io_data_qt.h2
-rw-r--r--src/core/web_contents_adapter_client.h2
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp37
-rw-r--r--src/webenginewidgets/api/qwebenginepage.h3
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h2
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.h1
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp31
13 files changed, 204 insertions, 52 deletions
diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp
index 2bb870071..79bfb5412 100644
--- a/src/core/api/qwebengineurlrequestinfo.cpp
+++ b/src/core/api/qwebengineurlrequestinfo.cpp
@@ -115,8 +115,11 @@ ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::OtherNavigation, Q
\fn void QWebEngineUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
Reimplementing this virtual function makes it possible to intercept URL
- requests. This function is executed on the IO thread, and therefore running
- long tasks here will block networking.
+ requests. For interceptors installed on a QWebEngineProfile, the function is executed
+ on the I/O thread, and thus it may not be thread-safe to interact with pages. If the
+ interceptor was installed on a QWebEnginePage, the function is executed on the main
+ application thread, and can safely interact with other user classes. Both versions will
+ be stalling the URL request until handled.
\a info contains the information about the URL request and will track internally
whether its members have been altered.
@@ -137,10 +140,17 @@ QWebEngineUrlRequestInfoPrivate::QWebEngineUrlRequestInfoPrivate(QWebEngineUrlRe
/*!
\internal
*/
+QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfo &&p)
+ : d_ptr(p.d_ptr.take())
+{
+}
+
+/*!
+ \internal
+*/
QWebEngineUrlRequestInfo::~QWebEngineUrlRequestInfo()
{
-
}
/*!
@@ -257,6 +267,14 @@ bool QWebEngineUrlRequestInfo::changed() const
}
/*!
+ \internal
+*/
+void QWebEngineUrlRequestInfo::resetChanged()
+{
+ d_ptr->changed = false;
+}
+
+/*!
Redirects this request to \a url.
It is only possible to redirect requests that do not have payload data, such as GET requests.
*/
diff --git a/src/core/api/qwebengineurlrequestinfo.h b/src/core/api/qwebengineurlrequestinfo.h
index 68c46dcf4..e1f9ca6ef 100644
--- a/src/core/api/qwebengineurlrequestinfo.h
+++ b/src/core/api/qwebengineurlrequestinfo.h
@@ -47,6 +47,7 @@
namespace QtWebEngineCore {
class NetworkDelegateQt;
+class URLRequestNotification;
}
QT_BEGIN_NAMESPACE
@@ -104,10 +105,14 @@ public:
private:
friend class QtWebEngineCore::NetworkDelegateQt;
+ friend class QtWebEngineCore::URLRequestNotification;
Q_DISABLE_COPY(QWebEngineUrlRequestInfo)
Q_DECLARE_PRIVATE(QWebEngineUrlRequestInfo)
+ void resetChanged();
+
QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPrivate *p);
+ QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfo &&p);
~QWebEngineUrlRequestInfo();
QScopedPointer<QWebEngineUrlRequestInfoPrivate> d_ptr;
};
diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp
index ccc8cc0e5..8cf974d17 100644
--- a/src/core/net/network_delegate_qt.cpp
+++ b/src/core/net/network_delegate_qt.cpp
@@ -40,6 +40,7 @@
#include "network_delegate_qt.h"
#include "profile_adapter.h"
+
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_request_info.h"
@@ -80,16 +81,19 @@ WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::Page
}
}
-namespace {
-
-QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType)
+static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType)
{
if (resourceType >= 0 && resourceType < content::ResourceType(QWebEngineUrlRequestInfo::ResourceTypeLast))
return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType);
return QWebEngineUrlRequestInfo::ResourceTypeUnknown;
}
-QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType)
+static content::ResourceType fromQt(QWebEngineUrlRequestInfo::ResourceType resourceType)
+{
+ return static_cast<content::ResourceType>(resourceType);
+}
+
+static QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType)
{
return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType);
}
@@ -98,16 +102,17 @@ QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::Navigati
class URLRequestNotification {
public:
URLRequestNotification(net::URLRequest *request,
- const QUrl &url,
bool isMainFrameRequest,
- int navigationType,
- int frameTreeNodeId,
+ GURL *newUrl,
+ QWebEngineUrlRequestInfo &&requestInfo,
+ content::ResourceRequestInfo::WebContentsGetter webContentsGetter,
net::CompletionOnceCallback callback)
: m_request(request)
- , m_url(url)
, m_isMainFrameRequest(isMainFrameRequest)
- , m_navigationType(navigationType)
- , m_frameTreeNodeId(frameTreeNodeId)
+ , m_newUrl(newUrl)
+ , m_originalUrl(requestInfo.requestUrl())
+ , m_requestInfo(std::move(requestInfo))
+ , m_webContentsGetter(webContentsGetter)
, m_callback(std::move(callback))
{
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
@@ -147,25 +152,36 @@ private:
// May run concurrently with cancel() so no peeking at m_request here.
int error = net::OK;
- content::WebContents *webContents = content::WebContents::FromFrameTreeNodeId(m_frameTreeNodeId);
+ content::WebContents *webContents = m_webContentsGetter.Run();
+
if (webContents) {
- int navigationRequestAction = WebContentsAdapterClient::AcceptRequest;
WebContentsAdapterClient *client =
- WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client();
- client->navigationRequested(m_navigationType,
- m_url,
- navigationRequestAction,
- m_isMainFrameRequest);
- error = net::ERR_FAILED;
- switch (static_cast<WebContentsAdapterClient::NavigationRequestAction>(navigationRequestAction)) {
- case WebContentsAdapterClient::AcceptRequest:
- error = net::OK;
- break;
- case WebContentsAdapterClient::IgnoreRequest:
- error = net::ERR_ABORTED;
- break;
+ WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client();
+
+ client->interceptRequest(m_requestInfo);
+ if (m_requestInfo.changed()) {
+ error = m_requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
+ // We handle the rest of the changes later when we are back in I/O thread
+ }
+
+ // Only do navigationRequested on MAIN_FRAME and SUB_FRAME resources
+ if (error == net::OK && content::IsResourceTypeFrame(fromQt(m_requestInfo.resourceType()))) {
+ int navigationRequestAction = WebContentsAdapterClient::AcceptRequest;
+ client->navigationRequested(m_requestInfo.navigationType(),
+ m_requestInfo.requestUrl(),
+ navigationRequestAction,
+ m_isMainFrameRequest);
+ error = net::ERR_FAILED;
+ switch (static_cast<WebContentsAdapterClient::NavigationRequestAction>(navigationRequestAction)) {
+ case WebContentsAdapterClient::AcceptRequest:
+ error = net::OK;
+ break;
+ case WebContentsAdapterClient::IgnoreRequest:
+ error = net::ERR_ABORTED;
+ break;
+ }
+ DCHECK(error != net::ERR_FAILED);
}
- DCHECK(error != net::ERR_FAILED);
}
// Run the callback on the IO thread.
@@ -180,6 +196,17 @@ private:
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (m_request) {
+ if (m_requestInfo.changed()) {
+ if (m_originalUrl != m_requestInfo.d_ptr->url)
+ *m_newUrl = toGurl(m_requestInfo.d_ptr->url);
+
+ if (!m_requestInfo.d_ptr->extraHeaders.isEmpty()) {
+ auto end = m_requestInfo.d_ptr->extraHeaders.constEnd();
+ for (auto header = m_requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header)
+ m_request->SetExtraRequestHeaderByName(header.key().toStdString(), header.value().toStdString(), /* overwrite */ true);
+ }
+ }
+
if (m_request->status().status() != net::URLRequestStatus::CANCELED)
std::move(m_callback).Run(error);
m_request->RemoveUserData(UserData::key);
@@ -191,17 +218,16 @@ private:
~URLRequestNotification() {}
net::URLRequest *m_request;
- QUrl m_url;
bool m_isMainFrameRequest;
- int m_navigationType;
- int m_frameTreeNodeId;
+ GURL *m_newUrl;
+ const QUrl m_originalUrl;
+ QWebEngineUrlRequestInfo m_requestInfo;
+ content::ResourceRequestInfo::WebContentsGetter m_webContentsGetter;
net::CompletionOnceCallback m_callback;
};
const char URLRequestNotification::UserData::key[] = "QtWebEngineCore::URLRequestNotification";
-} // namespace
-
NetworkDelegateQt::NetworkDelegateQt(ProfileIODataQt *data)
: m_profileIOData(data)
{
@@ -211,7 +237,6 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::Complet
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
Q_ASSERT(m_profileIOData);
-
const content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request);
content::ResourceType resourceType = content::RESOURCE_TYPE_LAST_TYPE;
@@ -224,14 +249,14 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::Complet
const QUrl qUrl = toQt(request->url());
- QWebEngineUrlRequestInterceptor* interceptor = m_profileIOData->requestInterceptor();
- if (interceptor) {
- QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType),
- toQt(navigationType),
- qUrl,
- toQt(request->site_for_cookies()),
- QByteArray::fromStdString(request->method()));
- QWebEngineUrlRequestInfo requestInfo(infoPrivate);
+ QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType),
+ toQt(navigationType),
+ qUrl,
+ toQt(request->site_for_cookies()),
+ QByteArray::fromStdString(request->method()));
+ QWebEngineUrlRequestInfo requestInfo(infoPrivate);
+
+ if (QWebEngineUrlRequestInterceptor *interceptor = m_profileIOData->requestInterceptor()) {
interceptor->interceptRequest(requestInfo);
if (requestInfo.changed()) {
int result = infoPrivate->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
@@ -247,23 +272,24 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::Complet
if (result != net::OK)
return result;
+
+ requestInfo.resetChanged();
}
}
if (!resourceInfo)
return net::OK;
- int frameTreeNodeId = resourceInfo->GetFrameTreeNodeId();
- // Only intercept MAIN_FRAME and SUB_FRAME with an associated render frame.
- if (!content::IsResourceTypeFrame(resourceType) || frameTreeNodeId == -1)
+ if (!m_profileIOData->hasPageInterceptors() && !content::IsResourceTypeFrame(resourceType))
return net::OK;
+ auto webContentsGetter = resourceInfo->GetWebContentsGetterForRequest();
new URLRequestNotification(
request,
- qUrl,
resourceInfo->IsMainFrame(),
- navigationType,
- frameTreeNodeId,
+ newUrl,
+ std::move(requestInfo),
+ webContentsGetter,
std::move(callback)
);
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index 57bf3e752..54afc185d 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -82,6 +82,7 @@ ProfileAdapter::ProfileAdapter(const QString &storageName):
, m_persistentCookiesPolicy(AllowPersistentCookies)
, m_visitedLinksPolicy(TrackVisitedLinksOnDisk)
, m_httpCacheMaxSize(0)
+ , m_pageRequestInterceptors(0)
{
WebEngineContext::current()->addBrowserContext(this);
// creation of profile requires webengine context
@@ -98,6 +99,7 @@ ProfileAdapter::~ProfileAdapter()
m_profile->GetDownloadManager(m_profile.data())->Shutdown();
m_downloadManagerDelegate.reset();
}
+ Q_ASSERT(m_pageRequestInterceptors == 0);
}
void ProfileAdapter::setStorageName(const QString &storageName)
@@ -174,6 +176,22 @@ void ProfileAdapter::removeClient(ProfileAdapterClient *adapterClient)
m_clients.removeOne(adapterClient);
}
+void ProfileAdapter::addPageRequestInterceptor()
+{
+ ++m_pageRequestInterceptors;
+ if (m_profile->m_urlRequestContextGetter.get())
+ m_profile->m_profileIOData->updateRequestInterceptor();
+}
+
+void ProfileAdapter::removePageRequestInterceptor()
+{
+ Q_ASSERT(m_pageRequestInterceptors > 0);
+ --m_pageRequestInterceptors;
+ if (m_profile->m_urlRequestContextGetter.get())
+ m_profile->m_profileIOData->updateRequestInterceptor();
+}
+
+
void ProfileAdapter::cancelDownload(quint32 downloadId)
{
downloadManagerDelegate()->cancelDownload(downloadId);
diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h
index 19a56d2a7..b0d0d5632 100644
--- a/src/core/profile_adapter.h
+++ b/src/core/profile_adapter.h
@@ -189,6 +189,10 @@ public:
void setUseForGlobalCertificateVerification(bool enable = true);
bool isUsedForGlobalCertificateVerification() const;
+ void addPageRequestInterceptor();
+ void removePageRequestInterceptor();
+ bool hasPageRequestInterceptor() const { return m_pageRequestInterceptors > 0; }
+
private:
void updateCustomUrlSchemeHandlers();
void resetVisitedLinksManager();
@@ -213,6 +217,7 @@ private:
QHash<QByteArray, QWebEngineUrlSchemeHandler *> m_customUrlSchemeHandlers;
QList<ProfileAdapterClient*> m_clients;
int m_httpCacheMaxSize;
+ int m_pageRequestInterceptors;
Q_DISABLE_COPY(ProfileAdapter)
};
diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp
index ad8c2a110..ad79304d3 100644
--- a/src/core/profile_io_data_qt.cpp
+++ b/src/core/profile_io_data_qt.cpp
@@ -727,6 +727,7 @@ void ProfileIODataQt::updateRequestInterceptor()
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
QMutexLocker lock(&m_mutex);
m_requestInterceptor = m_profileAdapter->requestInterceptor();
+ m_hasPageInterceptors = m_profileAdapter->hasPageRequestInterceptor();
// We in this case do not need to regenerate any Chromium classes.
}
@@ -738,6 +739,13 @@ QWebEngineUrlRequestInterceptor *ProfileIODataQt::requestInterceptor()
return m_requestInterceptor;
}
+bool ProfileIODataQt::hasPageInterceptors()
+{
+ // used in NetworkDelegateQt::OnBeforeURLRequest
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ return m_hasPageInterceptors;
+}
+
bool ProfileIODataQt::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const
{
return m_cookieDelegate->canSetCookie(firstPartyUrl,cookieLine, url);
diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h
index 3eb456e6e..949497c71 100644
--- a/src/core/profile_io_data_qt.h
+++ b/src/core/profile_io_data_qt.h
@@ -103,6 +103,7 @@ public:
void updateJobFactory(); // runs on ui thread
void updateRequestInterceptor(); // runs on ui thread
void updateUsedForGlobalCertificateVerification(); // runs on ui thread
+ bool hasPageInterceptors();
private:
ProfileQt *m_profile;
@@ -143,6 +144,7 @@ private:
bool m_updateUserAgent = false;
bool m_ignoreCertificateErrors = false;
bool m_useForGlobalCertificateVerification = false;
+ bool m_hasPageInterceptors = false;
base::WeakPtrFactory<ProfileIODataQt> m_weakPtrFactory; // this should be always the last member
DISALLOW_COPY_AND_ASSIGN(ProfileIODataQt);
};
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 6fd29ec61..f1a15ddfd 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -66,6 +66,7 @@ QT_FORWARD_DECLARE_CLASS(QKeyEvent)
QT_FORWARD_DECLARE_CLASS(QVariant)
QT_FORWARD_DECLARE_CLASS(QWebEngineQuotaRequest)
QT_FORWARD_DECLARE_CLASS(QWebEngineRegisterProtocolHandlerRequest)
+QT_FORWARD_DECLARE_CLASS(QWebEngineUrlRequestInfo)
namespace content {
struct DropData;
@@ -473,6 +474,7 @@ public:
virtual void setToolTip(const QString& toolTipText) = 0;
virtual ClientType clientType() = 0;
virtual void printRequested() = 0;
+ virtual void interceptRequest(QWebEngineUrlRequestInfo &) { }
virtual ProfileAdapter *profileAdapter() = 0;
virtual WebContentsAdapter* webContentsAdapter() = 0;
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index fbb7c1f9e..1f9b2f72a 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -241,6 +241,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
, webChannelWorldId(QWebEngineScript::MainWorld)
, defaultAudioMuted(false)
, defaultZoomFactor(1.0)
+ , requestInterceptor(nullptr)
#if QT_CONFIG(webengine_printing_and_pdf)
, currentPrinter(nullptr)
#endif
@@ -260,6 +261,8 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
QWebEnginePagePrivate::~QWebEnginePagePrivate()
{
+ if (requestInterceptor)
+ profile->d_ptr->profileAdapter()->removePageRequestInterceptor();
delete history;
delete settings;
}
@@ -1781,6 +1784,40 @@ void QWebEnginePagePrivate::printRequested()
});
}
+/*!
+ \since 5.13
+
+ Registers the request interceptor \a interceptor to intercept URL requests.
+
+ The page does not take ownership of the pointer. This interceptor is called
+ after any interceptors on the profile, and unlike profile interceptors, is run
+ on the UI thread, making it thread-safer. Only URL requests from this page are
+ intercepted.
+
+ To unset the request interceptor, set a \c nullptr.
+
+ \sa QWebEngineUrlRequestInfo, QWebEngineProfile::setRequestInterceptor()
+*/
+
+void QWebEnginePage::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
+{
+ Q_D(QWebEnginePage);
+ bool hadInterceptorChanged = bool(d->requestInterceptor) != bool(interceptor);
+ d->requestInterceptor = interceptor;
+ if (hadInterceptorChanged) {
+ if (interceptor)
+ d->profile->d_ptr->profileAdapter()->addPageRequestInterceptor();
+ else
+ d->profile->d_ptr->profileAdapter()->removePageRequestInterceptor();
+ }
+}
+
+void QWebEnginePagePrivate::interceptRequest(QWebEngineUrlRequestInfo &info)
+{
+ if (requestInterceptor)
+ requestInterceptor->interceptRequest(info);
+}
+
#if QT_CONFIG(menu)
QMenu *QWebEnginePage::createStandardContextMenu()
{
diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h
index 6dd2da21c..a6bad4f26 100644
--- a/src/webenginewidgets/api/qwebenginepage.h
+++ b/src/webenginewidgets/api/qwebenginepage.h
@@ -71,6 +71,7 @@ class QWebEngineQuotaRequest;
class QWebEngineRegisterProtocolHandlerRequest;
class QWebEngineScriptCollection;
class QWebEngineSettings;
+class QWebEngineUrlRequestInterceptor;
class QWEBENGINEWIDGETS_EXPORT QWebEnginePage : public QObject {
Q_OBJECT
@@ -305,6 +306,8 @@ public:
void setDevToolsPage(QWebEnginePage *page);
QWebEnginePage *devToolsPage() const;
+ void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
+
const QWebEngineContextMenuData &contextMenuData() const;
Q_SIGNALS:
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 66a92dec9..6d214adca 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -149,6 +149,7 @@ public:
void printRequested() override;
const QObject *holdingQObject() const override;
ClientType clientType() override { return QtWebEngineCore::WebContentsAdapterClient::WidgetsClient; }
+ void interceptRequest(QWebEngineUrlRequestInfo &) override;
QtWebEngineCore::ProfileAdapter *profileAdapter() override;
QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override;
@@ -187,6 +188,7 @@ public:
bool defaultAudioMuted;
qreal defaultZoomFactor;
QTimer wasShownTimer;
+ QWebEngineUrlRequestInterceptor *requestInterceptor;
mutable QtWebEngineCore::CallbackDirectory m_callbacks;
mutable QAction *actions[QWebEnginePage::WebActionCount];
diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h
index 2c0b5ca03..3f17137e7 100644
--- a/src/webenginewidgets/api/qwebengineprofile.h
+++ b/src/webenginewidgets/api/qwebengineprofile.h
@@ -144,6 +144,7 @@ private:
Q_DECLARE_PRIVATE(QWebEngineProfile)
QWebEngineProfile(QWebEngineProfilePrivate *, QObject *parent = Q_NULLPTR);
+ friend class QWebEnginePage;
friend class QWebEnginePagePrivate;
friend class QWebEngineUrlSchemeHandler;
QScopedPointer<QWebEngineProfilePrivate> d_ptr;
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
index 50a3e6ff6..3f91f1b96 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
@@ -50,7 +50,9 @@ private Q_SLOTS:
void cleanupTestCase();
void interceptRequest();
void ipv6HostEncoding();
+ void requestedUrl_data();
void requestedUrl();
+ void setUrlSameUrl_data();
void setUrlSameUrl();
void firstPartyUrl();
};
@@ -190,14 +192,27 @@ void tst_QWebEngineUrlRequestInterceptor::ipv6HostEncoding()
QCOMPARE(contentProvider.requestedUrls.at(0), QUrl::fromEncoded("http://[::1]/test.xml"));
}
+void tst_QWebEngineUrlRequestInterceptor::requestedUrl_data()
+{
+ QTest::addColumn<bool>("interceptInPage");
+
+ QTest::newRow("Profile intercept") << false;
+ QTest::newRow("Page intercept") << true;
+}
+
void tst_QWebEngineUrlRequestInterceptor::requestedUrl()
{
+ QFETCH(bool, interceptInPage);
+
QWebEngineProfile profile;
profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
TestRequestInterceptor interceptor(/* intercept */ true);
- profile.setRequestInterceptor(&interceptor);
+ if (!interceptInPage)
+ profile.setRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
+ if (interceptInPage)
+ page.setRequestInterceptor(&interceptor);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
page.setUrl(QUrl("qrc:///resources/__placeholder__"));
@@ -214,19 +229,29 @@ void tst_QWebEngineUrlRequestInterceptor::requestedUrl()
QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
page.setUrl(QUrl("http://abcdef.abcdef"));
- QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 3, 12000);
+ QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 3, 15000);
QCOMPARE(interceptor.observedUrls.at(3), QUrl("http://abcdef.abcdef/"));
QCOMPARE(page.requestedUrl(), QUrl("qrc:///resources/__placeholder__"));
QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
}
+void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl_data()
+{
+ requestedUrl_data();
+}
+
void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl()
{
+ QFETCH(bool, interceptInPage);
+
QWebEngineProfile profile;
TestRequestInterceptor interceptor(/* intercept */ true);
- profile.setRequestInterceptor(&interceptor);
+ if (!interceptInPage)
+ profile.setRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
+ if (interceptInPage)
+ page.setRequestInterceptor(&interceptor);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
page.setUrl(QUrl("qrc:///resources/__placeholder__"));