diff options
Diffstat (limited to 'src/core/net/proxying_url_loader_factory_qt.cpp')
-rw-r--r-- | src/core/net/proxying_url_loader_factory_qt.cpp | 422 |
1 files changed, 244 insertions, 178 deletions
diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp index d63659d2d..3a83ed7ea 100644 --- a/src/core/net/proxying_url_loader_factory_qt.cpp +++ b/src/core/net/proxying_url_loader_factory_qt.cpp @@ -1,75 +1,48 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://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 https://www.qt.io/terms-conditions. For further -** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "proxying_url_loader_factory_qt.h" #include <utility> -#include "base/bind.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/task/post_task.h" +#include "base/functional/bind.h" #include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/global_request_id.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/content_constants.h" -#include "content/public/common/url_utils.h" -#include "net/base/load_flags.h" +#include "content/public/common/content_switches.h" +#include "net/base/filename_util.h" #include "net/http/http_status_code.h" -#include "net/http/http_util.h" +#include "services/network/public/cpp/cors/cors.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/mojom/early_hints.mojom.h" +#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" +#include "url/url_util.h" +#include "url/url_util_qt.h" #include "api/qwebengineurlrequestinfo_p.h" -#include "profile_qt.h" #include "type_conversion.h" +#include "web_contents_adapter.h" #include "web_contents_adapter_client.h" #include "web_contents_view_qt.h" - -#include <QVariant> +#include "net/resource_request_body_qt.h" // 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 // found in the LICENSE file. +namespace { + network::mojom::URLResponseHeadPtr createResponse(const network::ResourceRequest &request) { + const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity); + network::mojom::URLResponseHeadPtr response = network::mojom::URLResponseHead::New(); + response->response_type = network::cors::CalculateResponseType( + request.mode, disable_web_security || ( + request.request_initiator && request.request_initiator->IsSameOriginWith(url::Origin::Create(request.url)))); + + return response; + } +} + namespace QtWebEngineCore { ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMainFrame, blink::mojom::ResourceType::kMainFrame) @@ -108,17 +81,28 @@ static QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::N return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType); } +static QHash<QByteArray, QByteArray> toQt(const net::HttpRequestHeaders &headers) +{ + const auto vector = headers.GetHeaderVector(); + QHash<QByteArray, QByteArray> hash; + + for (const auto &header : vector) { + hash.insert(QByteArray::fromStdString(header.key), QByteArray::fromStdString(header.value)); + } + + return hash; +} + // Handles intercepted, in-progress requests/responses, so that they can be // controlled and modified accordingly. class InterceptedRequest : public network::mojom::URLLoader , public network::mojom::URLLoaderClient { public: - InterceptedRequest(int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, + InterceptedRequest(ProfileAdapter *profile_adapter, + int frame_tree_node_id, int32_t request_id, uint32_t options, const network::ResourceRequest &request, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, - QWebEngineUrlRequestInterceptor *profile_request_interceptor, - QWebEngineUrlRequestInterceptor *page_request_interceptor, mojo::PendingReceiver<network::mojom::URLLoader> loader, mojo::PendingRemote<network::mojom::URLLoaderClient> client, mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory); @@ -127,24 +111,24 @@ public: void Restart(); // network::mojom::URLLoaderClient - void OnReceiveResponse(network::mojom::URLResponseHeadPtr head) override; + void OnReceiveResponse(network::mojom::URLResponseHeadPtr head, mojo::ScopedDataPipeConsumerHandle, absl::optional<mojo_base::BigBuffer>) override; void OnReceiveRedirect(const net::RedirectInfo &redirect_info, network::mojom::URLResponseHeadPtr head) override; void OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback callback) override; - void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override; void OnTransferSizeUpdated(int32_t transfer_size_diff) override; - void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle body) override; void OnComplete(const network::URLLoaderCompletionStatus &status) override; + void OnReceiveEarlyHints(network::mojom::EarlyHintsPtr) override {} // network::mojom::URLLoader void FollowRedirect(const std::vector<std::string> &removed_headers, - const net::HttpRequestHeaders &modified_headers, const base::Optional<GURL> &new_url) override; + const net::HttpRequestHeaders &modified_headers, + const net::HttpRequestHeaders &modified_cors_exempt_headers, + const absl::optional<GURL> &new_url) override; void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override; void PauseReadingBodyFromNet() override; void ResumeReadingBodyFromNet() override; private: void InterceptOnUIThread(); - void InterceptOnIOThread(base::WaitableEvent *event); void ContinueAfterIntercept(); // This is called when the original URLLoaderClient has a connection error. @@ -160,25 +144,39 @@ private: void SendErrorAndCompleteImmediately(int error_code); - const int process_id_; - const uint64_t request_id_; - const int32_t routing_id_; + content::WebContents* webContents(); + QWebEngineUrlRequestInterceptor* getProfileInterceptor(); + QWebEngineUrlRequestInterceptor* getPageInterceptor(); + + QPointer<ProfileAdapter> profile_adapter_; + const int frame_tree_node_id_; + const int32_t request_id_; const uint32_t options_; - bool input_stream_previously_failed_ = false; - bool request_was_redirected_ = false; + bool allow_local_ = false; + bool allow_remote_ = true; + bool local_access_ = false; + bool remote_access_ = true; + + bool loader_error_seen_ = false; // If the |target_loader_| called OnComplete with an error this stores it. // That way the destructor can send it to OnReceivedError if safe browsing // error didn't occur. int error_status_ = net::OK; network::ResourceRequest request_; + ResourceRequestBody request_body_; network::mojom::URLResponseHeadPtr current_response_; const net::MutableNetworkTrafficAnnotationTag traffic_annotation_; - QWebEngineUrlRequestInfo request_info_; - QPointer<QWebEngineUrlRequestInterceptor> profile_request_interceptor_; - QPointer<QWebEngineUrlRequestInterceptor> page_request_interceptor_; + struct RequestInfoDeleter + { + void operator()(QWebEngineUrlRequestInfo *ptr) const + { delete ptr; } + }; + + std::unique_ptr<QWebEngineUrlRequestInfo, RequestInfoDeleter> request_info_; + mojo::Receiver<network::mojom::URLLoader> proxied_loader_receiver_; mojo::Remote<network::mojom::URLLoaderClient> target_client_; mojo::Receiver<network::mojom::URLLoaderClient> proxied_client_receiver_{this}; @@ -186,36 +184,52 @@ private: mojo::Remote<network::mojom::URLLoaderFactory> target_factory_; base::WeakPtrFactory<InterceptedRequest> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(InterceptedRequest); }; -InterceptedRequest::InterceptedRequest(int process_id, uint64_t request_id, int32_t routing_id, uint32_t options, +InterceptedRequest::InterceptedRequest(ProfileAdapter *profile_adapter, + int frame_tree_node_id, int32_t request_id, uint32_t options, const network::ResourceRequest &request, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, - QWebEngineUrlRequestInterceptor *profile_request_interceptor, - QWebEngineUrlRequestInterceptor *page_request_interceptor, mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver, mojo::PendingRemote<network::mojom::URLLoaderClient> client, mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory) - : process_id_(process_id) + : profile_adapter_(profile_adapter) + , frame_tree_node_id_(frame_tree_node_id) , request_id_(request_id) - , routing_id_(routing_id) , options_(options) , request_(request) + , request_body_(ResourceRequestBody(request_.request_body.get())) , traffic_annotation_(traffic_annotation) - , profile_request_interceptor_(profile_request_interceptor) - , page_request_interceptor_(page_request_interceptor) , proxied_loader_receiver_(this, std::move(loader_receiver)) , target_client_(std::move(client)) , target_factory_(std::move(target_factory)) , weak_factory_(this) { - current_response_ = network::mojom::URLResponseHead::New(); + const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity); + current_response_ = createResponse(request_); // If there is a client error, clean up the request. target_client_.set_disconnect_handler( - base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, weak_factory_.GetWeakPtr())); + base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, base::Unretained(this))); proxied_loader_receiver_.set_disconnect_with_reason_handler( - base::BindOnce(&InterceptedRequest::OnURLLoaderError, weak_factory_.GetWeakPtr())); + base::BindOnce(&InterceptedRequest::OnURLLoaderError, base::Unretained(this))); + if (!disable_web_security && request_.request_initiator) { + const std::vector<std::string> &localSchemes = url::GetLocalSchemes(); + const std::string fromScheme = request_.request_initiator->GetTupleOrPrecursorTupleIfOpaque().scheme(); + const std::string toScheme = request_.url.scheme(); + const bool fromLocal = base::Contains(localSchemes, fromScheme); + const bool toLocal = base::Contains(localSchemes, toScheme); + bool hasLocalAccess = false; + local_access_ = toLocal; + remote_access_ = !toLocal && (toScheme != "data") && (toScheme != "qrc"); + if (const url::CustomScheme *cs = url::CustomScheme::FindScheme(fromScheme)) + hasLocalAccess = cs->flags & url::CustomScheme::LocalAccessAllowed; + if (fromLocal || toLocal) { + content::WebContents *wc = webContents(); + // local schemes must have universal access, or be accessing something local and have local access. + allow_local_ = hasLocalAccess || (fromLocal && wc && wc->GetOrCreateWebPreferences().allow_file_access_from_file_urls); + allow_remote_ = !fromLocal || (wc && wc->GetOrCreateWebPreferences().allow_remote_access_from_local_urls); + } + } } InterceptedRequest::~InterceptedRequest() @@ -223,115 +237,175 @@ InterceptedRequest::~InterceptedRequest() weak_factory_.InvalidateWeakPtrs(); } +content::WebContents* InterceptedRequest::webContents() +{ + if (frame_tree_node_id_ == content::RenderFrameHost::kNoFrameTreeNodeId) + return nullptr; + return content::WebContents::FromFrameTreeNodeId(frame_tree_node_id_); +} + +QWebEngineUrlRequestInterceptor* InterceptedRequest::getProfileInterceptor() +{ + return profile_adapter_ ? profile_adapter_->requestInterceptor() : nullptr; +} + +QWebEngineUrlRequestInterceptor* InterceptedRequest::getPageInterceptor() +{ + if (auto wc = webContents()) { + auto view = static_cast<content::WebContentsImpl *>(wc)->GetView(); + if (WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client()) + return client->webContentsAdapter()->requestInterceptor(); + } + return nullptr; +} + void InterceptedRequest::Restart() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - blink::mojom::ResourceType resourceType = blink::mojom::ResourceType(request_.resource_type); - WebContentsAdapterClient::NavigationType navigationType = - pageTransitionToNavigationType(ui::PageTransition(request_.transition_type)); - const QUrl originalUrl = toQt(request_.url); - const QUrl initiator = request_.request_initiator.has_value() ? toQt(request_.request_initiator->GetURL()) : QUrl(); + bool granted_special_access = false; + auto navigationType = toQt(pageTransitionToNavigationType(ui::PageTransition(request_.transition_type))); + switch (navigationType) { + case QWebEngineUrlRequestInfo::NavigationTypeLink: + case QWebEngineUrlRequestInfo::NavigationTypeTyped: + if (blink::mojom::ResourceType(request_.resource_type) == blink::mojom::ResourceType::kMainFrame && request_.has_user_gesture) + granted_special_access = true; // allow normal explicit navigation + break; + case QWebEngineUrlRequestInfo::NavigationTypeBackForward: + case QWebEngineUrlRequestInfo::NavigationTypeReload: + if (blink::mojom::ResourceType(request_.resource_type) == blink::mojom::ResourceType::kMainFrame) + granted_special_access = true; + break; + default: + break; + } - content::WebContents *webContents = nullptr; - if (process_id_) { - content::RenderFrameHost *frameHost = content::RenderFrameHost::FromID(process_id_, request_.render_frame_id); - webContents = content::WebContents::FromRenderFrameHost(frameHost); - } else { - webContents = content::WebContents::FromFrameTreeNodeId(request_.render_frame_id); + // Check if non-local access is allowed + if (!allow_remote_ && remote_access_) { + if (!granted_special_access) { + target_client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_NETWORK_ACCESS_DENIED)); + delete this; + return; + } + } + + // Check if local access is allowed + if (!allow_local_ && local_access_) { + // Check for specifically granted file access: + if (auto *frame_tree = content::FrameTreeNode::GloballyFindByID(frame_tree_node_id_)) { + const int renderer_id = frame_tree->current_frame_host()->GetProcess()->GetID(); + base::FilePath file_path; + if (net::FileURLToFilePath(request_.url, &file_path)) { + if (content::ChildProcessSecurityPolicy::GetInstance()->CanReadFile(renderer_id, file_path)) + granted_special_access = true; + } + } + if (!granted_special_access) { + target_client_->OnComplete(network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED)); + delete this; + return; + } + } + + // MEMO since all codepatch leading to Restart scheduled and executed as asynchronous tasks in main thread, + // interceptors may change in meantime and also during intercept call, so they should be resolved anew. + // Set here only profile's interceptor since it runs first without going to user code. + auto profileInterceptor = getProfileInterceptor(); + if (!profileInterceptor && !getPageInterceptor()) { + ContinueAfterIntercept(); + return; } - GURL top_document_url = webContents ? webContents->GetVisibleURL() : GURL(); + auto resourceType = toQt(blink::mojom::ResourceType(request_.resource_type)); + const QUrl originalUrl = toQt(request_.url); + const QUrl initiator = request_.request_initiator.has_value() ? toQt(request_.request_initiator->GetURL()) : QUrl(); + + auto wc = webContents(); + GURL top_document_url = wc ? wc->GetVisibleURL() : GURL(); QUrl firstPartyUrl; if (!top_document_url.is_empty()) firstPartyUrl = toQt(top_document_url); else - firstPartyUrl = toQt(request_.site_for_cookies.RepresentativeUrl()); // m_topDocumentUrl can be empty for the main-frame. - - QWebEngineUrlRequestInfoPrivate *infoPrivate = - new QWebEngineUrlRequestInfoPrivate(toQt(resourceType), toQt(navigationType), originalUrl, firstPartyUrl, - initiator, QByteArray::fromStdString(request_.method)); - request_info_ = QWebEngineUrlRequestInfo(infoPrivate); - - // TODO: remove for Qt6 - if (profile_request_interceptor_ && profile_request_interceptor_->property("deprecated").toBool()) { - // sync call supports depracated call of an interceptor on io thread - base::WaitableEvent event; - base::PostTask(FROM_HERE, { content::BrowserThread::IO }, - base::BindOnce(&InterceptedRequest::InterceptOnIOThread, base::Unretained(this), &event)); - event.Wait(); - if (request_info_.changed()) { - ContinueAfterIntercept(); - return; - } - } + firstPartyUrl = toQt(request_.site_for_cookies.first_party_url()); // m_topDocumentUrl can be empty for the main-frame. + + QHash<QByteArray, QByteArray> headers = toQt(request_.headers); + + if (!request_.referrer.is_empty()) + headers.insert("Referer", toQt(request_.referrer).toEncoded()); + + auto info = new QWebEngineUrlRequestInfoPrivate( + resourceType, navigationType, originalUrl, firstPartyUrl, initiator, + QByteArray::fromStdString(request_.method), &request_body_, headers); + Q_ASSERT(!request_info_); + request_info_.reset(new QWebEngineUrlRequestInfo(info)); + InterceptOnUIThread(); ContinueAfterIntercept(); } -void InterceptedRequest::InterceptOnIOThread(base::WaitableEvent *event) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (profile_request_interceptor_) - profile_request_interceptor_->interceptRequest(request_info_); - event->Signal(); -} - void InterceptedRequest::InterceptOnUIThread() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (profile_request_interceptor_ && !profile_request_interceptor_->property("deprecated").toBool()) - profile_request_interceptor_->interceptRequest(request_info_); + if (auto interceptor = getProfileInterceptor()) + interceptor->interceptRequest(*request_info_); - if (!request_info_.changed() && page_request_interceptor_) - page_request_interceptor_->interceptRequest(request_info_); + if (!request_info_->changed()) { + if (auto interceptor = getPageInterceptor()) + interceptor->interceptRequest(*request_info_); + } } void InterceptedRequest::ContinueAfterIntercept() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (request_info_.changed()) { - if (request_info_.d_ptr->shouldBlockRequest) - return SendErrorAndCompleteImmediately(net::ERR_BLOCKED_BY_CLIENT); - if (request_info_.d_ptr->shouldRedirectRequest) { - net::URLRequest::FirstPartyURLPolicy first_party_url_policy = - request_.update_first_party_url_on_redirect ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT - : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; - net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo( - request_.method, request_.url, request_.site_for_cookies, - first_party_url_policy, request_.referrer_policy, request_.referrer.spec(), - net::HTTP_TEMPORARY_REDIRECT, toGurl(request_info_.requestUrl()), base::nullopt, - false /*insecure_scheme_was_upgraded*/); - - // FIXME: Should probably create a new header. - current_response_->encoded_data_length = 0; - request_.method = redirectInfo.new_method; - request_.url = redirectInfo.new_url; - request_.site_for_cookies = redirectInfo.new_site_for_cookies; - request_.referrer = GURL(redirectInfo.new_referrer); - request_.referrer_policy = redirectInfo.new_referrer_policy; - if (request_.method == net::HttpRequestHeaders::kGetMethod) - request_.request_body = nullptr; - target_client_->OnReceiveRedirect(redirectInfo, std::move(current_response_)); - return; + if (request_info_) { + // cleanup in scope because of delete this and it's not needed else where after + const auto scoped_request_info = std::move(request_info_); + QWebEngineUrlRequestInfoPrivate &info = *scoped_request_info->d_ptr; + + for (auto header = info.extraHeaders.constBegin(); header != info.extraHeaders.constEnd(); ++header) { + std::string h = header.key().toStdString(); + if (base::EqualsCaseInsensitiveASCII(h, "referer")) + request_.referrer = GURL(header.value().toStdString()); + else + request_.headers.SetHeader(h, header.value().toStdString()); } - if (!request_info_.d_ptr->extraHeaders.isEmpty()) { - auto end = request_info_.d_ptr->extraHeaders.constEnd(); - for (auto header = request_info_.d_ptr->extraHeaders.constBegin(); header != end; ++header) { - std::string h = header.key().toStdString(); - if (base::LowerCaseEqualsASCII(h, "referer")) { - request_.referrer = GURL(header.value().toStdString()); - } else { - request_.headers.SetHeader(h, header.value().toStdString()); - } + if (info.changed) { + if (info.shouldBlockRequest) + return SendErrorAndCompleteImmediately(net::ERR_BLOCKED_BY_CLIENT); + + if (info.shouldRedirectRequest) { + net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy = + request_.update_first_party_url_on_redirect ? net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT + : net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL; + net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo( + request_.method, request_.url, request_.site_for_cookies, + first_party_url_policy, request_.referrer_policy, request_.referrer.spec(), + net::HTTP_TEMPORARY_REDIRECT, toGurl(info.url), absl::nullopt, + false /*insecure_scheme_was_upgraded*/); + request_.method = redirectInfo.new_method; + request_.url = redirectInfo.new_url; + request_.site_for_cookies = redirectInfo.new_site_for_cookies; + request_.referrer = GURL(redirectInfo.new_referrer); + request_.referrer_policy = redirectInfo.new_referrer_policy; + if (request_.method == net::HttpRequestHeaders::kGetMethod) + request_.request_body = nullptr; + // In case of multiple sequential rediredts, current_response_ has previously been moved to target_client_ + // so we create a new one using the redirect url. + if (!current_response_) + current_response_ = createResponse(request_); + current_response_->encoded_data_length = 0; + target_client_->OnReceiveRedirect(redirectInfo, std::move(current_response_)); + return; } } } if (!target_loader_ && target_factory_) { - target_factory_->CreateLoaderAndStart(target_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_, + loader_error_seen_ = false; + target_factory_->CreateLoaderAndStart(target_loader_.BindNewPipeAndPassReceiver(), request_id_, options_, request_, proxied_client_receiver_.BindNewPipeAndPassRemote(), traffic_annotation_); } @@ -339,17 +413,16 @@ void InterceptedRequest::ContinueAfterIntercept() // URLLoaderClient methods. -void InterceptedRequest::OnReceiveResponse(network::mojom::URLResponseHeadPtr head) +void InterceptedRequest::OnReceiveResponse(network::mojom::URLResponseHeadPtr head, mojo::ScopedDataPipeConsumerHandle handle, absl::optional<mojo_base::BigBuffer> buffer) { current_response_ = head.Clone(); - target_client_->OnReceiveResponse(std::move(head)); + target_client_->OnReceiveResponse(std::move(head), std::move(handle), std::move(buffer)); } void InterceptedRequest::OnReceiveRedirect(const net::RedirectInfo &redirect_info, network::mojom::URLResponseHeadPtr head) { // TODO(timvolodine): handle redirect override. - request_was_redirected_ = true; current_response_ = head.Clone(); target_client_->OnReceiveRedirect(redirect_info, std::move(head)); request_.url = redirect_info.new_url; @@ -364,21 +437,11 @@ void InterceptedRequest::OnUploadProgress(int64_t current_position, int64_t tota target_client_->OnUploadProgress(current_position, total_size, std::move(callback)); } -void InterceptedRequest::OnReceiveCachedMetadata(mojo_base::BigBuffer data) -{ - target_client_->OnReceiveCachedMetadata(std::move(data)); -} - void InterceptedRequest::OnTransferSizeUpdated(int32_t transfer_size_diff) { target_client_->OnTransferSizeUpdated(transfer_size_diff); } -void InterceptedRequest::OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle body) -{ - target_client_->OnStartLoadingResponseBody(std::move(body)); -} - void InterceptedRequest::OnComplete(const network::URLLoaderCompletionStatus &status) { // Only wait for the original loader to possibly have a custom error if the @@ -391,10 +454,11 @@ void InterceptedRequest::OnComplete(const network::URLLoaderCompletionStatus &st void InterceptedRequest::FollowRedirect(const std::vector<std::string> &removed_headers, const net::HttpRequestHeaders &modified_headers, - const base::Optional<GURL> &new_url) + const net::HttpRequestHeaders &modified_cors_exempt_headers, + const absl::optional<GURL> &new_url) { if (target_loader_) - target_loader_->FollowRedirect(removed_headers, modified_headers, new_url); + target_loader_->FollowRedirect(removed_headers, modified_headers, modified_cors_exempt_headers, new_url); // If |OnURLLoaderClientError| was called then we're just waiting for the // connection error handler of |proxied_loader_binding_|. Don't restart the @@ -436,6 +500,8 @@ void InterceptedRequest::OnURLLoaderError(uint32_t custom_reason, const std::str // If CallOnComplete was already called, then this object is ready to be deleted. if (!target_client_) delete this; + else + loader_error_seen_ = true; } void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus &status, bool wait_for_loader_error) @@ -449,7 +515,7 @@ void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus if (target_client_) target_client_->OnComplete(status); - if (proxied_loader_receiver_.is_bound() && wait_for_loader_error) { + if (proxied_loader_receiver_.is_bound() && wait_for_loader_error && !loader_error_seen_) { // Since the original client is gone no need to continue loading the // request. proxied_client_receiver_.reset(); @@ -478,10 +544,10 @@ void InterceptedRequest::SendErrorAndCompleteImmediately(int error_code) delete this; } -ProxyingURLLoaderFactoryQt::ProxyingURLLoaderFactoryQt(int process_id, QWebEngineUrlRequestInterceptor *profile, QWebEngineUrlRequestInterceptor *page, +ProxyingURLLoaderFactoryQt::ProxyingURLLoaderFactoryQt(ProfileAdapter *adapter, int frame_tree_node_id, mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver, mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_info) - : m_processId(process_id), m_profileRequestInterceptor(profile), m_pageRequestInterceptor(page), m_weakFactory(this) + : m_profileAdapter(adapter), m_frameTreeNodeId(frame_tree_node_id), m_weakFactory(this) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (target_factory_info) { @@ -499,8 +565,8 @@ ProxyingURLLoaderFactoryQt::~ProxyingURLLoaderFactoryQt() m_weakFactory.InvalidateWeakPtrs(); } -void ProxyingURLLoaderFactoryQt::CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> loader, int32_t routing_id, - int32_t request_id, uint32_t options, const network::ResourceRequest &request, +void ProxyingURLLoaderFactoryQt::CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> loader, int32_t request_id, + uint32_t options, const network::ResourceRequest &request, mojo::PendingRemote<network::mojom::URLLoaderClient> url_loader_client, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) { @@ -510,8 +576,8 @@ void ProxyingURLLoaderFactoryQt::CreateLoaderAndStart(mojo::PendingReceiver<netw m_targetFactory->Clone(target_factory_clone.InitWithNewPipeAndPassReceiver()); // Will manage its own lifetime - InterceptedRequest *req = new InterceptedRequest(m_processId, request_id, routing_id, options, request, traffic_annotation, - m_profileRequestInterceptor, m_pageRequestInterceptor, std::move(loader), + InterceptedRequest *req = new InterceptedRequest(m_profileAdapter, m_frameTreeNodeId, request_id, options, + request, traffic_annotation, std::move(loader), std::move(url_loader_client), std::move(target_factory_clone)); req->Restart(); } |