fix: access violation during redirects (intercepted requests) (#25393)
* fix: don't delete loader factory when request is pending When intercepted request is pending we need to make sure that loader factory is not deleted, especially when redirect occurs. Otherwise, it may cause access violation. * fix: added logic that removes requests from collection * fix: fixed lint errors * fix: fixed review remark * fix: fixed review remarks Removed intercepted_requests_ collection and leverage pending_receivers_. * fix: brought back removed line
This commit is contained in:
parent
125c5a6e9b
commit
8207f6901d
3 changed files with 48 additions and 31 deletions
|
@ -200,11 +200,22 @@ void ElectronURLLoaderFactory::CreateLoaderAndStart(
|
||||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||||
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
|
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
|
||||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||||
handler_.Run(
|
mojo::PendingRemote<network::mojom::URLLoaderFactory> proxy_factory;
|
||||||
request,
|
handler_.Run(request, base::BindOnce(&ElectronURLLoaderFactory::StartLoading,
|
||||||
base::BindOnce(&ElectronURLLoaderFactory::StartLoading, std::move(loader),
|
std::move(loader), routing_id,
|
||||||
routing_id, request_id, options, request,
|
request_id, options, request,
|
||||||
std::move(client), traffic_annotation, nullptr, type_));
|
std::move(client), traffic_annotation,
|
||||||
|
std::move(proxy_factory), type_));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void ElectronURLLoaderFactory::OnComplete(
|
||||||
|
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||||
|
int32_t request_id,
|
||||||
|
const network::URLLoaderCompletionStatus& status) {
|
||||||
|
mojo::Remote<network::mojom::URLLoaderClient> client_remote(
|
||||||
|
std::move(client));
|
||||||
|
client_remote->OnComplete(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -216,7 +227,7 @@ void ElectronURLLoaderFactory::StartLoading(
|
||||||
const network::ResourceRequest& request,
|
const network::ResourceRequest& request,
|
||||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||||
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
|
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
|
||||||
network::mojom::URLLoaderFactory* proxy_factory,
|
mojo::PendingRemote<network::mojom::URLLoaderFactory> proxy_factory,
|
||||||
ProtocolType type,
|
ProtocolType type,
|
||||||
gin::Arguments* args) {
|
gin::Arguments* args) {
|
||||||
// Send network error when there is no argument passed.
|
// Send network error when there is no argument passed.
|
||||||
|
@ -225,10 +236,8 @@ void ElectronURLLoaderFactory::StartLoading(
|
||||||
// passed, to keep compatibility with old code.
|
// passed, to keep compatibility with old code.
|
||||||
v8::Local<v8::Value> response;
|
v8::Local<v8::Value> response;
|
||||||
if (!args->GetNext(&response)) {
|
if (!args->GetNext(&response)) {
|
||||||
mojo::Remote<network::mojom::URLLoaderClient> client_remote(
|
OnComplete(std::move(client), request_id,
|
||||||
std::move(client));
|
network::URLLoaderCompletionStatus(net::ERR_NOT_IMPLEMENTED));
|
||||||
client_remote->OnComplete(
|
|
||||||
network::URLLoaderCompletionStatus(net::ERR_NOT_IMPLEMENTED));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,9 +246,8 @@ void ElectronURLLoaderFactory::StartLoading(
|
||||||
if (!dict.IsEmpty()) {
|
if (!dict.IsEmpty()) {
|
||||||
int error_code;
|
int error_code;
|
||||||
if (dict.Get("error", &error_code)) {
|
if (dict.Get("error", &error_code)) {
|
||||||
mojo::Remote<network::mojom::URLLoaderClient> client_remote(
|
OnComplete(std::move(client), request_id,
|
||||||
std::move(client));
|
network::URLLoaderCompletionStatus(error_code));
|
||||||
client_remote->OnComplete(network::URLLoaderCompletionStatus(error_code));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,10 +294,14 @@ void ElectronURLLoaderFactory::StartLoading(
|
||||||
// module.
|
// module.
|
||||||
//
|
//
|
||||||
// I'm not sure whether this is an intended behavior in Chromium.
|
// I'm not sure whether this is an intended behavior in Chromium.
|
||||||
if (proxy_factory) {
|
mojo::Remote<network::mojom::URLLoaderFactory> proxy_factory_remote(
|
||||||
proxy_factory->CreateLoaderAndStart(
|
std::move(proxy_factory));
|
||||||
|
|
||||||
|
if (proxy_factory_remote.is_bound()) {
|
||||||
|
proxy_factory_remote->CreateLoaderAndStart(
|
||||||
std::move(loader), routing_id, request_id, options, new_request,
|
std::move(loader), routing_id, request_id, options, new_request,
|
||||||
std::move(client), traffic_annotation);
|
std::move(client), traffic_annotation);
|
||||||
|
proxy_factory = proxy_factory_remote.Unbind();
|
||||||
} else {
|
} else {
|
||||||
StartLoadingHttp(std::move(loader), new_request, std::move(client),
|
StartLoadingHttp(std::move(loader), new_request, std::move(client),
|
||||||
traffic_annotation,
|
traffic_annotation,
|
||||||
|
@ -300,10 +312,8 @@ void ElectronURLLoaderFactory::StartLoading(
|
||||||
|
|
||||||
// Some protocol accepts non-object responses.
|
// Some protocol accepts non-object responses.
|
||||||
if (dict.IsEmpty() && ResponseMustBeObject(type)) {
|
if (dict.IsEmpty() && ResponseMustBeObject(type)) {
|
||||||
mojo::Remote<network::mojom::URLLoaderClient> client_remote(
|
OnComplete(std::move(client), request_id,
|
||||||
std::move(client));
|
network::URLLoaderCompletionStatus(net::ERR_NOT_IMPLEMENTED));
|
||||||
client_remote->OnComplete(
|
|
||||||
network::URLLoaderCompletionStatus(net::ERR_NOT_IMPLEMENTED));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,15 +340,13 @@ void ElectronURLLoaderFactory::StartLoading(
|
||||||
case ProtocolType::kFree:
|
case ProtocolType::kFree:
|
||||||
ProtocolType type;
|
ProtocolType type;
|
||||||
if (!gin::ConvertFromV8(args->isolate(), response, &type)) {
|
if (!gin::ConvertFromV8(args->isolate(), response, &type)) {
|
||||||
mojo::Remote<network::mojom::URLLoaderClient> client_remote(
|
OnComplete(std::move(client), request_id,
|
||||||
std::move(client));
|
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
||||||
client_remote->OnComplete(
|
|
||||||
network::URLLoaderCompletionStatus(net::ERR_FAILED));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
StartLoading(std::move(loader), routing_id, request_id, options, request,
|
StartLoading(std::move(loader), routing_id, request_id, options, request,
|
||||||
std::move(client), traffic_annotation, proxy_factory, type,
|
std::move(client), traffic_annotation,
|
||||||
args);
|
std::move(proxy_factory), type, args);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class ElectronURLLoaderFactory
|
||||||
const network::ResourceRequest& request,
|
const network::ResourceRequest& request,
|
||||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||||
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
|
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
|
||||||
network::mojom::URLLoaderFactory* proxy_factory,
|
mojo::PendingRemote<network::mojom::URLLoaderFactory> proxy_factory,
|
||||||
ProtocolType type,
|
ProtocolType type,
|
||||||
gin::Arguments* args);
|
gin::Arguments* args);
|
||||||
|
|
||||||
|
@ -77,6 +77,10 @@ class ElectronURLLoaderFactory
|
||||||
mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver);
|
mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver);
|
||||||
~ElectronURLLoaderFactory() override;
|
~ElectronURLLoaderFactory() override;
|
||||||
|
|
||||||
|
static void OnComplete(
|
||||||
|
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||||
|
int32_t request_id,
|
||||||
|
const network::URLLoaderCompletionStatus& status);
|
||||||
static void StartLoadingBuffer(
|
static void StartLoadingBuffer(
|
||||||
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
|
||||||
network::mojom::URLResponseHeadPtr head,
|
network::mojom::URLResponseHeadPtr head,
|
||||||
|
|
|
@ -801,12 +801,16 @@ void ProxyingURLLoaderFactory::CreateLoaderAndStart(
|
||||||
// Check if user has intercepted this scheme.
|
// Check if user has intercepted this scheme.
|
||||||
auto it = intercepted_handlers_.find(request.url.scheme());
|
auto it = intercepted_handlers_.find(request.url.scheme());
|
||||||
if (it != intercepted_handlers_.end()) {
|
if (it != intercepted_handlers_.end()) {
|
||||||
|
mojo::Remote<network::mojom::URLLoaderFactory> loader_remote;
|
||||||
|
this->Clone(loader_remote.BindNewPipeAndPassReceiver());
|
||||||
|
|
||||||
// <scheme, <type, handler>>
|
// <scheme, <type, handler>>
|
||||||
it->second.second.Run(
|
it->second.second.Run(
|
||||||
request, base::BindOnce(&ElectronURLLoaderFactory::StartLoading,
|
request,
|
||||||
std::move(loader), routing_id, request_id,
|
base::BindOnce(&ElectronURLLoaderFactory::StartLoading,
|
||||||
options, request, std::move(client),
|
std::move(loader), routing_id, request_id, options,
|
||||||
traffic_annotation, this, it->second.first));
|
request, std::move(client), traffic_annotation,
|
||||||
|
loader_remote.Unbind(), it->second.first));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -896,7 +900,8 @@ void ProxyingURLLoaderFactory::RemoveRequest(int32_t network_service_request_id,
|
||||||
void ProxyingURLLoaderFactory::MaybeDeleteThis() {
|
void ProxyingURLLoaderFactory::MaybeDeleteThis() {
|
||||||
// Even if all URLLoaderFactory pipes connected to this object have been
|
// Even if all URLLoaderFactory pipes connected to this object have been
|
||||||
// closed it has to stay alive until all active requests have completed.
|
// closed it has to stay alive until all active requests have completed.
|
||||||
if (target_factory_.is_bound() || !requests_.empty())
|
if (target_factory_.is_bound() || !requests_.empty() ||
|
||||||
|
!proxy_receivers_.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
delete this;
|
delete this;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue