refactor: ginify net.request (#22779)

This commit is contained in:
Jeremy Apthorp 2020-03-23 13:09:45 -07:00 committed by GitHub
parent d3d7b3eb54
commit decbca734f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 50 deletions

View file

@ -5,10 +5,7 @@ const { EventEmitter } = require('events');
const { Readable, Writable } = require('stream'); const { Readable, Writable } = require('stream');
const { app } = require('electron'); const { app } = require('electron');
const { Session } = process.electronBinding('session'); const { Session } = process.electronBinding('session');
const { net, Net, _isValidHeaderName, _isValidHeaderValue } = process.electronBinding('net'); const { net, Net, isValidHeaderName, isValidHeaderValue, createURLLoader } = process.electronBinding('net');
const { URLLoader } = net;
Object.setPrototypeOf(URLLoader.prototype, EventEmitter.prototype);
const kSupportedProtocols = new Set(['http:', 'https:']); const kSupportedProtocols = new Set(['http:', 'https:']);
@ -240,10 +237,10 @@ function parseOptions (options) {
useSessionCookies: options.useSessionCookies || false useSessionCookies: options.useSessionCookies || false
}; };
for (const [name, value] of Object.entries(urlLoaderOptions.extraHeaders)) { for (const [name, value] of Object.entries(urlLoaderOptions.extraHeaders)) {
if (!_isValidHeaderName(name)) { if (!isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${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}'`); throw new Error(`Invalid value for header '${name}': '${value}'`);
} }
} }
@ -307,10 +304,10 @@ class ClientRequest extends Writable {
if (this._started || this._firstWrite) { if (this._started || this._firstWrite) {
throw new Error('Can\'t set headers after they are sent'); throw new Error('Can\'t set headers after they are sent');
} }
if (!_isValidHeaderName(name)) { if (!isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${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}'`); throw new Error(`Invalid value for header '${name}': '${value}'`);
} }
@ -374,7 +371,7 @@ class ClientRequest extends Writable {
return ret; return ret;
}; };
const opts = { ...this._urlLoaderOptions, extraHeaders: stringifyValues(this._urlLoaderOptions.extraHeaders) }; 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) => { this._urlLoader.on('response-started', (event, finalUrl, responseHead) => {
const response = this._response = new IncomingMessage(responseHead); const response = this._response = new IncomingMessage(responseHead);
this.emit('response', response); this.emit('response', response);

View file

@ -33,15 +33,6 @@ v8::Local<v8::Value> Net::Create(v8::Isolate* isolate) {
void Net::BuildPrototype(v8::Isolate* isolate, void Net::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) { v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(gin::StringToV8(isolate, "Net")); prototype->SetClassName(gin::StringToV8(isolate, "Net"));
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetProperty("URLLoader", &Net::URLLoader);
}
v8::Local<v8::Value> Net::URLLoader(v8::Isolate* isolate) {
v8::Local<v8::FunctionTemplate> constructor;
constructor = SimpleURLLoaderWrapper::GetConstructor(isolate);
return constructor->GetFunction(isolate->GetCurrentContext())
.ToLocalChecked();
} }
} // namespace api } // namespace api
@ -67,15 +58,13 @@ void Initialize(v8::Local<v8::Object> exports,
void* priv) { void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
SimpleURLLoaderWrapper::SetConstructor(
isolate, base::BindRepeating(SimpleURLLoaderWrapper::New));
gin_helper::Dictionary dict(isolate, exports); gin_helper::Dictionary dict(isolate, exports);
dict.Set("net", Net::Create(isolate)); dict.Set("net", Net::Create(isolate));
dict.Set("Net", dict.Set("Net",
Net::GetConstructor(isolate)->GetFunction(context).ToLocalChecked()); Net::GetConstructor(isolate)->GetFunction(context).ToLocalChecked());
dict.SetMethod("_isValidHeaderName", &IsValidHeaderName); dict.SetMethod("isValidHeaderName", &IsValidHeaderName);
dict.SetMethod("_isValidHeaderValue", &IsValidHeaderValue); dict.SetMethod("isValidHeaderValue", &IsValidHeaderValue);
dict.SetMethod("createURLLoader", &SimpleURLLoaderWrapper::Create);
} }
} // namespace } // namespace

View file

