Electron HarmonyOS Porting Guide
[TOC]
Note: If you have not used this framework on other platforms, it is not recommended to use it directly. You should choose a cross-platform framework based on your overall cross-platform evolution plan for your software.
Environment Configuration
Operating System: Ubuntu 22.04
Disk Space: More than 200GB
Memory: More than 32GB
CPU Architecture: x86_64
Building Applications from Source Code
Downloading and Installing Source Code and Tools
Tool Installation
- Code Repository URL
-
Install the tools
git-lfsandccache. Note: This step only needs to be executed when pulling the code for the first time.# Install git-lfs to ensure large files in the repository can be pulled locally. ccache is a compiler cache. $ sudo apt install git-lfs ccache

-
Configure the
repotool. Note: This step only needs to be executed when pulling the code for the first time. Please ensure the python3 environment is configured before executing this step.# Download the Gitee repo tool (refer to Gitee Help Center: https://gitee.com/help/articles/4316) $ mkdir -p ~/bin $ curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > ~/bin/repo $ chmod a+x ~/bin/repo $ echo 'export PATH=~/bin/:$PATH' >> ~/.bashrc $ source ~/.bashrc $ pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests
Installing Node.js Environment
Three installation methods are available:
Via Ubuntu Standard Repository
This method requires installing npm separately.
sudo apt update
sudo apt install -y nodejs npm
Check version number:
node -v
Via NodeSource Repository
This method installs Node.js with npm included; npm does not need to be installed separately.
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
Check version numbers:
node -v
npm -v
Via nvm
git clone https://gitee.com/mirrors/nvm
cd nvm
bash install.sh
source ~/.bashrc
Check nvm version and install Node.js:
nvm -v
Install Node.js (version 20.18.1, 32-bit or 64-bit, using 32-bit as an example below), use and check version number:
nvm install node 20.18.1 32
nvm use 20.18.1
node -v
Pulling the chromium-electron Repository Code
-
Clone the chromium-electron repository from the code repository.
# Pull chromium-electron code using https $ git clone -b master https://gitcode.com/openharmony-sig/electron.git $ cd electron # Switch to the newly cloned electron repository directory $ git lfs pull # Execute `git lfs pull` to ensure large files in the repository are downloaded # Pull the OHOS chromium code corresponding to chromium-electron $ repo init -u https://gitcode.com/openharmony-tpc/manifest.git -b pc_chromium_132 -m chromium.xml --no-repo-verify $ repo sync -c # Can be executed multiple times to ensure all code is pulled successfully $ repo forall -c 'git lfs pull' # Can be executed multiple times to ensure all large files are pulled successfully # Apply chromium-electron patches to OHOS chromium $ pushd src $ find -name "*.git*" -exec rm -rf "{}" \; $ popd $ chmod +x override_files.sh $ ./override_files.sh -
Run the script at Electron_actual_directory/src/build/install-build-deps.sh to install the required build packages. Note: This step only needs to be executed when pulling the code for the first time.
$ sudo ./src/build/install-build-deps.sh --no-chromeos-fonts
-
Run the script
electron_build.sh.
$ ./electron_build.sh
Q&A: Handling Electron Build Errors
Q: Why does the following error occur when running ./electron_build.sh for compilation?
cannot access 'rust-toolchain.tar.gz' : No such file or directory
A: Because when executing ./override_files.sh, an unstable network caused the download of rust-toolchain.tar.gz to fail.
Output
After compilation, the build artifacts will be output in the src/out/musl_64 directory as follows:
locales/ libelectron.so electron resources.pak chrome_100_percent.pak chrome_200_percent.pak icudtl.dat libadapter.so libffmpeg.so v8_context_snapshot.bin
You can use the following script to copy the required resources (Note: Please modify source_path to your actual path):
#!/bin/sh
source_path=./Electron_actual_directory/src/out/musl_64
destination_path=./electron
if [ -d ${destination_path} ];then
rm -rf ${destination_path}
fi
mkdir ${destination_path}
cp ${source_path}/libelectron.so ${destination_path}
cp ${source_path}/libffmpeg.so ${destination_path}
cp ${source_path}/libadapter.so ${destination_path}
cp ${source_path}/electron ${destination_path}
cp ${source_path}/icudtl.dat ${destination_path}
cp ${source_path}/v8_context_snapshot.bin ${destination_path}
cp ${source_path}/chrome_100_percent.pak ${destination_path}
cp ${source_path}/chrome_200_percent.pak ${destination_path}
cp ${source_path}/resources.pak ${destination_path}
mkdir ${destination_path}/locales
cp ${source_path}/locales/zh-CN.pak ${destination_path}/locales
cp ${source_path}/locales/en-US.pak ${destination_path}/locales
Save the script as copy.sh, place it at the same level as the chromium compilation folder, and execute it. After execution, the required resources will be copied to the electron folder at the same level.
HAP Package Building and Usage
The HAP package project is located in the source directory: src/ohos/app/ folder.
Building an Unsigned HAP Package
Create an electron/libs/arm64-v8a folder in the project, replace the resources in the electron/libs/arm64-v8a directory and the web_engine/src/main/resources/resfile directory, and use DevEco Studio to compile and install.
libc++_shared.so needs to be obtained from /src/ohos_sdk/openharmony/native/llvm/lib/aarch64-linux-ohos. This file appears after the SDK archive is extracted.
Place the Electron project source code (or build artifacts if compilation is needed) into the web_engine/src/main/resources/resfile/resources/app directory.

