メインコンテンツへ飛ぶ

Electron ブラウザモジュールの新規作成

Electron API ガイドへようこそ! browser ディレクトリ内に新しい Electron API モジュールを作成することに慣れていない方向けに、このガイドでは実装が必要ないくつかのステップをチェックリストとして提供しています。

これは、Electron Browser API を作成するための包括的なつきっきりのガイドではなく、直感的ではないような手順について説明する概略です。

Electron のプロジェクト構成へのファイル追加

Electron は、コンパイラである Ninja 用のファイルを生成するためのメタビルドシステムとして GN を使用しています。 This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into filenames.gni.

API ファイル名は以下のように、アルファベット順で適切なファイルに追加する必要があります。

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

なお、Windows、macOS、Linux の配列の追加は任意であり、API にプラットフォーム固有の実装があれば追加する必要があります。

API ドキュメントの作成

Electron は @electron/docs-parser@electron/typescript-definitions を利用して型定義ファイルを生成します。 このステップは、Electron の API ドキュメントの一貫性を確保するために必要です。 これは、API の型定義を electron.d.ts ファイルに出すには.md ファイルを作成する必要があるということです。 サンプルは このフォルダ にあります。

ObjectTemplateBuilderWrappable のセットアップ

Electron は、object_template_builder を使ってモジュールを構築します。

wrappable は、C++ オブジェクトがそれに対応する v8 ラッパーオブジェクトを保持するための基底クラスです。

ここでは、object_template_builderwrappable を API に組み込むために必要となるコードの基本的な例を示します。 参考までに、さらなる実装は こちら で紹介しています。

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::DeprecatedWrappable<ApiName> {
public:
static gin::Handle<ApiName> Create(v8::Isolate* isolate);

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

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::DeprecatedWrapperInfo 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* const isolate = v8::Isolate::GetCurrent();
gin_helper::Dictionary dict(isolate, exports);
dict.Set("apiName", electron::api::ApiName::Create(isolate));
}

} // namespace

Electron API と Node をリンクする

In the typings/internal-ambient.d.ts file, we need to append a new property onto the Process interface like so:

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

api_name.cc ファイルのかなり下の方に以下の行があります。

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

In your shell/common/node_bindings.cc file, add your node binding name to Electron's built-in modules.

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

[!NOTE] Node が Electron とどのようにリンクしているのか、より技術的な詳細は ブログ に記載してあります。

API を TypeScript に公開

API をモジュールとしてエクスポート

以下のパスに新しい TypeScript ファイルを作成する必要があります。

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

An example of the contents of this file can be found here.

モジュールを TypeScript に公開

"lib/browser/api/module-list.ts" にあるモジュールリストに、あなたのモジュールを以下のように追加してください。

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