fix: use BlockedRequest struct to handle webRequest data (#42647)

Fixes an issue where Chromium could crash on a dangling unretained pointer in one of several webRequest functions. This was happening as a result of the fact that we had outstanding blocking requests continue to reference state owned by ProxyingWebsocket and ProxyingURLLoaderFactory after the requests were destroyed.

This had been going on for a few years, and was likely leading to some ongoing memory issues. To fix this, we need to ensure that all state is cleaned up in OnRequestWillBeDestroyed. I chose to create a new BlockedRequest struct to do so, which approximates the approach that upstream takes. The complexities of doing so also made our templated approach more trouble than it felt worth, so i pried that apart into separate handlers.
This commit is contained in:
Shelley Vohr 2024-07-02 14:02:49 +02:00 committed by GitHub
parent 8a8241163d
commit 1729a9868c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 304 additions and 111 deletions

View file

@ -84,6 +84,10 @@ class WebRequest : public gin::Wrappable<WebRequest>, public WebRequestAPI {
WebRequest(v8::Isolate* isolate, content::BrowserContext* browser_context);
~WebRequest() override;
// Contains info about requests that are blocked waiting for a response from
// the user.
struct BlockedRequest;
enum class SimpleEvent {
kOnSendHeaders,
kOnBeforeRedirect,
@ -91,6 +95,7 @@ class WebRequest : public gin::Wrappable<WebRequest>, public WebRequestAPI {
kOnCompleted,
kOnErrorOccurred,
};
enum class ResponseEvent {
kOnBeforeRequest,
kOnBeforeSendHeaders,
@ -113,15 +118,30 @@ class WebRequest : public gin::Wrappable<WebRequest>, public WebRequestAPI {
void HandleSimpleEvent(SimpleEvent event,
extensions::WebRequestInfo* info,
Args... args);
template <typename Out, typename... Args>
int HandleResponseEvent(ResponseEvent event,
extensions::WebRequestInfo* info,
net::CompletionOnceCallback callback,
Out out,
Args... args);
template <typename T>
void OnListenerResult(uint64_t id, T out, v8::Local<v8::Value> response);
int HandleOnBeforeRequestResponseEvent(
extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
net::CompletionOnceCallback callback,
GURL* redirect_url);
int HandleOnBeforeSendHeadersResponseEvent(
extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
BeforeSendHeadersCallback callback,
net::HttpRequestHeaders* headers);
int HandleOnHeadersReceivedResponseEvent(
extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
net::CompletionOnceCallback callback,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers);
void OnBeforeRequestListenerResult(uint64_t id,
v8::Local<v8::Value> response);
void OnBeforeSendHeadersListenerResult(uint64_t id,
v8::Local<v8::Value> response);
void OnHeadersReceivedListenerResult(uint64_t id,
v8::Local<v8::Value> response);
class RequestFilter {
public:
@ -164,7 +184,7 @@ class WebRequest : public gin::Wrappable<WebRequest>, public WebRequestAPI {
std::map<SimpleEvent, SimpleListenerInfo> simple_listeners_;
std::map<ResponseEvent, ResponseListenerInfo> response_listeners_;
std::map<uint64_t, net::CompletionOnceCallback> callbacks_;
std::map<uint64_t, BlockedRequest> blocked_requests_;
// Weak-ref, it manages us.
raw_ptr<content::BrowserContext> browser_context_;