The test files required in the resfile/resources/app directory shown above can be found in the resources directory of the chromium-electron repository. After placing both the .so libraries and resfile in the specified locations, click Build -> Build Hap(s)/APP(s) -> Build Hap(s) to compile and generate an unsigned HAP package, or click the Run button in the upper right corner to launch the application.


After compilation, the unsigned HAP package will be saved to ohos_hap/electron/build/default/outputs/default/, with the filename electron-default-unsigned.hap.

Signing and Permissions
App/Service Signing - DevEco Studio - Huawei HarmonyOS Developer (huawei.com)
Example of permission request email content:
Please apply for permissions based on actual needs. The example content is for reference only.

The permission configuration file is located at: ohos_hap\web_engine\src\main\module.json5 in the requestPermissions field. Below are the currently declared permissions and their descriptions.
| Permission Name | Permission Description | Necessity |
|---|---|---|
| ohos.permission.SYSTEM_FLOAT_WINDOW | Allows the application to use the global floating window capability. | Apply as needed |
| ohos.permission.INTERNET | Allows use of the Internet network. | Basic |
| ohos.permission.GET_NETWORK_INFO | Allows the application to obtain data network information. | Basic |
| ohos.permission.ACCESS_CERT_MANAGER | Allows the application to query certificates and private credentials. | Apply as needed |
| ohos.permission.RUNNING_LOCK | Allows the application to acquire a running lock for continuous background execution. | Basic |
| ohos.permission.PRINT | Allows the application to access printing framework capabilities. | Apply as needed |
| ohos.permission.PREPARE_APP_TERMINATE | Allows the application to perform custom pre-termination actions before closing. | Basic |
| ohos.permission.ACCESS_BIOMETRIC | Allows the application to use biometric recognition for identity authentication. | Apply as needed |
| ohos.permission.FILE_ACCESS_PERSIST | Allows the application to persist access to file URIs. | Basic |
| ohos.permission.PRIVACY_WINDOW | Allows the application to set windows as privacy windows, preventing screenshots and screen recording. | Apply as needed |
| ohos.permission.WINDOW_TOPMOST | Allows the window to stay on top. | Apply as needed |
| ohos.permission.READ_PASTEBOARD | Allows the application to read the clipboard. | Basic |
| ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY | Allows the application to access the Download directory and its subdirectories under public directories. It is recommended to apply together with ohos.permission.FILE_ACCESS_PERSIST. | Apply as needed |
| ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY | Allows the application to access the Documents directory and its subdirectories under public directories. It is recommended to apply together with ohos.permission.FILE_ACCESS_PERSIST. | Apply as needed |
| ohos.permission.READ_WRITE_DESKTOP_DIRECTORY | Allows the application to access the Desktop directory and its subdirectories under public directories. It is recommended to apply together with ohos.permission.FILE_ACCESS_PERSIST. | Apply as needed |
| ohos.permission.LOCATION | Allows the application to obtain device location information. | Apply as needed |
| ohos.permission.APPROXIMATELY_LOCATION | Allows the application to obtain approximate device location information. | Apply as needed |
| ohos.permission.LOCATION_IN_BACKGROUND | Allows the application to obtain device location information while running in the background. | Apply as needed |
| ohos.permission.MICROPHONE | Allows the application to use the microphone. | Apply as needed |
| ohos.permission.CAMERA | Allows the application to use the camera. | Apply as needed |
| ohos.permission.ACCESS_BLUETOOTH | Allows the application to access Bluetooth and use Bluetooth capabilities such as pairing and connecting to peripheral devices. | Apply as needed |
| ohos.permission.CUSTOM_SCREEN_CAPTURE | Allows the application to capture screen content. | Apply as needed |
Permissions in Electron that require ACL signing include (if the certificate has not been obtained and signing fails, you can temporarily comment out these permissions):
"requestPermissions": [
{
"name": "ohos.permission.SYSTEM_FLOAT_WINDOW"
},
...
{
"name": "ohos.permission.READ_PASTEBOARD",
"reason": "$string:access_pasteboard",
},
...
{
"name": "ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY",
"reason": "$string:reason_download",
"usedScene": {
"abilities": [
"FormAbility"
],
"when":"always"
}
},
{
"name": "ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY",
"reason": "$string:reason_documents",
"usedScene": {
"abilities": [
"FormAbility"
],
"when":"always"
}
},
{
"name": "ohos.permission.READ_WRITE_DESKTOP_DIRECTORY",
"reason": "$string:reason_desktop",
"usedScene": {
"abilities": [
"FormAbility"
],
"when":"always"
}
}
]
Running a Signed HAP Package
After obtaining the certificate, configure it in DevEco Studio.

