summaryrefslogtreecommitdiffstats
path: root/src/core/net
diff options
context:
space:
mode:
authorYigit Akcay <yigit.akcay@qt.io>2023-02-15 20:43:25 +0100
committerYigit Akcay <yigit.akcay@qt.io>2023-03-10 17:13:32 +0100
commit5e257fb57a211f95556ec387fe6f262a60cbb6fe (patch)
tree330abbb7f84f8664fbd44b80d573265da4cc2bcb /src/core/net
parent28a2cfe4116f7218b33df811b79536c0593ddda6 (diff)
QWebEngineUrlResponseInterceptor: Implement new URL response interceptor
This patch adds the QWebEngineUrlResponseInterceptor abstract class, which, when implemented, allows a user to intercept response headers and modify them in any way they like. A response interceptor can be set via QWebEngineProfile::setUrlResponseInterceptor(), QQuickWebEngineProfile::setUrlResponseInterceptor() or QWebEnginePage::setUrlResponseInterceptor(). Also, the QWebEngineUrlResponseInfo class is implemented, which contains the request and response data to be used with the response interceptor. If a response interceptor is set in the profile and page, the one in the profile takes precedence. Fixes: QTBUG-61071 Change-Id: I484d14373ff597b1d531541c066f0102bae28c72 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'src/core/net')
-rw-r--r--src/core/net/proxying_url_loader_factory_qt.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp
index 70ec61b34..aa333ae02 100644
--- a/src/core/net/proxying_url_loader_factory_qt.cpp
+++ b/src/core/net/proxying_url_loader_factory_qt.cpp
@@ -20,11 +20,14 @@
#include "url/url_util_qt.h"
#include "api/qwebengineurlrequestinfo_p.h"
+#include "api/qwebengineurlresponseinfo_p.h"
#include "type_conversion.h"
#include "web_contents_adapter.h"
#include "web_contents_adapter_client.h"
#include "web_contents_view_qt.h"
+#include <QtWebEngineCore/QWebEngineUrlResponseInfo>
+
// originally based on aw_proxying_url_loader_factory.cc:
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
@@ -148,6 +151,11 @@ private:
content::WebContents* webContents();
QWebEngineUrlRequestInterceptor* getProfileInterceptor();
QWebEngineUrlRequestInterceptor* getPageInterceptor();
+ QWebEngineUrlResponseInterceptor *getProfileResponseInterceptor();
+ QWebEngineUrlResponseInterceptor *getPageResponseInterceptor();
+
+ void interceptResponseHeaders(QWebEngineUrlResponseInterceptor *const interceptor,
+ net::HttpResponseHeaders *const responseHeadersPtr);
QPointer<ProfileAdapter> profile_adapter_;
const int frame_tree_node_id_;
@@ -252,6 +260,59 @@ QWebEngineUrlRequestInterceptor* InterceptedRequest::getPageInterceptor()
return nullptr;
}
+QWebEngineUrlResponseInterceptor* InterceptedRequest::getProfileResponseInterceptor()
+{
+ return profile_adapter_ ? profile_adapter_->responseInterceptor() : nullptr;
+}
+
+QWebEngineUrlResponseInterceptor* InterceptedRequest::getPageResponseInterceptor()
+{
+ if (auto wc = webContents()) {
+ auto view = static_cast<content::WebContentsImpl *>(wc)->GetView();
+ if (WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client())
+ return client->webContentsAdapter()->responseInterceptor();
+ }
+ return nullptr;
+}
+
+void InterceptedRequest::interceptResponseHeaders(
+ QWebEngineUrlResponseInterceptor *const interceptor,
+ net::HttpResponseHeaders *const responseHeadersPtr)
+{
+ QHash<QByteArray, QByteArray> responseHeaders;
+ std::unordered_set<std::string> headersToRemove;
+ {
+ std::size_t iter = 0;
+ std::string name;
+ std::string value;
+ while (responseHeadersPtr->EnumerateHeaderLines(&iter, &name, &value)) {
+ responseHeaders.insert(QByteArray::fromStdString(name),
+ QByteArray::fromStdString(value));
+ headersToRemove.insert(name);
+ }
+ }
+
+ const QUrl requestUrl = QUrl::fromEncoded(QByteArray::fromStdString(request_.url.spec()));
+ const QHash<QByteArray, QByteArray> requestHeaders =
+ [](const net::HttpRequestHeaders &headers) {
+ QHash<QByteArray, QByteArray> result;
+ for (const auto &header : headers.GetHeaderVector()) {
+ result.insert(QByteArray::fromStdString(header.key),
+ QByteArray::fromStdString(header.value));
+ }
+ return result;
+ }(request_.headers);
+
+ QWebEngineUrlResponseInfo info(requestUrl, requestHeaders, responseHeaders);
+ interceptor->interceptResponseHeaders(info);
+
+ if (info.d_ptr->isModified) {
+ responseHeadersPtr->RemoveHeaders(headersToRemove);
+ for (auto it = info.responseHeaders().cbegin(); it != info.responseHeaders().cend(); ++it)
+ responseHeadersPtr->AddHeader(it.key().toStdString(), it.value().toStdString());
+ }
+}
+
void InterceptedRequest::Restart()
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -404,6 +465,12 @@ void InterceptedRequest::ContinueAfterIntercept()
void InterceptedRequest::OnReceiveResponse(network::mojom::URLResponseHeadPtr head, mojo::ScopedDataPipeConsumerHandle handle, absl::optional<mojo_base::BigBuffer> buffer)
{
+ QWebEngineUrlResponseInterceptor *const responseInterceptor = getProfileResponseInterceptor()
+ ? getProfileResponseInterceptor()
+ : getPageResponseInterceptor();
+ if (responseInterceptor)
+ interceptResponseHeaders(responseInterceptor, head->headers.get());
+
current_response_ = head.Clone();
target_client_->OnReceiveResponse(std::move(head), std::move(handle), std::move(buffer));