diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 1ccbbd361993..a469248a5280 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -5,10 +5,7 @@ const { EventEmitter } = require('events'); const { Readable, Writable } = require('stream'); const { app } = require('electron'); const { Session } = process.electronBinding('session'); -const { net, Net, _isValidHeaderName, _isValidHeaderValue } = process.electronBinding('net'); -const { URLLoader } = net; - -Object.setPrototypeOf(URLLoader.prototype, EventEmitter.prototype); +const { net, Net, isValidHeaderName, isValidHeaderValue, createURLLoader } = process.electronBinding('net'); const kSupportedProtocols = new Set(['http:', 'https:']); @@ -240,10 +237,10 @@ function parseOptions (options) { useSessionCookies: options.useSessionCookies || false }; for (const [name, value] of Object.entries(urlLoaderOptions.extraHeaders)) { - if (!_isValidHeaderName(name)) { + if (!isValidHeaderName(name)) { throw new Error(`Invalid header name: '${name}'`); } - if (!_isValidHeaderValue(value.toString())) { + if (!isValidHeaderValue(value.toString())) { throw new Error(`Invalid value for header '${name}': '${value}'`); } } @@ -307,10 +304,10 @@ class ClientRequest extends Writable { if (this._started || this._firstWrite) { throw new Error('Can\'t set headers after they are sent'); } - if (!_isValidHeaderName(name)) { + if (!isValidHeaderName(name)) { throw new Error(`Invalid header name: '${name}'`); } - if (!_isValidHeaderValue(value.toString())) { + if (!isValidHeaderValue(value.toString())) { throw new Error(`Invalid value for header '${name}': '${value}'`); } @@ -374,7 +371,7 @@ class ClientRequest extends Writable { return ret; }; const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) }; - this._urlLoader = new URLLoader(opts); + this._urlLoader = createURLLoader(opts); this._urlLoader.on('response-started', (event, finalUrl, responseHead) => { const response = this._response = new IncomingMessage(responseHead); this.emit('response', response); diff --git a/shell/browser/api/electron_api_net.cc b/shell/browser/api/electron_api_net.cc index 647eabc17d7d..4382ebe3c4ff 100644 --- a/shell/browser/api/electron_api_net.cc +++ b/shell/browser/api/electron_api_net.cc @@ -33,15 +33,6 @@ v8::Local Net::Create(v8::Isolate* isolate) { void Net::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { prototype->SetClassName(gin::StringToV8(isolate, "Net")); - gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) - .SetProperty("URLLoader", &Net::URLLoader); -} - -v8::Local Net::URLLoader(v8::Isolate* isolate) { - v8::Local constructor; - constructor = SimpleURLLoaderWrapper::GetConstructor(isolate); - return constructor->GetFunction(isolate->GetCurrentContext()) - .ToLocalChecked(); } } // namespace api @@ -67,15 +58,13 @@ void Initialize(v8::Local exports, void* priv) { v8::Isolate* isolate = context->GetIsolate(); - SimpleURLLoaderWrapper::SetConstructor( - isolate, base::BindRepeating(SimpleURLLoaderWrapper::New)); - gin_helper::Dictionary dict(isolate, exports); dict.Set("net", Net::Create(isolate)); dict.Set("Net", Net::GetConstructor(isolate)->GetFunction(context).ToLocalChecked()); - dict.SetMethod("_isValidHeaderName", &IsValidHeaderName); - dict.SetMethod("_isValidHeaderValue", &IsValidHeaderValue); + dict.SetMethod("isValidHeaderName", &IsValidHeaderName); + dict.SetMethod("isValidHeaderValue", &IsValidHeaderValue); + dict.SetMethod("createURLLoader", &SimpleURLLoaderWrapper::Create); } } // namespace diff --git a/shell/browser/api/electron_api_url_loader.cc b/shell/browser/api/electron_api_url_loader.cc index e18b7229d2da..801e3e761f9d 100644 --- a/shell/browser/api/electron_api_url_loader.cc +++ b/shell/browser/api/electron_api_url_loader.cc @@ -247,6 +247,9 @@ base::IDMap& GetAllRequests() { } // namespace +gin::WrapperInfo SimpleURLLoaderWrapper::kWrapperInfo = { + gin::kEmbedderNativeGin}; + SimpleURLLoaderWrapper::SimpleURLLoaderWrapper( std::unique_ptr request, network::mojom::URLLoaderFactory* url_loader_factory) @@ -279,14 +282,14 @@ SimpleURLLoaderWrapper::SimpleURLLoaderWrapper( } void SimpleURLLoaderWrapper::Pin() { - // Prevent ourselves from being GC'd until the request is complete. - // Must be called after InitWithArgs(), otherwise GetWrapper() isn't - // initialized. - pinned_wrapper_.Reset(isolate(), GetWrapper()); + // Prevent ourselves from being GC'd until the request is complete. Must be + // called after gin::CreateHandle, otherwise the wrapper isn't initialized. + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + pinned_wrapper_.Reset(isolate, GetWrapper(isolate).ToLocalChecked()); } void SimpleURLLoaderWrapper::PinBodyGetter(v8::Local body_getter) { - pinned_chunk_pipe_getter_.Reset(isolate(), body_getter); + pinned_chunk_pipe_getter_.Reset(v8::Isolate::GetCurrent(), body_getter); } SimpleURLLoaderWrapper::~SimpleURLLoaderWrapper() { @@ -338,11 +341,12 @@ void SimpleURLLoaderWrapper::Cancel() { } // static -gin_helper::WrappableBase* SimpleURLLoaderWrapper::New(gin::Arguments* args) { +gin::Handle SimpleURLLoaderWrapper::Create( + gin::Arguments* args) { gin_helper::Dictionary opts; if (!args->GetNext(&opts)) { args->ThrowTypeError("Expected a dictionary"); - return nullptr; + return gin::Handle(); } auto request = std::make_unique(); request->attach_same_site_cookies = true; @@ -354,7 +358,7 @@ gin_helper::WrappableBase* SimpleURLLoaderWrapper::New(gin::Arguments* args) { if (!net::HttpUtil::IsValidHeaderName(it.first) || !net::HttpUtil::IsValidHeaderValue(it.second)) { args->ThrowTypeError("Invalid header name or value"); - return nullptr; + return gin::Handle(); } request->headers.SetHeader(it.first, it.second); } @@ -404,9 +408,9 @@ gin_helper::WrappableBase* SimpleURLLoaderWrapper::New(gin::Arguments* args) { auto url_loader_factory = session->browser_context()->GetURLLoaderFactory(); - auto* ret = - new SimpleURLLoaderWrapper(std::move(request), url_loader_factory.get()); - ret->InitWithArgs(args); + auto ret = gin::CreateHandle( + args->isolate(), + new SimpleURLLoaderWrapper(std::move(request), url_loader_factory.get())); ret->Pin(); if (!chunk_pipe_getter.IsEmpty()) { ret->PinBodyGetter(chunk_pipe_getter); @@ -417,8 +421,9 @@ gin_helper::WrappableBase* SimpleURLLoaderWrapper::New(gin::Arguments* args) { void SimpleURLLoaderWrapper::OnDataReceived(base::StringPiece string_piece, base::OnceClosure resume) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - v8::HandleScope handle_scope(isolate()); - auto array_buffer = v8::ArrayBuffer::New(isolate(), string_piece.size()); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + auto array_buffer = v8::ArrayBuffer::New(isolate, string_piece.size()); auto backing_store = array_buffer->GetBackingStore(); memcpy(backing_store->Data(), string_piece.data(), string_piece.size()); Emit("data", array_buffer); @@ -441,8 +446,9 @@ void SimpleURLLoaderWrapper::OnRetry(base::OnceClosure start_retry) {} void SimpleURLLoaderWrapper::OnResponseStarted( const GURL& final_url, const network::mojom::URLResponseHead& response_head) { - v8::HandleScope scope(isolate()); - gin::Dictionary dict = gin::Dictionary::CreateEmpty(isolate()); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + gin::Dictionary dict = gin::Dictionary::CreateEmpty(isolate); dict.Set("statusCode", response_head.headers->response_code()); dict.Set("statusMessage", response_head.headers->GetStatusText()); dict.Set("httpVersion", response_head.headers->GetHttpVersion()); @@ -471,14 +477,17 @@ void SimpleURLLoaderWrapper::OnDownloadProgress(uint64_t current) { } // static -void SimpleURLLoaderWrapper::BuildPrototype( - v8::Isolate* isolate, - v8::Local prototype) { - prototype->SetClassName(gin::StringToV8(isolate, "SimpleURLLoaderWrapper")); - gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) +gin::ObjectTemplateBuilder SimpleURLLoaderWrapper::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return gin_helper::EventEmitterMixin< + SimpleURLLoaderWrapper>::GetObjectTemplateBuilder(isolate) .SetMethod("cancel", &SimpleURLLoaderWrapper::Cancel); } +const char* SimpleURLLoaderWrapper::GetTypeName() { + return "SimpleURLLoaderWrapper"; +} + } // namespace api } // namespace electron diff --git a/shell/browser/api/electron_api_url_loader.h b/shell/browser/api/electron_api_url_loader.h index 6cffcd91c616..80ef2d8b06ab 100644 --- a/shell/browser/api/electron_api_url_loader.h +++ b/shell/browser/api/electron_api_url_loader.h @@ -10,18 +10,21 @@ #include #include "base/memory/weak_ptr.h" +#include "gin/wrappable.h" #include "net/base/auth.h" #include "services/network/public/cpp/simple_url_loader_stream_consumer.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom-forward.h" #include "services/network/public/mojom/url_response_head.mojom.h" -#include "shell/common/gin_helper/event_emitter.h" +#include "shell/browser/event_emitter_mixin.h" #include "url/gurl.h" #include "v8/include/v8.h" namespace gin { class Arguments; -} +template +class Handle; +} // namespace gin namespace network { class SimpleURLLoader; @@ -34,14 +37,12 @@ namespace api { /** Wraps a SimpleURLLoader to make it usable from JavaScript */ class SimpleURLLoaderWrapper - : public gin_helper::EventEmitter, + : public gin::Wrappable, + public gin_helper::EventEmitterMixin, public network::SimpleURLLoaderStreamConsumer { public: ~SimpleURLLoaderWrapper() override; - static gin_helper::WrappableBase* New(gin::Arguments* args); - - static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + static gin::Handle Create(gin::Arguments* args); static SimpleURLLoaderWrapper* FromID(uint32_t id); @@ -55,6 +56,12 @@ class SimpleURLLoaderWrapper void Cancel(); + // gin::Wrappable + static gin::WrapperInfo kWrapperInfo; + gin::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + const char* GetTypeName() override; + private: SimpleURLLoaderWrapper(std::unique_ptr loader, network::mojom::URLLoaderFactory* url_loader_factory);