After configuration, click the Run button in the upper right corner to run.

Alternatively,
Install the HAP package via command line:
hdc app install <signed_hap_package_path>
# e.g: hdc app install pc_entry-default-signed.hap

Paths in HarmonyOS
Mapping Between Application Sandbox Paths and Actual Physical Paths
When reading and writing files in the application sandbox path, the actual read/write operations are performed on the real physical paths through path mapping. The correspondence between sandbox paths and physical paths is shown in the table below.
Where is currently fixed at 100.
| Application Sandbox Path | Physical Path | Description |
|---|---|---|
| /data/storage/el1/bundle | /data/app/el1/bundle/public/<PACKAGENAME> | Application installation package directory |
| /data/storage/el1/base | /data/app/el1/<USERID>/base/<PACKAGENAME> | Application el1-level encrypted data directory |
| /data/storage/el2/base | /data/app/el2/<USERID>/base/<PACKAGENAME> | Application el2-level encrypted data directory |
| /data/storage/el1/database | /data/app/el1/<USERID>/database/<PACKAGENAME> | Application el1-level encrypted database directory |
| /data/storage/el2/database | /data/app/el2/<USERID>/database/<PACKAGENAME> | Application el2-level encrypted database directory |
User data must be stored under the /data/storage/el2/base path. The default --user-data-dir for Electron is /data/storage/el2/base/files.

To view user data, use the system file manager as shown below:


Customizing Your HarmonyOS Application
Replacing the Application Name
Location: ohos_hap\electron\src\main\resources\zh_CN\element\string.json
Replace the value of the EntryAbility_label field in the file.

Replacing the Icon
Location: ohos_hap\AppScope\resources\base\media

