diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-07-10 16:29:54 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-07-15 14:48:00 +0200 |
commit | 9a90cd56c432f2ad3e811449cb199b11c6ed9de8 (patch) | |
tree | 9f1441e3c6508866ea77dcdc5138dd8bcbb2f4fa | |
parent | 11a27178e42df66906dd12dcb5773ac6cb4426b8 (diff) |
Add the cookie filter to URL requests
Submodule src/3rdparty c91f4d20..809e16e4:
> Add cookie filter to URL requests cookie headers
> Use audio-manager app-name for MPRIS
Fixes: QTBUG-85526
Change-Id: Icab26cad3cea8e2ee021a3e589f41bf0543d64fa
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
m--------- | src/3rdparty | 0 | ||||
-rw-r--r-- | src/core/api/qwebenginecookiestore.cpp | 9 | ||||
-rw-r--r-- | src/core/net/cookie_monster_delegate_qt.cpp | 39 | ||||
-rw-r--r-- | src/core/net/cookie_monster_delegate_qt.h | 4 | ||||
-rw-r--r-- | tests/auto/core/qwebenginecookiestore/qwebenginecookiestore.pro | 1 | ||||
-rw-r--r-- | tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp | 72 | ||||
-rw-r--r-- | tests/auto/shared/httpreqrep.cpp | 2 |
7 files changed, 126 insertions, 1 deletions
diff --git a/src/3rdparty b/src/3rdparty -Subproject c91f4d20178b4f039b68bddde534daca4aaa27b +Subproject 809e16e4ac75c0d7eb39cef6a2d29544971b8d3 diff --git a/src/core/api/qwebenginecookiestore.cpp b/src/core/api/qwebenginecookiestore.cpp index 40594b9c0..a09a74bf6 100644 --- a/src/core/api/qwebenginecookiestore.cpp +++ b/src/core/api/qwebenginecookiestore.cpp @@ -89,6 +89,9 @@ void QWebEngineCookieStorePrivate::processPendingUserCookies() delegate->deleteSessionCookies(CallbackDirectory::DeleteSessionCookiesCallbackId); } + if (bool(filterCallback)) + delegate->setHasFilter(true); + if (m_pendingUserCookies.isEmpty()) return; @@ -362,7 +365,10 @@ void QWebEngineCookieStore::deleteAllCookies() */ void QWebEngineCookieStore::setCookieFilter(const std::function<bool(const FilterRequest &)> &filterCallback) { + bool changed = bool(d_ptr->filterCallback) != bool(filterCallback); d_ptr->filterCallback = filterCallback; + if (changed && d_ptr->delegate) + d_ptr->delegate->setHasFilter(bool(d_ptr->filterCallback)); } /*! @@ -371,7 +377,10 @@ void QWebEngineCookieStore::setCookieFilter(const std::function<bool(const Filte */ void QWebEngineCookieStore::setCookieFilter(std::function<bool(const FilterRequest &)> &&filterCallback) { + bool changed = bool(d_ptr->filterCallback) != bool(filterCallback); d_ptr->filterCallback = std::move(filterCallback); + if (changed && d_ptr->delegate) + d_ptr->delegate->setHasFilter(bool(d_ptr->filterCallback)); } /*! diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp index d3157f760..d2e0b38e2 100644 --- a/src/core/net/cookie_monster_delegate_qt.cpp +++ b/src/core/net/cookie_monster_delegate_qt.cpp @@ -72,6 +72,25 @@ private: DISALLOW_COPY_AND_ASSIGN(CookieChangeListener); }; +class CookieAccessFilter : public network::mojom::CookieRemoteAccessFilter +{ +public: + CookieAccessFilter(CookieMonsterDelegateQt *delegate) : m_delegate(delegate) { } + ~CookieAccessFilter() override = default; + + void AllowedAccess(const GURL& url, const GURL& site_for_cookies, AllowedAccessCallback callback) override + { + bool allow = m_delegate->canGetCookies(toQt(site_for_cookies), toQt(url)); + std::move(callback).Run(allow); + } + +private: + CookieMonsterDelegateQt *m_delegate; + + DISALLOW_COPY_AND_ASSIGN(CookieAccessFilter); +}; + + static GURL sourceUrlForCookie(const QNetworkCookie &cookie) { QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path()); @@ -81,7 +100,10 @@ static GURL sourceUrlForCookie(const QNetworkCookie &cookie) CookieMonsterDelegateQt::CookieMonsterDelegateQt() : m_client(nullptr) , m_listener(new CookieChangeListener(this)) + , m_filter(new CookieAccessFilter(this)) , m_receiver(m_listener.get()) + , m_filterReceiver(m_filter.get()) + , m_hasFilter(false) { } @@ -176,14 +198,31 @@ void CookieMonsterDelegateQt::setMojoCookieManager(network::mojom::CookieManager m_mojoCookieManager.Bind(std::move(cookie_manager_info)); m_mojoCookieManager->AddGlobalChangeListener(m_receiver.BindNewPipeAndPassRemote()); + if (m_hasFilter) + m_mojoCookieManager->SetRemoteFilter(m_filterReceiver.BindNewPipeAndPassRemote()); if (m_client) m_client->d_func()->processPendingUserCookies(); } +void CookieMonsterDelegateQt::setHasFilter(bool hasFilter) +{ + m_hasFilter = hasFilter; + if (!m_mojoCookieManager.is_bound()) + return; + if (m_hasFilter) { + if (!m_filterReceiver.is_bound()) + m_mojoCookieManager->SetRemoteFilter(m_filterReceiver.BindNewPipeAndPassRemote()); + } else { + if (m_filterReceiver.is_bound()) + m_filterReceiver.reset(); + } +} + void CookieMonsterDelegateQt::unsetMojoCookieManager() { m_receiver.reset(); + m_filterReceiver.reset(); m_mojoCookieManager.reset(); } diff --git a/src/core/net/cookie_monster_delegate_qt.h b/src/core/net/cookie_monster_delegate_qt.h index bcbbe4c52..748e92da9 100644 --- a/src/core/net/cookie_monster_delegate_qt.h +++ b/src/core/net/cookie_monster_delegate_qt.h @@ -91,7 +91,10 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT CookieMonsterDelegateQt : public base::RefC network::mojom::CookieManagerPtr m_mojoCookieManager; std::unique_ptr<network::mojom::CookieChangeListener> m_listener; + std::unique_ptr<network::mojom::CookieRemoteAccessFilter> m_filter; mojo::Receiver<network::mojom::CookieChangeListener> m_receiver; + mojo::Receiver<network::mojom::CookieRemoteAccessFilter> m_filterReceiver; + bool m_hasFilter; public: CookieMonsterDelegateQt(); ~CookieMonsterDelegateQt(); @@ -107,6 +110,7 @@ public: void setClient(QWebEngineCookieStore *client); void setMojoCookieManager(network::mojom::CookieManagerPtrInfo cookie_manager_info); void unsetMojoCookieManager(); + void setHasFilter(bool b); bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const; bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const; diff --git a/tests/auto/core/qwebenginecookiestore/qwebenginecookiestore.pro b/tests/auto/core/qwebenginecookiestore/qwebenginecookiestore.pro index e99c7f493..9c239f1a7 100644 --- a/tests/auto/core/qwebenginecookiestore/qwebenginecookiestore.pro +++ b/tests/auto/core/qwebenginecookiestore/qwebenginecookiestore.pro @@ -1 +1,2 @@ include(../tests.pri) +include(../../shared/http.pri) diff --git a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp index 2c41aa9b1..638b2e028 100644 --- a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp +++ b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp @@ -33,6 +33,9 @@ #include <QtWebEngineWidgets/qwebenginepage.h> #include <QtWebEngineWidgets/qwebengineprofile.h> +#include "httpserver.h" +#include "httpreqrep.h" + class tst_QWebEngineCookieStore : public QObject { Q_OBJECT @@ -56,6 +59,7 @@ private Q_SLOTS: void cookieSignals(); void batchCookieTasks(); void basicFilter(); + void basicFilterOverHTTP(); void html5featureFilter(); private: @@ -239,6 +243,74 @@ void tst_QWebEngineCookieStore::basicFilter() QCOMPARE(cookieAddedSpy.count(), 2); } +void tst_QWebEngineCookieStore::basicFilterOverHTTP() +{ + QWebEnginePage page(m_profile); + QWebEngineCookieStore *client = m_profile->cookieStore(); + + QAtomicInt accessTested = 0; + client->setCookieFilter([&](const QWebEngineCookieStore::FilterRequest &) { ++accessTested; return true; }); + + HttpServer httpServer; + + if (!httpServer.start()) + QSKIP("Failed to start http server"); + + QByteArray cookieRequestHeader; + connect(&httpServer, &HttpServer::newRequest, [&cookieRequestHeader](HttpReqRep *rr) { + if (rr->requestPath().size() <= 1) { + cookieRequestHeader = rr->requestHeader(QByteArrayLiteral("Cookie")); + rr->setResponseStatus(200); + if (cookieRequestHeader.isEmpty()) + rr->setResponseHeader(QByteArrayLiteral("Set-Cookie"), QByteArrayLiteral("Test=test")); + rr->sendResponse(); + } else { + rr->setResponseStatus(404); + rr->sendResponse(); + } + }); + + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &))); + QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &))); + + page.load(httpServer.url()); + + QTRY_COMPARE_WITH_TIMEOUT(loadSpy.count(), 1, 30000); + QVERIFY(loadSpy.takeFirst().takeFirst().toBool()); + QTRY_COMPARE(cookieAddedSpy.count(), 1); + QTRY_COMPARE(accessTested.loadAcquire(), 3); + QVERIFY(cookieRequestHeader.isEmpty()); + + page.triggerAction(QWebEnginePage::Reload); + QTRY_COMPARE(loadSpy.count(), 1); + QVERIFY(loadSpy.takeFirst().takeFirst().toBool()); + QVERIFY(!cookieRequestHeader.isEmpty()); + QTRY_COMPARE(cookieAddedSpy.count(), 1); + QTRY_COMPARE(accessTested.loadAcquire(), 5); + + client->deleteAllCookies(); + QTRY_COMPARE(cookieRemovedSpy.count(), 1); + + client->setCookieFilter([&](const QWebEngineCookieStore::FilterRequest &) { ++accessTested; return false; }); + page.triggerAction(QWebEnginePage::ReloadAndBypassCache); + QTRY_COMPARE(loadSpy.count(), 1); + QVERIFY(loadSpy.takeFirst().takeFirst().toBool()); + QVERIFY(cookieRequestHeader.isEmpty()); + // Test cookies are NOT added: + QTest::qWait(100); + QCOMPARE(cookieAddedSpy.count(), 1); + QTRY_COMPARE(accessTested.loadAcquire(), 8); + + page.triggerAction(QWebEnginePage::Reload); + QTRY_COMPARE(loadSpy.count(), 1); + QVERIFY(loadSpy.takeFirst().takeFirst().toBool()); + QVERIFY(cookieRequestHeader.isEmpty()); + QCOMPARE(cookieAddedSpy.count(), 1); + + (void) httpServer.stop(); +} + void tst_QWebEngineCookieStore::html5featureFilter() { QWebEnginePage page(m_profile); diff --git a/tests/auto/shared/httpreqrep.cpp b/tests/auto/shared/httpreqrep.cpp index 15a86631c..b1b6a0a04 100644 --- a/tests/auto/shared/httpreqrep.cpp +++ b/tests/auto/shared/httpreqrep.cpp @@ -67,7 +67,7 @@ void HttpReqRep::close() QByteArray HttpReqRep::requestHeader(const QByteArray &key) const { - auto it = m_requestHeaders.find(key); + auto it = m_requestHeaders.find(key.toLower()); if (it != m_requestHeaders.end()) return it->second; return {}; |