@ -247,6 +247,9 @@ base::IDMap<SimpleURLLoaderWrapper*>& GetAllRequests() {
} // namespace } // namespace
gin::WrapperInfo SimpleURLLoaderWrapper::kWrapperInfo = {
gin::kEmbedderNativeGin};
SimpleURLLoaderWrapper::SimpleURLLoaderWrapper( SimpleURLLoaderWrapper::SimpleURLLoaderWrapper(
std::unique_ptr<network::ResourceRequest> request, std::unique_ptr<network::ResourceRequest> request,
network::mojom::URLLoaderFactory* url_loader_factory) network::mojom::URLLoaderFactory* url_loader_factory)
@ -279,14 +282,14 @@ SimpleURLLoaderWrapper::SimpleURLLoaderWrapper(
} }
void SimpleURLLoaderWrapper::Pin() { void SimpleURLLoaderWrapper::Pin() {
// Prevent ourselves from being GC'd until the request is complete. // Prevent ourselves from being GC'd until the request is complete. Must be
// Must be called after InitWithArgs(), otherwise GetWrapper() isn't // called after gin::CreateHandle, otherwise the wrapper isn't initialized.
// initialized. v8::Isolate* isolate = v8::Isolate::GetCurrent();
pinned_wrapper_.Reset(isolate(), GetWrapper()); pinned_wrapper_.Reset(isolate, GetWrapper(isolate).ToLocalChecked());
} }
void SimpleURLLoaderWrapper::PinBodyGetter(v8::Local<v8::Value> body_getter) { void SimpleURLLoaderWrapper::PinBodyGetter(v8::Local<v8::Value> body_getter) {
pinned_chunk_pipe_getter_.Reset(isolate(), body_getter); pinned_chunk_pipe_getter_.Reset(v8::Isolate::GetCurrent(), body_getter);
} }
SimpleURLLoaderWrapper::~SimpleURLLoaderWrapper() { SimpleURLLoaderWrapper::~SimpleURLLoaderWrapper() {
@ -338,11 +341,12 @@ void SimpleURLLoaderWrapper::Cancel() {
} }
// static // static
gin_helper::WrappableBase* SimpleURLLoaderWrapper::New(gin::Arguments* args) { gin::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
gin::Arguments* args) {
gin_helper::Dictionary opts; gin_helper::Dictionary opts;
if (!args->GetNext(&opts)) { if (!args->GetNext(&opts)) {
args->ThrowTypeError("Expected a dictionary"); args->ThrowTypeError("Expected a dictionary");
return nullptr; return gin::Handle<SimpleURLLoaderWrapper>();
} }
auto request = std::make_unique<network::ResourceRequest>(); auto request = std::make_unique<network::ResourceRequest>();
request->attach_same_site_cookies = true; request->attach_same_site_cookies = true;
@ -354,7 +358,7 @@ gin_helper::WrappableBase* SimpleURLLoaderWrapper::New(gin::Arguments* args) {
if (!net::HttpUtil::IsValidHeaderName(it.first) || if (!net::HttpUtil::IsValidHeaderName(it.first) ||
!net::HttpUtil::IsValidHeaderValue(it.second)) { !net::HttpUtil::IsValidHeaderValue(it.second)) {
args->ThrowTypeError("Invalid header name or value"); args->ThrowTypeError("Invalid header name or value");
return nullptr; return gin::Handle<SimpleURLLoaderWrapper>();
} }
request->headers.SetHeader(it.first, it.second); 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 url_loader_factory = session->browser_context()->GetURLLoaderFactory();
auto* ret = auto ret = gin::CreateHandle(
new SimpleURLLoaderWrapper(std::move(request), url_loader_factory.get()); args->isolate(),
ret->InitWithArgs(args); new SimpleURLLoaderWrapper(std::move(request), url_loader_factory.get()));
ret->Pin(); ret->Pin();
if (!chunk_pipe_getter.IsEmpty()) { if (!chunk_pipe_getter.IsEmpty()) {
ret->PinBodyGetter(chunk_pipe_getter); ret->PinBodyGetter(chunk_pipe_getter);
@ -417,8 +421,9 @@ gin_helper::WrappableBase* SimpleURLLoaderWrapper::New(gin::Arguments* args) {
void SimpleURLLoaderWrapper::OnDataReceived(base::StringPiece string_piece, void SimpleURLLoaderWrapper::OnDataReceived(base::StringPiece string_piece,
base::OnceClosure resume) { base::OnceClosure resume) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
v8::HandleScope handle_scope(isolate()); v8::Isolate* isolate = v8::Isolate::GetCurrent();
auto array_buffer = v8::ArrayBuffer::New(isolate(), string_piece.size()); v8::HandleScope handle_scope(isolate);
auto array_buffer = v8::ArrayBuffer::New(isolate, string_piece.size());
auto backing_store = array_buffer->GetBackingStore(); auto backing_store = array_buffer->GetBackingStore();
memcpy(backing_store->Data(), string_piece.data(), string_piece.size()); memcpy(backing_store->Data(), string_piece.data(), string_piece.size());
Emit("data", array_buffer); Emit("data", array_buffer);
@ -441,8 +446,9 @@ void SimpleURLLoaderWrapper::OnRetry(base::OnceClosure start_retry) {}
void SimpleURLLoaderWrapper::OnResponseStarted( void SimpleURLLoaderWrapper::OnResponseStarted(
const GURL& final_url, const GURL& final_url,
const network::mojom::URLResponseHead& response_head) { const network::mojom::URLResponseHead& response_head) {
v8::HandleScope scope(isolate()); v8::Isolate* isolate = v8::Isolate::GetCurrent();
gin::Dictionary dict = gin::Dictionary::CreateEmpty(isolate()); v8::HandleScope scope(isolate);
gin::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
dict.Set("statusCode", response_head.headers->response_code()); dict.Set("statusCode", response_head.headers->response_code());
dict.Set("statusMessage", response_head.headers->GetStatusText()); dict.Set("statusMessage", response_head.headers->GetStatusText());
dict.Set("httpVersion", response_head.headers->GetHttpVersion()); dict.Set("httpVersion", response_head.headers->GetHttpVersion());
@ -471,14 +477,17 @@ void SimpleURLLoaderWrapper::OnDownloadProgress(uint64_t current) {
} }
// static // static
void SimpleURLLoaderWrapper::BuildPrototype( gin::ObjectTemplateBuilder SimpleURLLoaderWrapper::GetObjectTemplateBuilder(
v8::Isolate* isolate, v8::Isolate* isolate) {
v8::Local<v8::FunctionTemplate> prototype) { return gin_helper::EventEmitterMixin<
prototype->SetClassName(gin::StringToV8(isolate, "SimpleURLLoaderWrapper")); SimpleURLLoaderWrapper>::GetObjectTemplateBuilder(isolate)
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("cancel", &SimpleURLLoaderWrapper::Cancel); .SetMethod("cancel", &SimpleURLLoaderWrapper::Cancel);
} }
const char* SimpleURLLoaderWrapper::GetTypeName() {
return "SimpleURLLoaderWrapper";
}
} // namespace api } // namespace api
} // namespace electron } // namespace electron

View file

@ -10,18 +10,21 @@
#include <vector> #include <vector>
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "gin/wrappable.h"
#include "net/base/auth.h" #include "net/base/auth.h"
#include "services/network/public/cpp/simple_url_loader_stream_consumer.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/network_context.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom-forward.h" #include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
#include "services/network/public/mojom/url_response_head.mojom.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 "url/gurl.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
namespace gin { namespace gin {
class Arguments; class Arguments;
} template <typename T>
class Handle;
} // namespace gin
namespace network { namespace network {
class SimpleURLLoader; class SimpleURLLoader;
@ -34,14 +37,12 @@ namespace api {
/** Wraps a SimpleURLLoader to make it usable from JavaScript */ /** Wraps a SimpleURLLoader to make it usable from JavaScript */
class SimpleURLLoaderWrapper class SimpleURLLoaderWrapper
: public gin_helper::EventEmitter<SimpleURLLoaderWrapper>, : public gin::Wrappable<SimpleURLLoaderWrapper>,
public gin_helper::EventEmitterMixin<SimpleURLLoaderWrapper>,
public network::SimpleURLLoaderStreamConsumer { public network::SimpleURLLoaderStreamConsumer {
public: public:
~SimpleURLLoaderWrapper() override; ~SimpleURLLoaderWrapper() override;
static gin_helper::WrappableBase* New(gin::Arguments* args); static gin::Handle<SimpleURLLoaderWrapper> Create(gin::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
static SimpleURLLoaderWrapper* FromID(uint32_t id); static SimpleURLLoaderWrapper* FromID(uint32_t id);
@ -55,6 +56,12 @@ class SimpleURLLoaderWrapper
void Cancel(); void Cancel();
// gin::Wrappable
static gin::WrapperInfo kWrapperInfo;
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
const char* GetTypeName() override;
private: private:
SimpleURLLoaderWrapper(std::unique_ptr<network::ResourceRequest> loader, SimpleURLLoaderWrapper(std::unique_ptr<network::ResourceRequest> loader,
network::mojom::URLLoaderFactory* url_loader_factory); network::mojom::URLLoaderFactory* url_loader_factory);