Resource Replacement
Since HarmonyOS does not currently have a compilation environment, if the original project requires compilation (e.g., TypeScript needs to be compiled to JavaScript before loading), you need to place the compiled JavaScript files in the project at web_engine/src/main/resources/resfile/resources/app.
Issues you may encounter with open-source third-party libraries:
-
If an npm library uses addons (i.e., C++ libraries called by JavaScript), it cannot function properly without HarmonyOS platform adaptation. -- Refer to the sqlite3 compilation adaptation solution for guidance. Note: compiling .node requires a minimum C++ version of 17.
-
If an npm library uses platform-checking APIs such as process.platform or os.type(), it cannot function properly without HarmonyOS platform adaptation, because process.platform returns "openharmony", which third-party libraries may not recognize. -- Code modifications are needed to adapt for the OH platform.
-
If an npm library contains binary files (e.g., libraries like esbuild), it cannot function properly. -- Linux machines require root privileges; for new PCs, use the HNP solution.
Multi-Instance Configuration
If the application does not need multi-instance support, remove the "multiAppMode" configuration as shown below:

Electron HarmonyOS Feature Notes
Windows
Specifying the Initial Window Size
If the application needs to specify the window size at startup, modify the file electron/src/main/module.json5 in the project and add the metadata property inside abilities as shown below. If centering is not needed, only width and height need to be specified.
{
"module": {
"name": "pc_entry",
"type": "entry",
"srcEntry": "./ets/Application/AbilityStage.ets",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"2in1"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:app_icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:app_icon",
"startWindowBackground": "$color:start_window_background",
"launchType": "specified",
"removeMissionAfterTerminate": true,
"exported": true,
***************** Add here *****************
"metadata": [
{
"name": "ohos.ability.window.height",
"value": "800"
},
{
"name": "ohos.ability.window.width",
"value": "800",
},
{
"name": "ohos.ability.window.left",
"value": "center"
},
{
"name": "ohos.ability.window.top",
"value": "center",
}
],
*********************************************
"skills": [
{
"entities": [
"entity.system.home",
"entity.system.browsable"
],
"actions": [
"action.system.home",
"ohos.want.action.viewData"
],
"uris": []
}
]
}
]
}
}
Window Show/Hide
Due to OH system limitations, window show/hide is tightly bound to the application tray. Therefore, before launching the application, a tray must be created first to ensure proper window creation.
const { app, Tray } = require('electron');
const path = require('path');
app.whenReady().then(() => {
let tray = new Tray(path.join(__dirname, 'tray_icon.png'));
...
})
If the application does not need a tray or hidden windows, modify ohos_hap/web_engine/src/main/ets/adapter/AppWindowAdapter.ets and comment out the processMode and startupVisibility properties.
...
const options: StartOptions = {
// processMode: contextConstant.ProcessMode.ATTACH_TO_STATUS_BAR_ITEM,
// startupVisibility: param.show ? contextConstant.StartupVisibility.STARTUP_SHOW : contextConstant.StartupVisibility.STARTUP_HIDE,
windowLeft: param.left - leftBorder,
windowTop: param.top - topBorder,
windowWidth: param.width + leftBorder + leftBorder,
windowHeight: param.height + leftBorder + topBorder
}
...
Window Control Buttons
The current window control buttons (close, minimize, maximize) behave consistently with other platforms. When creating windows other than the first window, if the window has a frame (frame property is true), the control buttons are visible. If the window is frameless, the control buttons are not displayed. Sub-windows and floating windows have no control buttons.
If the application needs to display control buttons when creating frameless windows, you can modify the initial state in WebAbility.ets to adjust the initial display state of the control buttons when creating windows. See the figure below:

