Aller au contenu principal

Création d'un nouveau module Browser pour Electron

Bienvenue dans le guide de l'API Electron ! Si vous n'êtes pas familiarisé avec la création de nouveau module API Electron dans le répertoire browser , ce guide vous servira de checklist pour certaines des étapes nécessaires à mettre en œuvre.

Il ne s'agit pas d'un guide complet pour créer une API de navigateur d''Electron, mais plutôt d'un aperçu documentant certaines des étapes les moins intuitives.

Ajout de vos fichiers à la configuration du projet Electron

Electron utilise GN comme méta système de compilation pour générer des fichiers pour son compilateur, Ninja. Cela signifie que pour ordonner à Electron de compiler du code, nous devons ajouter ce code de votre API et les noms des fichiers d'en-tête dans filenames.gni.

Vous devez ajouter les noms de fichiers de votre API par ordre alphabétique dans les fichiers appropriés comme suit:

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",
]

Notez que l'ajout des tableaux Windows, macOS et Linux est facultatif et ceux-ci ne doivent être ajoutés que si votre API a des implémentations spécifiques à certaines plate-formes.

Création de la documentation de l'API

Les définitions de types sont générées par Electron en utilisant @electron/docs-parser et @electron/typescript-definitions. Cette étape est nécessaire pour assurer la cohérence de la documentation de l'API d'Electron. Cela signifie que pour que la définition du type de votre API apparaisse dans le fichier electron.d.ts , un fichier .md doit être créé. On peut trouver des exemples dans ce dossier.

Configuration de ObjectTemplateBuilder et de Wrappable

Electron batit ses modules en utilisant object_template_builder.

wrappable est une classe de base pour les objets C++ qui ont des objets wrapper v8 correspondants.

Voici un exemple basique de code que vous aurez besoin d'ajouter, afin d'incorporer object_template_builder et wrappable dans votre API. Pour plus d'information, vous pouvez trouver d'avantage d'implémentations ici.

Dans votre fichier 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

Dans votre fichier 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

Liaison de votre API Electron avec Node

Dans le fichier typings/internal-ambient.d.ts, nous allons devoir ajouter une nouvelle propriété à l'interface Process de la manière suivante:

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

Et en bas de votre fichier api_name.cc:

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

Dans votre fichier shell/common/node_bindings.cc, ajouter ensuite votre nom de liaison Node aux modules intégrés d’Electron.

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

Remarque : Plus de détails techniques sur la façon dont Node est lié avec Electron peuvent être trouvés sur notre blog.

Exposition de votre API à TypeScript

Export de votre API en tant que module

Nous devons créer un nouveau fichier TypeScript dans le chemin suivant :

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

Un exemple de contenu de ce fichier peut être trouvé ici.

Exposition de votre module à TypeScript

Ajouter votre module à la liste des modules située à "lib/browser/api/module-list.ts" comme suit:

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