![electron-roller[bot]](/assets/img/avatar_default.png)
* chore: bump chromium in DEPS to 140.0.7269.2 * chore: bump chromium in DEPS to 140.0.7270.0 * chore: bump chromium in DEPS to 140.0.7271.0 * chore: bump chromium in DEPS to 140.0.7273.0 * 6516731: [ExclusiveAccessForAndroid] remove unneeded includes & deps | https://chromium-review.googlesource.com/c/chromium/src/+/6516731 * 6694809: dbus: Ensure systemd scope is started before using any portal services | https://chromium-review.googlesource.com/c/chromium/src/+/6694809 * chore: patch chromium * chore: export patches * chore: bump chromium in DEPS to 140.0.7275.0 * 6677511: [pepper] More pepper removal | https://chromium-review.googlesource.com/c/chromium/src/+/6677511 * 6513641: [gin] Rename gin::Wrappable to gin::DeprecatedWrappable | https://chromium-review.googlesource.com/c/chromium/src/+/6513641 * chore: export chromium patches * 6513641: [gin] Rename gin::Wrappable to gin::DeprecatedWrappable | https://chromium-review.googlesource.com/c/chromium/src/+/6513641 * chore: bump chromium in DEPS to 140.0.7277.0 * chore: bump chromium in DEPS to 140.0.7279.0 * chore: bump chromium in DEPS to 140.0.7281.0 * 6677314: Plumb enabled client hints in the network requestion to network layer https://chromium-review.googlesource.com/c/chromium/src/+/6677314 * 6351556: [source-phase-imports] Support Wasm Source Phase Imports https://chromium-review.googlesource.com/c/chromium/src/+/6351556 * 6700077: [renderer] Avoid calls to deprecated GetIsolate methods https://chromium-review.googlesource.com/c/chromium/src/+/6700077 * 6692873: Reland "Reland "FSA: Only normalize the hardcoded rules once during initialization"" https://chromium-review.googlesource.com/c/chromium/src/+/6692873 * 6686234: [gin] Cleanup NamedPropertyInterceptor for Wrappable https://chromium-review.googlesource.com/c/chromium/src/+/6686234 * chore: export patches * 6667723: Remove content_enable_legacy_ipc GN arg. https://chromium-review.googlesource.com/c/chromium/src/+/6667723 * 6646566: ui: Move NativeWindowTracker to its own directory https://chromium-review.googlesource.com/c/chromium/src/+/6646566 * fix: add missing includes * 6580522: [WAR, DNR] Fix unsafe redirect error to web accessible resource https://chromium-review.googlesource.com/c/chromium/src/+/6580522 * 6680477: Implement `completeCode` endpoint and expose to DevTools https://chromium-review.googlesource.com/c/chromium/src/+/6680477 * 6677511: [pepper] More pepper removal https://chromium-review.googlesource.com/c/chromium/src/+/6677511 * 6696689: Rename views::WidgetFocusManager -> NativeViewFocusManager https://chromium-review.googlesource.com/c/chromium/src/+/6696689 * 6702812: Move wtf/text/string_impl*.* to "blink" namespace https://chromium-review.googlesource.com/c/chromium/src/+/6702812 * chore: fix dialog patch * 6702431: [animation-trigger] Parse timeline-trigger-name https://chromium-review.googlesource.com/c/chromium/src/+/6702431 * chore: fixup patch indices * feat: replace webFrame.routingId with webFrame.frameToken * feat: WebFrameMain.prototype.frameToken * test: refactor to use replacement APIs * chore: fixup pip patch * test: adjust webFrame tests for frameToken changes * 6703757: Reland "Enable -fsanitize=array-bounds in non-UBSan builds" https://chromium-review.googlesource.com/c/chromium/src/+/6703757 * test: switch to frameTokens * test: routingId is fine to test in the main process * docs: add routingId to breaking changes * docs: update plugin-crashed event * chore: fixup linux dialog patch --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: alice <alice@makenotion.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: Samuel Maddock <smaddock@slack-corp.com>
174 lines
6.3 KiB
Markdown
174 lines
6.3 KiB
Markdown
# Creating a New Electron Browser Module
|
|
|
|
Welcome to the Electron API guide! If you are unfamiliar with creating a new Electron API module within the [`browser`](https://github.com/electron/electron/tree/main/shell/browser) directory, this guide serves as a checklist for some of the necessary steps that you will need to implement.
|
|
|
|
This is not a comprehensive end-all guide to creating an Electron Browser API, rather an outline documenting some of the more unintuitive steps.
|
|
|
|
## Add your files to Electron's project configuration
|
|
|
|
Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). 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`](https://github.com/electron/electron/blob/main/filenames.gni).
|
|
|
|
You will need to append your API file names alphabetically into the appropriate files like so:
|
|
|
|
```cpp title='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",
|
|
]
|
|
```
|
|
|
|
Note that the Windows, macOS and Linux array additions are optional and should only be added if your API has specific platform implementations.
|
|
|
|
## Create API documentation
|
|
|
|
Type definitions are generated by Electron using [`@electron/docs-parser`](https://github.com/electron/docs-parser) and [`@electron/typescript-definitions`](https://github.com/electron/typescript-definitions). This step is necessary to ensure consistency across Electron's API documentation. This means that for your API type definition to appear in the `electron.d.ts` file, we must create a `.md` file. Examples can be found in [this folder](https://github.com/electron/electron/tree/main/docs/api).
|
|
|
|
## Set up `ObjectTemplateBuilder` and `Wrappable`
|
|
|
|
Electron constructs its modules using [`object_template_builder`](https://www.electronjs.org/blog/from-native-to-js#mateobjecttemplatebuilder).
|
|
|
|
[`wrappable`](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/gin/wrappable.h) is a base class for C++ objects that have corresponding v8 wrapper objects.
|
|
|
|
Here is a basic example of code that you may need to add, in order to incorporate `object_template_builder` and `wrappable` into your API. For further reference, you can find more implementations [here](https://github.com/electron/electron/tree/main/shell/browser/api).
|
|
|
|
In your `api_name.h` file:
|
|
|
|
```cpp title='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
|
|
```
|
|
|
|
In your `api_name.cc` file:
|
|
|
|
```cpp title='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* isolate = context->GetIsolate();
|
|
gin_helper::Dictionary dict(isolate, exports);
|
|
dict.Set("apiName", electron::api::ApiName::Create(isolate));
|
|
}
|
|
|
|
} // namespace
|
|
```
|
|
|
|
## Link your Electron API with Node
|
|
|
|
In the [`typings/internal-ambient.d.ts`](https://github.com/electron/electron/blob/main/typings/internal-ambient.d.ts) file, we need to append a new property onto the `Process` interface like so:
|
|
|
|
```ts title='typings/internal-ambient.d.ts' @ts-nocheck
|
|
interface Process {
|
|
_linkedBinding(name: 'electron_browser_{api_name}'): Electron.ApiName;
|
|
}
|
|
```
|
|
|
|
At the very bottom of your `api_name.cc` file:
|
|
|
|
```cpp title='api_name.cc'
|
|
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{api_name},Initialize)
|
|
```
|
|
|
|
In your [`shell/common/node_bindings.cc`](https://github.com/electron/electron/blob/main/shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.
|
|
|
|
```cpp title='shell/common/node_bindings.cc'
|
|
#define ELECTRON_BROWSER_MODULES(V) \
|
|
V(electron_browser_{api_name})
|
|
```
|
|
|
|
> [!NOTE]
|
|
> More technical details on how Node links with Electron can be found on [our blog](https://www.electronjs.org/blog/electron-internals-using-node-as-a-library#link-node-with-electron).
|
|
|
|
## Expose your API to TypeScript
|
|
|
|
### Export your API as a module
|
|
|
|
We will need to create a new TypeScript file in the path that follows:
|
|
|
|
`"lib/browser/api/{electron_browser_{api_name}}.ts"`
|
|
|
|
An example of the contents of this file can be found [here](https://github.com/electron/electron/blob/main/lib/browser/api/native-theme.ts).
|
|
|
|
### Expose your module to TypeScript
|
|
|
|
Add your module to the module list found at `"lib/browser/api/module-list.ts"` like so:
|
|
|
|
<!-- eslint-disable semi -->
|
|
|
|
```ts title='lib/browser/api/module-list.ts' @ts-nocheck
|
|
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
|
{ name: 'apiName', loader: () => require('./api-name') }
|
|
];
|
|
```
|