New APIs
Floating Window
A new windowInfo property has been added to BrowserWindow. It is an Object with a single property type (type: String), which can be one of mainWindow, subWindow, or floatWindow. The default value is mainWindow.
let w = new BrowserWindow({
windowInfo: {
// type can be mainWindow, subWindow, or floatWindow
type: 'floatWindow'
},
parent: mainWindow;
x:100,
y:100,
width:800,
height: 600,
show: true,
// You can set background color and opacity
// The priority order for opacity is: transparent, opacity, and the alpha value in backgroundColor
transparent: true, // Fully transparent
opacity: 0.5, // Semi-transparent
backgroundColor: '#660000ee' // Semi-transparent blue
});
w.loadURL("https://www.baidu.com");
systemPreferences Module
Native API Implementation
systemPreferences.getMediaAccessStatus(mediaType)
mediaTypestring - Can bemicrophone,camera, orscreen.
Returns string - The value can be not-determined, granted, denied, restricted, or unknown.
Gets the status of microphone, camera, or screen capture permissions. On the OHOS platform, only granted and denied states are currently returned.
systemPreferences.askForMediaAccess(mediaType)
mediaTypestring - The type of media being requested, can bemicrophoneorcamera.
Returns Promise<boolean> - Resolves true if the user grants or has already granted permission. The system authorization dialog will only appear once. If permission has already been requested or was denied, it must be manually changed in Settings -> Privacy & Security. No prompt will appear, and the promise will return the existing permission status.
New Permission Request APIs
systemPreferences.requestSystemPermission(permission)
-
permissionstring - One of the following values:location,camera,microphone,screen-capture,user-download-dir,user-desktop-dir,user-document-dir,bluetooth,pasteboard
Returns Promise<boolean> - Resolves true if the user grants or has already granted permission. The system authorization dialog will only appear once. If permission has already been requested or was denied, it must be manually changed in Settings -> Privacy & Security. No prompt will appear, and the promise will return the existing permission status.
systemPreferences.requestDirectoryPermission(path)
pathstring | null
Returns Promise<boolean> - Resolves true if the user grants or has already granted permission. When path is null, permissions for the user's Download, Desktop, and Documents directories will be requested simultaneously. The promise resolves true if any one of the three directories is authorized. The system authorization dialog will only appear once. If permission has already been requested or was denied, it must be manually changed in Settings -> Privacy & Security. No prompt will appear.
New API to Open Application Info Page in System Settings
systemPreferences.openApplicationInfoEntry()
Opens "System Settings" and navigates to the application information page.
systemPreferences.fileAccessPersist(paths)
pathsstring[] - File or directory paths that need persistent authorization.
Grants persistent authorization for the specified files or directories.
Debugging the Application
Renderer Process
The most widely used tool for debugging a specific renderer process is Chromium's Developer Tools. It can access all renderer processes, including instances of BrowserWindow, BrowserView, and WebView. You can programmatically open them by calling the openDevTools() API on the webContents of a BrowserWindow:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.webContents.openDevTools()
Main Process
Use the following command-line switches to debug Electron's main process:
--inspect=[port]
Electron will listen for V8 debug protocol messages on the specified port. An external debugger needs to connect to this port. The default port is 9229 and can be changed to another port. This guide uses port 9229 as an example.
Below are the steps to debug the main process of an Electron application on OHOS using Chrome browser on Windows, with port 9229:
- Enable the Electron command-line switch. In the file ohos_hap/web_engine/src/main/ets/components/WebWindow.ets, add the
inspectparameter with the value'--inspect=9229', add the variable tovec_args, and rebuild and install.
// ohos_hap/web_engine/src/main/ets/components/WebWindow.ets
...
this.xComponent.attribute
.backgroundColor(Color.Transparent)
.onLoad(() => {
let resDir = '--bundle-installation-dir=' + getContext().resourceDir;
// Create a new variable here
let inspect = '--inspect=9229';
// And add it to vec_args
let vec_args = ['--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', resDir, inspect];
this.electronRelaunchArgs.forEach((arg: string) => {
vec_args.push(arg);
})
let nativeContext = JsBindingUtils.getNativeContext(ContextType.kMainProcess);
nativeContext.runBrowser(vec_args);
})
...
- Configure port forwarding. In the command line, execute the port forwarding command. The result is shown in the figure.
hdc fport tcp:9229 tcp:9229

