refactor: make api::WebRequest inherit from gin::Wrappable (#48762)

* refactor: make api::WebRequest inherit from gin::Wrappable

refactor: remove unused v8::Isolate* arg from WebRequest ctor

refactor: make electron::api::Session::web_request_ a cppgc::Member<api::WebRequest>

refactor: allocate api::WebRequest on cpp heap

refactor: modify Create(), Find(), and FindOrCreate() to return a WebRequest*

* refactor: ProxyingURLLoaderFactory takes a concrete api::WebRequest instead of a WebRequestAPI

Experimental commit to ensure `ProxyingURLLoaderFactory::web_request_api_`
won't be a dangling pointer.

* chore: fix doc shear

* refactor: use cppgc::WeakPersistent<> in ProxyingURLLoaderFactory

* refactor: make ProxyingURLLoaderFactory::web_request_ const

* refactor: make ProxyingWebSocket::web_request_ a cppgc::WeakPersistent<>

* add a gin::WeakCellFactory to api::WebRequest

* refactor: use a gin::WeakCell for the bound WebRequest argument in HandleOnBeforeRequestResponseEvent()

* chore: update patches
This commit is contained in:
Charles Kerr
2025-11-12 12:53:00 -06:00
committed by GitHub
parent 27727dbe0a
commit 3c5513015a
9 changed files with 97 additions and 77 deletions

View File

@@ -1360,12 +1360,10 @@ v8::Local<v8::Value> Session::ServiceWorkerContext(v8::Isolate* isolate) {
return service_worker_context_.Get(isolate);
}
v8::Local<v8::Value> Session::WebRequest(v8::Isolate* isolate) {
if (web_request_.IsEmptyThreadSafe()) {
auto handle = WebRequest::Create(base::PassKey<Session>{}, isolate);
web_request_.Reset(isolate, handle.ToV8());
}
return web_request_.Get(isolate);
WebRequest* Session::WebRequest(v8::Isolate* isolate) {
if (!web_request_)
web_request_ = WebRequest::Create(isolate, base::PassKey<Session>{});
return web_request_;
}
NetLog* Session::NetLog(v8::Isolate* isolate) {

View File

@@ -61,6 +61,7 @@ struct PreloadScript;
namespace api {
class NetLog;
class WebRequest;
class Session final : public gin::Wrappable<Session>,
public gin_helper::Constructible<Session>,
@@ -169,7 +170,7 @@ class Session final : public gin::Wrappable<Session>,
v8::Local<v8::Value> Extensions(v8::Isolate* isolate);
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
v8::Local<v8::Value> ServiceWorkerContext(v8::Isolate* isolate);
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
WebRequest* WebRequest(v8::Isolate* isolate);
api::NetLog* NetLog(v8::Isolate* isolate);
void Preconnect(const gin_helper::Dictionary& options, gin::Arguments* args);
v8::Local<v8::Promise> CloseAllConnections();
@@ -217,7 +218,7 @@ class Session final : public gin::Wrappable<Session>,
v8::TracedReference<v8::Value> protocol_;
cppgc::Member<api::NetLog> net_log_;
v8::TracedReference<v8::Value> service_worker_context_;
v8::TracedReference<v8::Value> web_request_;
cppgc::Member<api::WebRequest> web_request_;
raw_ptr<v8::Isolate> isolate_;

View File

@@ -22,6 +22,7 @@
#include "gin/converter.h"
#include "gin/dictionary.h"
#include "gin/object_template_builder.h"
#include "gin/persistent.h"
#include "shell/browser/api/electron_api_session.h"
#include "shell/browser/api/electron_api_web_contents.h"
#include "shell/browser/api/electron_api_web_frame_main.h"
@@ -204,7 +205,8 @@ CalculateOnBeforeSendHeadersDelta(const net::HttpRequestHeaders* old_headers,
} // namespace
gin::DeprecatedWrapperInfo WebRequest::kWrapperInfo = {gin::kEmbedderNativeGin};
const gin::WrapperInfo WebRequest::kWrapperInfo = {{gin::kEmbedderNativeGin},
gin::kElectronWebRequest};
WebRequest::RequestFilter::RequestFilter(
std::set<URLPattern> include_url_patterns,
@@ -318,8 +320,7 @@ WebRequest::~WebRequest() = default;
gin::ObjectTemplateBuilder WebRequest::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return gin_helper::DeprecatedWrappable<WebRequest>::GetObjectTemplateBuilder(
isolate)
return gin::Wrappable<WebRequest>::GetObjectTemplateBuilder(isolate)
.SetMethod(
"onBeforeRequest",
&WebRequest::SetResponseListener<ResponseEvent::kOnBeforeRequest>)
@@ -342,8 +343,17 @@ gin::ObjectTemplateBuilder WebRequest::GetObjectTemplateBuilder(
&WebRequest::SetSimpleListener<SimpleEvent::kOnCompleted>);
}
const char* WebRequest::GetTypeName() {
return GetClassName();
const gin::WrapperInfo* WebRequest::wrapper_info() const {
return &kWrapperInfo;
}
const char* WebRequest::GetHumanReadableName() const {
return "Electron / WebRequest";
}
void WebRequest::Trace(cppgc::Visitor* visitor) const {
gin::Wrappable<WebRequest>::Trace(visitor);
visitor->Trace(weak_factory_);
}
bool WebRequest::HasListener() const {
@@ -381,9 +391,11 @@ int WebRequest::HandleOnBeforeRequestResponseEvent(
gin_helper::Dictionary details(isolate, v8::Object::New(isolate));
FillDetails(&details, request_info, request, *new_url);
ResponseCallback response =
base::BindOnce(&WebRequest::OnBeforeRequestListenerResult,
base::Unretained(this), request_info->id);
auto& allocation_handle = isolate->GetCppHeap()->GetAllocationHandle();
ResponseCallback response = base::BindOnce(
&WebRequest::OnBeforeRequestListenerResult,
gin::WrapPersistent(weak_factory_.GetWeakCell(allocation_handle)),
request_info->id);
info.listener.Run(gin::ConvertToV8(isolate, details), std::move(response));
return net::ERR_IO_PENDING;
}
@@ -777,22 +789,16 @@ void WebRequest::OnLoginAuthResult(
}
// static
gin_helper::Handle<WebRequest> WebRequest::FromOrCreate(
v8::Isolate* isolate,
content::BrowserContext* browser_context) {
v8::Local<v8::Value> web_request =
Session::FromOrCreate(isolate, browser_context)->WebRequest(isolate);
gin_helper::Handle<WebRequest> handle;
gin::ConvertFromV8(isolate, web_request, &handle);
DCHECK(!handle.IsEmpty());
return handle;
WebRequest* WebRequest::FromOrCreate(v8::Isolate* isolate,
content::BrowserContext* browser_context) {
return Session::FromOrCreate(isolate, browser_context)->WebRequest(isolate);
}
// static
gin_helper::Handle<WebRequest> WebRequest::Create(
base::PassKey<Session> passkey,
v8::Isolate* isolate) {
return gin_helper::CreateHandle(isolate, new WebRequest{std::move(passkey)});
WebRequest* WebRequest::Create(v8::Isolate* isolate,
base::PassKey<Session> passkey) {
return cppgc::MakeGarbageCollected<WebRequest>(
isolate->GetCppHeap()->GetAllocationHandle(), std::move(passkey));
}
} // namespace electron::api

View File

@@ -10,9 +10,10 @@
#include <string>
#include "base/types/pass_key.h"
#include "gin/weak_cell.h"
#include "gin/wrappable.h"
#include "net/base/completion_once_callback.h"
#include "services/network/public/cpp/resource_request.h"
#include "shell/common/gin_helper/wrappable.h"
class URLPattern;
@@ -38,7 +39,7 @@ namespace electron::api {
class Session;
class WebRequest final : public gin_helper::DeprecatedWrappable<WebRequest> {
class WebRequest final : public gin::Wrappable<WebRequest> {
public:
using BeforeSendHeadersCallback =
base::OnceCallback<void(const std::set<std::string>& removed_headers,
@@ -65,21 +66,29 @@ class WebRequest final : public gin_helper::DeprecatedWrappable<WebRequest> {
// Convenience wrapper around api::Session::FromOrCreate()->WebRequest().
// Creates the Session and WebRequest if they don't already exist.
// Note that the WebRequest is owned by the session, not by the caller.
static gin_helper::Handle<WebRequest> FromOrCreate(
v8::Isolate* isolate,
content::BrowserContext* browser_context);
static WebRequest* FromOrCreate(v8::Isolate* isolate,
content::BrowserContext* browser_context);
// Return a new WebRequest object. This can only be called by api::Session.
static gin_helper::Handle<WebRequest> Create(base::PassKey<Session>,
v8::Isolate* isolate);
static WebRequest* Create(v8::Isolate* isolate, base::PassKey<Session>);
// Make public for cppgc::MakeGarbageCollected.
explicit WebRequest(base::PassKey<Session>);
~WebRequest() override;
// disable copy
WebRequest(const WebRequest&) = delete;
WebRequest& operator=(const WebRequest&) = delete;
static const char* GetClassName() { return "WebRequest"; }
// gin_helper::Wrappable:
static gin::DeprecatedWrapperInfo kWrapperInfo;
// gin::Wrappable:
static const gin::WrapperInfo kWrapperInfo;
void Trace(cppgc::Visitor*) const override;
const gin::WrapperInfo* wrapper_info() const override;
const char* GetHumanReadableName() const override;
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
const char* GetTypeName() override;
bool HasListener() const;
int OnBeforeRequest(extensions::WebRequestInfo* info,
@@ -118,9 +127,6 @@ class WebRequest final : public gin_helper::DeprecatedWrappable<WebRequest> {
void OnRequestWillBeDestroyed(extensions::WebRequestInfo* info);
private:
explicit WebRequest(base::PassKey<Session>);
~WebRequest() override;
// Contains info about requests that are blocked waiting for a response from
// the user.
struct BlockedRequest;
@@ -235,6 +241,8 @@ class WebRequest final : public gin_helper::DeprecatedWrappable<WebRequest> {
std::map<SimpleEvent, SimpleListenerInfo> simple_listeners_;
std::map<ResponseEvent, ResponseListenerInfo> response_listeners_;
std::map<uint64_t, BlockedRequest> blocked_requests_;
gin::WeakCellFactory<WebRequest> weak_factory_{this};
};
} // namespace electron::api