diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-07-24 09:41:25 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-17 12:34:30 +0000 |
commit | 17bd9d9de2d424ef7f7a193e17d1619d6effec7b (patch) | |
tree | 049a423c6a2f091e1d0f9e2c8a2531ebbd9412fc | |
parent | 0b1025b8aea4aa0336671f7e908287d65490d120 (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.cpp | 24 | ||||
-rw-r--r-- | src/core/api/qwebengineurlrequestinfo.h | 5 | ||||
-rw-r--r-- | src/core/net/network_delegate_qt.cpp | 118 | ||||
-rw-r--r-- | src/core/profile_adapter.cpp | 18 | ||||
-rw-r--r-- | src/core/profile_adapter.h | 5 | ||||
-rw-r--r-- | src/core/profile_io_data_qt.cpp | 8 | ||||
-rw-r--r-- | src/core/profile_io_data_qt.h | 2 | ||||
-rw-r--r-- | src/core/web_contents_adapter_client.h | 2 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.cpp | 37 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.h | 3 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage_p.h | 2 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebengineprofile.h | 1 | ||||
-rw-r--r-- | tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp | 31 |
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__")); |