Saltar al contenido principal

Crear un nuevo módulo de navegador Electron

¡Bienvenido a la guía de Electron API! Si no está familiarizado con la creación de un nuevo módulo de Electron API dentro del directorio browser, esta guía sirve como una lista de verificación para algunos de los pasos necesarios que necesitará implementar.

Esta no es una guía completa para crear un Electron Browser API, sino un esquema que documenta algunos de los pasos menos intuitivos.

Añade tus archivos a la configuración del proyecto de Electron

Electron usa GN como un sistema de meta build para generar archivos para su compilador, Ninja. Esto significa que para decirle a Electron que compile su código, tenemos que añadir el código de tu API y los nombres de archivo de cabecera en filenames.gni.

Necesitarás añadir tus nombres de archivo API alfabéticamente a los archivos apropiados así:

filenames.gni
lib_sources = [
"path/to/api/api_name.cc",
"path/to/api/api_name.h",
]

lib_sources_mac = [
"path/to/api/api_name_mac.h",
"path/to/api/api_name_mac.mm",
]

lib_sources_win = [
"path/to/api/api_name_win.cc",
"path/to/api/api_name_win.h",
]

lib_sources_linux = [
"path/to/api/api_name_linux.cc",
"path/to/api/api_name_linux.h",
]

Tenga en cuenta que las adiciones de las matrices de Windows, macOS y Linux son opcionales y sólo deben ser añadidas si su API tiene implementaciones específicas de la plataforma.

Crear documentación de la API

Las definiciones de tipo son generadas por Electron usando @electron/docs-parser y @electron/typescript-definitions. Este paso es necesario para asegurar la consistencia en toda la documentación de la API de Electron. Esto significa que para que su definición de tipo API aparezca en el archivo electron.d.ts, debemos crear un archivo .md. Los ejemplos se pueden encontrar en esta carpeta.

Configurar ObjectTemplateBuilder y Wrappable

Electron construye sus módulos usando object_template_builder.

wrappable es una clase base para objetos C++ que tienen objetos envoltorios v8 correspondientes.

Este es un ejemplo básico de código que puede necesitar añadir para incorporar object_template_builder y wrappable en su API. Para más referencia, puede encontrar más implementaciones aquí.

En su archivo api_name.h:

api_name.h

#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_

#include "gin/handle.h"
#include "gin/wrappable.h"

namespace electron {

namespace api {

class ApiName : public gin::Wrappable<ApiName> {
public:
static gin::Handle<ApiName> Create(v8::Isolate* isolate);

// gin::Wrappable
static gin::WrapperInfo kWrapperInfo;
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
const char* GetTypeName() override;
} // namespace api
} // namespace electron

En su archivo api_name.cc:

api_name.cc
#include "shell/browser/api/electron_api_safe_storage.h"

#include "shell/browser/browser.h"
#include "shell/common/gin_converters/base_converter.h"
#include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "shell/common/platform_util.h"

namespace electron {

namespace api {

gin::WrapperInfo ApiName::kWrapperInfo = {gin::kEmbedderNativeGin};

gin::ObjectTemplateBuilder ApiName::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return gin::ObjectTemplateBuilder(isolate)
.SetMethod("methodName", &ApiName::methodName);
}

const char* ApiName::GetTypeName() {
return "ApiName";
}

// static
gin::Handle<ApiName> ApiName::Create(v8::Isolate* isolate) {
return gin::CreateHandle(isolate, new ApiName());
}

} // namespace api

} // namespace electron

namespace {

void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
gin_helper::Dictionary dict(isolate, exports);
dict.Set("apiName", electron::api::ApiName::Create(isolate));
}

} // namespace

Vincula su API de Electron con Node

En el archivo typings/internal-ambient.d.ts, necesitamos añadir una nueva propiedad a la interfaz Process así:

typings/internal-ambient.d.ts
interface Process {
_linkedBinding(name: 'electron_browser_{api_name}'): Electron.ApiName;
}

En la parte final de su archivo api_name.cc:

api_name.cc
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{api_name},Initialize)

En su archivo shell/common/node_bindings.cc, agregue el nombre del enlace de nodos a los módulos integrados de Electron.

shell/common/node_bindings.cc
#define ELECTRON_BROWSER_MODULES(V)      \
V(electron_browser_{api_name})

Nota: Más detalles técnicos sobre cómo vincular Node con Electron pueden encontrarse en nuestro blog.

Exponga su API a TypeScript

Exportar su API como módulo

Necesitaremos crear un nuevo archivo TypeScript en la ruta que sigue:

"lib/browser/api/{electron_browser_{api_name}}.ts"

Se puede encontrar un ejemplo de los contenidos de este archivo aquí.

Exponer su módulo a TypeScript

Añade su módulo a la lista de módulos encontrada en "lib/browser/api/module-list.ts" así:

lib/browser/api/module-list.ts
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'apiName', loader: () => require('./api-name') },
];