- Visit the following page to connect to Chrome. The result is shown in the figure.
chrome://inspect
- On the
inspectpage, click theConfigure...button.

- Click the
Configure...button. In the popup menu, ensure localhost:9229 is present. If not, add it.

- After configuration, launch the Electron application on the device. The Chrome browser on Windows will display debuggable page options (this may take a moment). Click inspect to remotely debug the Electron main process.

When using command-line parameters, especially those related to security, exercise caution to ensure system security and stability. Risk parameters include but are not limited to the following:
-
--remote-debugging-port- Purpose: Enables remote debugging and specifies the debugging port number.
- Precautions: Ensure the debugging port is only open in trusted network environments. Avoid exposing it on public networks to prevent malicious attacks.
-
--disable-web-security- Purpose: Disables the same-origin policy, allowing cross-origin requests.
- Precautions: Use only in development or testing environments. Never enable in production to prevent potential security vulnerabilities.
-
--no-sandbox- Purpose: Disables the sandbox mechanism, reducing process isolation protection.
- Precautions: Ensure the environment is secure when using this option to prevent malware from exploiting this configuration.
-
--ignore-certificate-errors- Purpose: Ignores certificate errors, allowing self-signed certificates.
- Precautions: Use only in trusted environments. Avoid enabling in production to prevent man-in-the-middle attacks.
-
--gpu-launcher- Purpose: Specifies the launcher command for the GPU process.
- Precautions: Primarily used for advanced debugging or specific GPU configurations. Understand its specific usage and potential impact.
-
--inspectand--inspect-brk- Purpose: Starts the debug server, supporting background debugging and pause on startup.
- Precautions: Avoid using in production environments to ensure debugging security.
-
--host-rules- Purpose: Configures routing or redirection of network requests.
- Precautions: Configure the syntax correctly to ensure network request security and compliance.
Summary: These parameters are very useful during development and debugging, but should be used with caution. Ensure the environment is secure and avoid enabling parameters that may weaken security in production environments.
Publishing Issues
If you encounter the following error when publishing an Electron application to the PC App Store, check whether the application permission declarations include permissions that are only for 2-in-1 devices.
If they do, here are two solutions:
- For applications that do not need to be published on pad: Remove the pad_entry module.
- For applications that need to be published on both pad and PC: Move the permissions that are only for 2-in-1 devices from the web_engine module to the pc_entry module.
Troubleshooting
For crash issues, please provide the corresponding daily build version (e.g., 20241229.1) or the code commit ID (can be viewed using git log, e.g., 162a67b2a0a2a6f36e47d4e6c10cb780dd8c99b4) and crash stack trace information (click the save button shown in the figure below in DevEco Studio to save the information locally).

Secure Shield Mode
Secure Shield Mode is a system-level security protection solution designed for users with high security requirements. This mode significantly enhances system security by enforcing strict functional restrictions, effectively preventing various threats targeting remote attack surfaces. Under Secure Shield Mode, Electron has additional functional restrictions, and developers need to evaluate application usability in this mode.
Enabling Secure Shield Mode
To enable Secure Shield Mode, follow these steps:
- Go to System Settings
- Select "Privacy & Security"
- Click "Secure Shield Mode" and enable it
Functional Restrictions in Secure Shield Mode
To reduce the attack risk for Electron, Secure Shield Mode enforces the following key security restrictions:
- Completely disables Just-In-Time (JIT) compilation, including for applications that have obtained ACL permissions
- Suspends WebAssembly support (in the current version, WebAssembly depends on JIT functionality)
Application Compatibility Assessment Guide
When running applications in Secure Shield Mode, the following compatibility checks are recommended:
-
JavaScript Performance Assessment:
- Test the application's runtime efficiency in the restricted environment
- Optimize potential performance bottlenecks
-
WebAssembly Compatibility Check:
- Static code analysis: Check the project for WebAssembly-related API calls and third-party library Wasm dependencies.
- Runtime verification: Execute full-functionality testing in Secure Shield Mode.
Reference Documentation: