Electron Documentation
Docs / All
Accelerator
Define keyboard shortcuts.
Accelerators are Strings that can contain multiple modifiers and a single key code,
combined by the +
character, and are used to define keyboard shortcuts
throughout your application.
Examples:
CommandOrControl+A
CommandOrControl+Shift+Z
Shortcuts are registered with the globalShortcut
module
using the register
method, i.e.
const { app, globalShortcut } = require('electron')
app.whenReady().then(() => {
// Register a 'CommandOrControl+Y' shortcut listener.
globalShortcut.register('CommandOrControl+Y', () => {
// Do stuff when Y and either Command/Control is pressed.
})
})
Platform notice
On Linux and Windows, the Command
key does not have any effect so
use CommandOrControl
which represents Command
on macOS and Control
on
Linux and Windows to define some accelerators.
Use Alt
instead of Option
. The Option
key only exists on macOS, whereas
the Alt
key is available on all platforms.
The Super
key is mapped to the Windows
key on Windows and Linux and
Cmd
on macOS.
Available modifiers
Command
(orCmd
for short)Control
(orCtrl
for short)CommandOrControl
(orCmdOrCtrl
for short)Alt
Option
AltGr
Shift
Super
Available key codes
0
to9
A
toZ
F1
toF24
- Punctuation like
~
,!
,@
,#
,$
, etc. Plus
Space
Tab
Capslock
Numlock
Scrolllock
Backspace
Delete
Insert
Return
(orEnter
as alias)Up
,Down
,Left
andRight
Home
andEnd
PageUp
andPageDown
Escape
(orEsc
for short)VolumeUp
,VolumeDown
andVolumeMute
MediaNextTrack
,MediaPreviousTrack
,MediaStop
andMediaPlayPause
PrintScreen
- NumPad Keys
num0
-num9
numdec
- decimal keynumadd
- numpad+
keynumsub
- numpad-
keynummult
- numpad*
keynumdiv
- numpad÷
key
Accessibility
Making accessible applications is important and we're happy to provide functionality to Devtron and Spectron that gives developers the opportunity to make their apps better for everyone.
Accessibility concerns in Electron applications are similar to those of websites because they're both ultimately HTML. With Electron apps, however, you can't use the online resources for accessibility audits because your app doesn't have a URL to point the auditor to.
These features bring those auditing tools to your Electron app. You can choose to add audits to your tests with Spectron or use them within DevTools with Devtron. Read on for a summary of the tools.
Spectron
In the testing framework Spectron, you can now audit each window and <webview>
tag in your application. For example:
app.client.auditAccessibility().then(function (audit) {
if (audit.failed) {
console.error(audit.message)
}
})
You can read more about this feature in Spectron's documentation.
Devtron
In Devtron, there is an accessibility tab which will allow you to audit a page in your app, sort and filter the results.
Both of these tools are using the Accessibility Developer Tools library built by Google for Chrome. You can learn more about the accessibility audit rules this library uses on that repository's wiki.
If you know of other great accessibility tools for Electron, add them to the accessibility documentation with a pull request.
Manually enabling accessibility features
Electron applications will automatically enable accessibility features in the presence of assistive technology (e.g. JAWS on Windows or VoiceOver on macOS). See Chrome's accessibility documentation for more details.
You can also manually toggle these features either within your Electron application or by setting flags in third-party native software.
Using Electron's API
By using the app.setAccessibilitySupportEnabled(enabled)
API, you can manually expose Chrome's accessibility tree to users in the application preferences.
Note that the user's system assistive utilities have priority over this setting and
will override it.
macOS
On macOS, third-party assistive technology can toggle accessibility features inside
Electron applications by setting the AXManualAccessibility
attribute
programmatically:
CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility");
+ (void)enableAccessibility:(BOOL)enable inElectronApplication:(NSRunningApplication *)app
{
AXUIElementRef appRef = AXUIElementCreateApplication(app.processIdentifier);
if (appRef == nil)
return;
CFBooleanRef value = enable ? kCFBooleanTrue : kCFBooleanFalse;
AXUIElementSetAttributeValue(appRef, kAXManualAccessibility, value);
CFRelease(appRef);
}
app
Control your application's event lifecycle.
Process: Main
The following example shows how to quit the application when the last window is closed:
const { app } = require('electron')
app.on('window-all-closed', () => {
app.quit()
})
Events
The app
object emits the following events:
Event: 'will-finish-launching'
Emitted when the application has finished basic startup. On Windows and Linux,
the will-finish-launching
event is the same as the ready
event; on macOS,
this event represents the applicationWillFinishLaunching
notification of
NSApplication
. You would usually set up listeners for the open-file
and
open-url
events here, and start the crash reporter and auto updater.
In most cases, you should do everything in the ready
event handler.
Event: 'ready'
Returns:
event
EventlaunchInfo
Record<string, any> macOS
Emitted once, when Electron has finished initializing. On macOS, launchInfo
holds the userInfo
of the NSUserNotification
that was used to open the
application, if it was launched from Notification Center. You can also call
app.isReady()
to check if this event has already fired and app.whenReady()
to get a Promise that is fulfilled when Electron is initialized.
Event: 'window-all-closed'
Emitted when all windows have been closed.
If you do not subscribe to this event and all windows are closed, the default
behavior is to quit the app; however, if you subscribe, you control whether the
app quits or not. If the user pressed Cmd + Q
, or the developer called
app.quit()
, Electron will first try to close all the windows and then emit the
will-quit
event, and in this case the window-all-closed
event would not be
emitted.
Event: 'before-quit'
Returns:
event
Event
Emitted before the application starts closing its windows.
Calling event.preventDefault()
will prevent the default behavior, which is
terminating the application.
Note: If application quit was initiated by autoUpdater.quitAndInstall()
,
then before-quit
is emitted after emitting close
event on all windows and
closing them.
Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.
Event: 'will-quit'
Returns:
event
Event
Emitted when all windows have been closed and the application will quit.
Calling event.preventDefault()
will prevent the default behavior, which is
terminating the application.
See the description of the window-all-closed
event for the differences between
the will-quit
and window-all-closed
events.
Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.
Event: 'quit'
Returns:
event
EventexitCode
Integer
Emitted when the application is quitting.
Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.
Event: 'open-file' macOS
Returns:
event
Eventpath
String
Emitted when the user wants to open a file with the application. The open-file
event is usually emitted when the application is already open and the OS wants
to reuse the application to open the file. open-file
is also emitted when a
file is dropped onto the dock and the application is not yet running. Make sure
to listen for the open-file
event very early in your application startup to
handle this case (even before the ready
event is emitted).
You should call event.preventDefault()
if you want to handle this event.
On Windows, you have to parse process.argv
(in the main process) to get the
filepath.
Event: 'open-url' macOS
Returns:
event
Eventurl
String
Emitted when the user wants to open a URL with the application. Your application's
Info.plist
file must define the URL scheme within the CFBundleURLTypes
key, and
set NSPrincipalClass
to AtomApplication
.
You should call event.preventDefault()
if you want to handle this event.
Event: 'activate' macOS
Returns:
event
EventhasVisibleWindows
Boolean
Emitted when the application is activated. Various actions can trigger this event, such as launching the application for the first time, attempting to re-launch the application when it's already running, or clicking on the application's dock or taskbar icon.
Event: 'did-become-active' macOS
Returns:
event
Event
Emitted when mac application become active. Difference from activate
event is
that did-become-active
is emitted every time the app becomes active, not only
when Dock icon is clicked or application is re-launched.
Event: 'continue-activity' macOS
Returns:
event
Eventtype
String - A string identifying the activity. Maps toNSUserActivity.activityType
.userInfo
unknown - Contains app-specific state stored by the activity on another device.
Emitted during Handoff when an activity from a different device wants
to be resumed. You should call event.preventDefault()
if you want to handle
this event.
A user activity can be continued only in an app that has the same developer Team
ID as the activity's source app and that supports the activity's type.
Supported activity types are specified in the app's Info.plist
under the
NSUserActivityTypes
key.
Event: 'will-continue-activity' macOS
Returns:
event
Eventtype
String - A string identifying the activity. Maps toNSUserActivity.activityType
.
Emitted during Handoff before an activity from a different device wants
to be resumed. You should call event.preventDefault()
if you want to handle
this event.
Event: 'continue-activity-error' macOS
Returns:
event
Eventtype
String - A string identifying the activity. Maps toNSUserActivity.activityType
.error
String - A string with the error's localized description.
Emitted during Handoff when an activity from a different device fails to be resumed.
Event: 'activity-was-continued' macOS
Returns:
event
Eventtype
String - A string identifying the activity. Maps toNSUserActivity.activityType
.userInfo
unknown - Contains app-specific state stored by the activity.
Emitted during Handoff after an activity from this device was successfully resumed on another one.
Event: 'update-activity-state' macOS
Returns:
event
Eventtype
String - A string identifying the activity. Maps toNSUserActivity.activityType
.userInfo
unknown - Contains app-specific state stored by the activity.
Emitted when Handoff is about to be resumed on another device. If you need to update the state to be transferred, you should call event.preventDefault()
immediately, construct a new userInfo
dictionary and call app.updateCurrentActivity()
in a timely manner. Otherwise, the operation will fail and continue-activity-error
will be called.
Event: 'new-window-for-tab' macOS
Returns:
event
Event
Emitted when the user clicks the native macOS new tab button. The new
tab button is only visible if the current BrowserWindow
has a
tabbingIdentifier
Event: 'browser-window-blur'
Returns:
event
Eventwindow
BrowserWindow
Emitted when a browserWindow gets blurred.
Event: 'browser-window-focus'
Returns:
event
Eventwindow
BrowserWindow
Emitted when a browserWindow gets focused.
Event: 'browser-window-created'
Returns:
event
Eventwindow
BrowserWindow
Emitted when a new browserWindow is created.
Event: 'web-contents-created'
Returns:
event
EventwebContents
WebContents
Emitted when a new webContents is created.
Event: 'certificate-error'
Returns:
event
EventwebContents
WebContentsurl
Stringerror
String - The error codecertificate
Certificatecallback
FunctionisTrusted
Boolean - Whether to consider the certificate as trusted
Emitted when failed to verify the certificate
for url
, to trust the
certificate you should prevent the default behavior with
event.preventDefault()
and call callback(true)
.
const { app } = require('electron')
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
if (url === 'https://github.com') {
// Verification logic.
event.preventDefault()
callback(true)
} else {
callback(false)
}
})
Event: 'select-client-certificate'
Returns:
event
EventwebContents
WebContentsurl
URLcertificateList
Certificate[]callback
Functioncertificate
Certificate (optional)
Emitted when a client certificate is requested.
The url
corresponds to the navigation entry requesting the client certificate
and callback
can be called with an entry filtered from the list. Using
event.preventDefault()
prevents the application from using the first
certificate from the store.
const { app } = require('electron')
app.on('select-client-certificate', (event, webContents, url, list, callback) => {
event.preventDefault()
callback(list[0])
})
Event: 'login'
Returns:
event
EventwebContents
WebContentsauthenticationResponseDetails
Objecturl
URL
authInfo
ObjectisProxy
Booleanscheme
Stringhost
Stringport
Integerrealm
String
callback
Functionusername
String (optional)password
String (optional)
Emitted when webContents
wants to do basic auth.
The default behavior is to cancel all authentications. To override this you
should prevent the default behavior with event.preventDefault()
and call
callback(username, password)
with the credentials.
const { app } = require('electron')
app.on('login', (event, webContents, details, authInfo, callback) => {
event.preventDefault()
callback('username', 'secret')
})
If callback
is called without a username or password, the authentication
request will be cancelled and the authentication error will be returned to the
page.
Event: 'gpu-info-update'
Emitted whenever there is a GPU info update.
Event: 'gpu-process-crashed' Deprecated
Returns:
event
Eventkilled
Boolean
Emitted when the GPU process crashes or is killed.
Deprecated: This event is superceded by the child-process-gone
event
which contains more information about why the child process disappeared. It
isn't always because it crashed. The killed
boolean can be replaced by
checking reason === 'killed'
when you switch to that event.
Event: 'renderer-process-crashed' Deprecated
Returns:
event
EventwebContents
WebContentskilled
Boolean
Emitted when the renderer process of webContents
crashes or is killed.
Deprecated: This event is superceded by the render-process-gone
event
which contains more information about why the render process disappeared. It
isn't always because it crashed. The killed
boolean can be replaced by
checking reason === 'killed'
when you switch to that event.
Event: 'render-process-gone'
Returns:
event
EventwebContents
WebContentsdetails
Objectreason
String - The reason the render process is gone. Possible values:clean-exit
- Process exited with an exit code of zeroabnormal-exit
- Process exited with a non-zero exit codekilled
- Process was sent a SIGTERM or otherwise killed externallycrashed
- Process crashedoom
- Process ran out of memorylaunch-failed
- Process never successfully launchedintegrity-failure
- Windows code integrity checks failed
Emitted when the renderer process unexpectedly disappears. This is normally because it was crashed or killed.
Event: 'child-process-gone'
Returns:
event
Eventdetails
Objecttype
String - Process type. One of the following values:Utility
Zygote
Sandbox helper
GPU
Pepper Plugin
Pepper Plugin Broker
Unknown
reason
String - The reason the child process is gone. Possible values:clean-exit
- Process exited with an exit code of zeroabnormal-exit
- Process exited with a non-zero exit codekilled
- Process was sent a SIGTERM or otherwise killed externallycrashed
- Process crashedoom
- Process ran out of memorylaunch-failed
- Process never successfully launchedintegrity-failure
- Windows code integrity checks failed
exitCode
Number - The exit code for the process (e.g. status from waitpid if on posix, from GetExitCodeProcess on Windows).name
String (optional) - The name of the process. i.e. for plugins it might be Flash. Examples for utility:Audio Service
,Content Decryption Module Service
,Network Service
,Video Capture
, etc.
Emitted when the child process unexpectedly disappears. This is normally because it was crashed or killed. It does not include renderer processes.
Event: 'accessibility-support-changed' macOS Windows
Returns:
event
EventaccessibilitySupportEnabled
Boolean -true
when Chrome's accessibility support is enabled,false
otherwise.
Emitted when Chrome's accessibility support changes. This event fires when assistive technologies, such as screen readers, are enabled or disabled. See https://www.chromium.org/developers/design-documents/accessibility for more details.
Event: 'session-created'
Returns:
session
Session
Emitted when Electron has created a new session
.
const { app } = require('electron')
app.on('session-created', (session) => {
console.log(session)
})
Event: 'second-instance'
Returns:
event
Eventargv
String[] - An array of the second instance's command line argumentsworkingDirectory
String - The second instance's working directory
This event will be emitted inside the primary instance of your application
when a second instance has been executed and calls app.requestSingleInstanceLock()
.
argv
is an Array of the second instance's command line arguments,
and workingDirectory
is its current working directory. Usually
applications respond to this by making their primary window focused and
non-minimized.
Note: If the second instance is started by a different user than the first, the argv
array will not include the arguments.
This event is guaranteed to be emitted after the ready
event of app
gets emitted.
Note: Extra command line arguments might be added by Chromium,
such as --original-process-start-time
.
Event: 'desktop-capturer-get-sources'
Returns:
event
EventwebContents
WebContents
Emitted when desktopCapturer.getSources()
is called in the renderer process of webContents
.
Calling event.preventDefault()
will make it return empty sources.
Event: 'remote-require'
Returns:
event
EventwebContents
WebContentsmoduleName
String
Emitted when remote.require()
is called in the renderer process of webContents
.
Calling event.preventDefault()
will prevent the module from being returned.
Custom value can be returned by setting event.returnValue
.
Event: 'remote-get-global'
Returns:
event
EventwebContents
WebContentsglobalName
String
Emitted when remote.getGlobal()
is called in the renderer process of webContents
.
Calling event.preventDefault()
will prevent the global from being returned.
Custom value can be returned by setting event.returnValue
.
Event: 'remote-get-builtin'
Returns:
event
EventwebContents
WebContentsmoduleName
String
Emitted when remote.getBuiltin()
is called in the renderer process of webContents
.
Calling event.preventDefault()
will prevent the module from being returned.
Custom value can be returned by setting event.returnValue
.
Event: 'remote-get-current-window'
Returns:
event
EventwebContents
WebContents
Emitted when remote.getCurrentWindow()
is called in the renderer process of webContents
.
Calling event.preventDefault()
will prevent the object from being returned.
Custom value can be returned by setting event.returnValue
.
Event: 'remote-get-current-web-contents'
Returns:
event
EventwebContents
WebContents
Emitted when remote.getCurrentWebContents()
is called in the renderer process of webContents
.
Calling event.preventDefault()
will prevent the object from being returned.
Custom value can be returned by setting event.returnValue
.
Methods
The app
object has the following methods:
Note: Some methods are only available on specific operating systems and are labeled as such.
app.quit()
Try to close all windows. The before-quit
event will be emitted first. If all
windows are successfully closed, the will-quit
event will be emitted and by
default the application will terminate.
This method guarantees that all beforeunload
and unload
event handlers are
correctly executed. It is possible that a window cancels the quitting by
returning false
in the beforeunload
event handler.
app.exit([exitCode])
exitCode
Integer (optional)
Exits immediately with exitCode
. exitCode
defaults to 0.
All windows will be closed immediately without asking the user, and the before-quit
and will-quit
events will not be emitted.
app.relaunch([options])
options
Object (optional)args
String[] (optional)execPath
String (optional)
Relaunches the app when current instance exits.
By default, the new instance will use the same working directory and command line
arguments with current instance. When args
is specified, the args
will be
passed as command line arguments instead. When execPath
is specified, the
execPath
will be executed for relaunch instead of current app.
Note that this method does not quit the app when executed, you have to call
app.quit
or app.exit
after calling app.relaunch
to make the app restart.
When app.relaunch
is called for multiple times, multiple instances will be
started after current instance exited.
An example of restarting current instance immediately and adding a new command line argument to the new instance:
const { app } = require('electron')
app.relaunch({ args: process.argv.slice(1).concat(['--relaunch']) })
app.exit(0)
app.isReady()
Returns Boolean
- true
if Electron has finished initializing, false
otherwise.
See also app.whenReady()
.
app.whenReady()
Returns Promise<void>
- fulfilled when Electron is initialized.
May be used as a convenient alternative to checking app.isReady()
and subscribing to the ready
event if the app is not ready yet.
app.focus([options])
options
Object (optional)steal
Boolean macOS - Make the receiver the active app even if another app is currently active.
On Linux, focuses on the first visible window. On macOS, makes the application the active app. On Windows, focuses on the application's first window.
You should seek to use the steal
option as sparingly as possible.
app.hide()
macOS
Hides all application windows without minimizing them.
app.show()
macOS
Shows application windows after they were hidden. Does not automatically focus them.
app.setAppLogsPath([path])
path
String (optional) - A custom path for your logs. Must be absolute.
Sets or creates a directory your app's logs which can then be manipulated with app.getPath()
or app.setPath(pathName, newPath)
.
Calling app.setAppLogsPath()
without a path
parameter will result in this directory being set to ~/Library/Logs/YourAppName
on macOS, and inside the userData
directory on Linux and Windows.
app.getAppPath()
Returns String
- The current application directory.
app.getPath(name)
name
String - You can request the following paths by the name:home
User's home directory.appData
Per-user application data directory, which by default points to:%APPDATA%
on Windows$XDG_CONFIG_HOME
or~/.config
on Linux~/Library/Application Support
on macOS
userData
The directory for storing your app's configuration files, which by default it is theappData
directory appended with your app's name.cache
temp
Temporary directory.exe
The current executable file.module
Thelibchromiumcontent
library.desktop
The current user's Desktop directory.documents
Directory for a user's "My Documents".downloads
Directory for a user's downloads.music
Directory for a user's music.pictures
Directory for a user's pictures.videos
Directory for a user's videos.recent
Directory for the user's recent files (Windows only).logs
Directory for your app's log folder.pepperFlashSystemPlugin
Full path to the system version of the Pepper Flash plugin.crashDumps
Directory where crash dumps are stored.
Returns String
- A path to a special directory or file associated with name
. On
failure, an Error
is thrown.
If app.getPath('logs')
is called without called app.setAppLogsPath()
being called first, a default log directory will be created equivalent to calling app.setAppLogsPath()
without a path
parameter.
app.getFileIcon(path[, options])
path
Stringoptions
Object (optional)size
Stringsmall
- 16x16normal
- 32x32large
- 48x48 on Linux, 32x32 on Windows, unsupported on macOS.
Returns Promise<NativeImage>
- fulfilled with the app's icon, which is a NativeImage.
Fetches a path's associated icon.
On Windows, there a 2 kinds of icons:
- Icons associated with certain file extensions, like
.mp3
,.png
, etc. - Icons inside the file itself, like
.exe
,.dll
,.ico
.
On Linux and macOS, icons depend on the application associated with file mime type.
app.setPath(name, path)
name
Stringpath
String
Overrides the path
to a special directory or file associated with name
.
If the path specifies a directory that does not exist, an Error
is thrown.
In that case, the directory should be created with fs.mkdirSync
or similar.
You can only override paths of a name
defined in app.getPath
.
By default, web pages' cookies and caches will be stored under the userData
directory. If you want to change this location, you have to override the
userData
path before the ready
event of the app
module is emitted.
app.getVersion()
Returns String
- The version of the loaded application. If no version is found in the
application's package.json
file, the version of the current bundle or
executable is returned.
app.getName()
Returns String
- The current application's name, which is the name in the application's
package.json
file.
Usually the name
field of package.json
is a short lowercase name, according
to the npm modules spec. You should usually also specify a productName
field, which is your application's full capitalized name, and which will be
preferred over name
by Electron.
app.setName(name)
name
String
Overrides the current application's name.
Note: This function overrides the name used internally by Electron; it does not affect the name that the OS uses.
app.getLocale()
Returns String
- The current application locale. Possible return values are documented here.
To set the locale, you'll want to use a command line switch at app startup, which may be found here.
Note: When distributing your packaged app, you have to also ship the
locales
folder.
Note: On Windows, you have to call it after the ready
events gets emitted.
app.getLocaleCountryCode()
Returns String
- User operating system's locale two-letter ISO 3166 country code. The value is taken from native OS APIs.
Note: When unable to detect locale country code, it returns empty string.
app.addRecentDocument(path)
macOS Windows
path
String
Adds path
to the recent documents list.
This list is managed by the OS. On Windows, you can visit the list from the task bar, and on macOS, you can visit it from dock menu.
app.clearRecentDocuments()
macOS Windows
Clears the recent documents list.
app.setAsDefaultProtocolClient(protocol[, path, args])
protocol
String - The name of your protocol, without://
. For example, if you want your app to handleelectron://
links, call this method withelectron
as the parameter.path
String (optional) Windows - The path to the Electron executable. Defaults toprocess.execPath
args
String[] (optional) Windows - Arguments passed to the executable. Defaults to an empty array
Returns Boolean
- Whether the call succeeded.
Sets the current executable as the default handler for a protocol (aka URI
scheme). It allows you to integrate your app deeper into the operating system.
Once registered, all links with your-protocol://
will be opened with the
current executable. The whole link, including protocol, will be passed to your
application as a parameter.
Note: On macOS, you can only register protocols that have been added to
your app's info.plist
, which cannot be modified at runtime. However, you can
change the file during build time via Electron Forge,
Electron Packager, or by editing info.plist
with a text
editor. Please refer to Apple's documentation for details.
Note: In a Windows Store environment (when packaged as an appx
) this API
will return true
for all calls but the registry key it sets won't be accessible
by other applications. In order to register your Windows Store application
as a default protocol handler you must declare the protocol in your manifest.
The API uses the Windows Registry and LSSetDefaultHandlerForURLScheme
internally.
app.removeAsDefaultProtocolClient(protocol[, path, args])
macOS Windows
protocol
String - The name of your protocol, without://
.path
String (optional) Windows - Defaults toprocess.execPath
args
String[] (optional) Windows - Defaults to an empty array
Returns Boolean
- Whether the call succeeded.
This method checks if the current executable as the default handler for a protocol (aka URI scheme). If so, it will remove the app as the default handler.
app.isDefaultProtocolClient(protocol[, path, args])
protocol
String - The name of your protocol, without://
.path
String (optional) Windows - Defaults toprocess.execPath
args
String[] (optional) Windows - Defaults to an empty array
Returns Boolean
- Whether the current executable is the default handler for a
protocol (aka URI scheme).
Note: On macOS, you can use this method to check if the app has been
registered as the default protocol handler for a protocol. You can also verify
this by checking ~/Library/Preferences/com.apple.LaunchServices.plist
on the
macOS machine. Please refer to
Apple's documentation for details.
The API uses the Windows Registry and LSCopyDefaultHandlerForURLScheme
internally.
app.getApplicationNameForProtocol(url)
url
String - a URL with the protocol name to check. Unlike the other methods in this family, this accepts an entire URL, including://
at a minimum (e.g.https://
).
Returns String
- Name of the application handling the protocol, or an empty
string if there is no handler. For instance, if Electron is the default
handler of the URL, this could be Electron
on Windows and Mac. However,
don't rely on the precise format which is not guaranteed to remain unchanged.
Expect a different format on Linux, possibly with a .desktop
suffix.
This method returns the application name of the default handler for the protocol (aka URI scheme) of a URL.
app.getApplicationInfoForProtocol(url)
macOS Windows
url
String - a URL with the protocol name to check. Unlike the other methods in this family, this accepts an entire URL, including://
at a minimum (e.g.https://
).
Returns Promise<Object>
- Resolve with an object containing the following:
icon
NativeImage - the display icon of the app handling the protocol.path
String - installation path of the app handling the protocol.name
String - display name of the app handling the protocol.
This method returns a promise that contains the application name, icon and path of the default handler for the protocol (aka URI scheme) of a URL.
app.setUserTasks(tasks)
Windows
tasks
Task[] - Array ofTask
objects
Adds tasks
to the Tasks category of the Jump List on Windows.
tasks
is an array of Task
objects.
Returns Boolean
- Whether the call succeeded.
Note: If you'd like to customize the Jump List even more use
app.setJumpList(categories)
instead.
app.getJumpListSettings()
Windows
Returns Object
:
minItems
Integer - The minimum number of items that will be shown in the Jump List (for a more detailed description of this value see the MSDN docs).removedItems
JumpListItem[] - Array ofJumpListItem
objects that correspond to items that the user has explicitly removed from custom categories in the Jump List. These items must not be re-added to the Jump List in the next call toapp.setJumpList()
, Windows will not display any custom category that contains any of the removed items.
app.setJumpList(categories)
Windows
categories
JumpListCategory[] |null
- Array ofJumpListCategory
objects.
Sets or removes a custom Jump List for the application, and returns one of the following strings:
ok
- Nothing went wrong.error
- One or more errors occurred, enable runtime logging to figure out the likely cause.invalidSeparatorError
- An attempt was made to add a separator to a custom category in the Jump List. Separators are only allowed in the standardTasks
category.fileTypeRegistrationError
- An attempt was made to add a file link to the Jump List for a file type the app isn't registered to handle.customCategoryAccessDeniedError
- Custom categories can't be added to the Jump List due to user privacy or group policy settings.
If categories
is null
the previously set custom Jump List (if any) will be
replaced by the standard Jump List for the app (managed by Windows).
Note: If a JumpListCategory
object has neither the type
nor the name
property set then its type
is assumed to be tasks
. If the name
property
is set but the type
property is omitted then the type
is assumed to be
custom
.
Note: Users can remove items from custom categories, and Windows will not
allow a removed item to be added back into a custom category until after
the next successful call to app.setJumpList(categories)
. Any attempt to
re-add a removed item to a custom category earlier than that will result in the
entire custom category being omitted from the Jump List. The list of removed
items can be obtained using app.getJumpListSettings()
.
Here's a very simple example of creating a custom Jump List:
const { app } = require('electron')
app.setJumpList([
{
type: 'custom',
name: 'Recent Projects',
items: [
{ type: 'file', path: 'C:\\Projects\\project1.proj' },
{ type: 'file', path: 'C:\\Projects\\project2.proj' }
]
},
{ // has a name so `type` is assumed to be "custom"
name: 'Tools',
items: [
{
type: 'task',
title: 'Tool A',
program: process.execPath,
args: '--run-tool-a',
icon: process.execPath,
iconIndex: 0,
description: 'Runs Tool A'
},
{
type: 'task',
title: 'Tool B',
program: process.execPath,
args: '--run-tool-b',
icon: process.execPath,
iconIndex: 0,
description: 'Runs Tool B'
}
]
},
{ type: 'frequent' },
{ // has no name and no type so `type` is assumed to be "tasks"
items: [
{
type: 'task',
title: 'New Project',
program: process.execPath,
args: '--new-project',
description: 'Create a new project.'
},
{ type: 'separator' },
{
type: 'task',
title: 'Recover Project',
program: process.execPath,
args: '--recover-project',
description: 'Recover Project'
}
]
}
])
app.requestSingleInstanceLock()
Returns Boolean
The return value of this method indicates whether or not this instance of your application successfully obtained the lock. If it failed to obtain the lock, you can assume that another instance of your application is already running with the lock and exit immediately.
I.e. This method returns true
if your process is the primary instance of your
application and your app should continue loading. It returns false
if your
process should immediately quit as it has sent its parameters to another
instance that has already acquired the lock.
On macOS, the system enforces single instance automatically when users try to open
a second instance of your app in Finder, and the open-file
and open-url
events will be emitted for that. However when users start your app in command
line, the system's single instance mechanism will be bypassed, and you have to
use this method to ensure single instance.
An example of activating the window of primary instance when a second instance starts:
const { app } = require('electron')
let myWindow = null
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (myWindow) {
if (myWindow.isMinimized()) myWindow.restore()
myWindow.focus()
}
})
// Create myWindow, load the rest of the app, etc...
app.whenReady().then(() => {
myWindow = createWindow()
})
}
app.hasSingleInstanceLock()
Returns Boolean
This method returns whether or not this instance of your app is currently
holding the single instance lock. You can request the lock with
app.requestSingleInstanceLock()
and release with
app.releaseSingleInstanceLock()
app.releaseSingleInstanceLock()
Releases all locks that were created by requestSingleInstanceLock
. This will
allow multiple instances of the application to once again run side by side.
app.setUserActivity(type, userInfo[, webpageURL])
macOS
type
String - Uniquely identifies the activity. Maps toNSUserActivity.activityType
.userInfo
any - App-specific state to store for use by another device.webpageURL
String (optional) - The webpage to load in a browser if no suitable app is installed on the resuming device. The scheme must behttp
orhttps
.
Creates an NSUserActivity
and sets it as the current activity. The activity
is eligible for Handoff to another device afterward.
app.getCurrentActivityType()
macOS
Returns String
- The type of the currently running activity.
app.invalidateCurrentActivity()
macOS
Invalidates the current Handoff user activity.
app.resignCurrentActivity()
macOS
Marks the current Handoff user activity as inactive without invalidating it.
app.updateCurrentActivity(type, userInfo)
macOS
type
String - Uniquely identifies the activity. Maps toNSUserActivity.activityType
.userInfo
any - App-specific state to store for use by another device.
Updates the current activity if its type matches type
, merging the entries from
userInfo
into its current userInfo
dictionary.
app.setActivationPolicy(policy)
macOS
policy
String - Can be 'regular', 'accessory', or 'prohibited'.
Sets the activation policy for a given app.
Activation policy types:
- 'regular' - The application is an ordinary app that appears in the Dock and may have a user interface.
- 'accessory' - The application doesn’t appear in the Dock and doesn’t have a menu bar, but it may be activated programmatically or by clicking on one of its windows.
- 'prohibited' - The application doesn’t appear in the Dock and may not create windows or be activated.
app.importCertificate(options, callback)
Linux
options
Objectcertificate
String - Path for the pkcs12 file.password
String - Passphrase for the certificate.
callback
Functionresult
Integer - Result of import.
Imports the certificate in pkcs12 format into the platform certificate store.
callback
is called with the result
of import operation, a value of 0
indicates success while any other value indicates failure according to Chromium net_error_list.
app.disableHardwareAcceleration()
Disables hardware acceleration for current app.
This method can only be called before app is ready.
app.disableDomainBlockingFor3DAPIs()
By default, Chromium disables 3D APIs (e.g. WebGL) until restart on a per domain basis if the GPU processes crashes too frequently. This function disables that behavior.
This method can only be called before app is ready.
app.getAppMetrics()
Returns ProcessMetric[]
: Array of ProcessMetric
objects that correspond to memory and CPU usage statistics of all the processes associated with the app.
app.getGPUFeatureStatus()
Returns GPUFeatureStatus
- The Graphics Feature Status from chrome://gpu/
.
Note: This information is only usable after the gpu-info-update
event is emitted.
app.getGPUInfo(infoType)
infoType
String - Can bebasic
orcomplete
.
Returns Promise<unknown>
For infoType
equal to complete
:
Promise is fulfilled with Object
containing all the GPU Information as in chromium's GPUInfo object. This includes the version and driver information that's shown on chrome://gpu
page.
For infoType
equal to basic
:
Promise is fulfilled with Object
containing fewer attributes than when requested with complete
. Here's an example of basic response:
{
auxAttributes:
{
amdSwitchable: true,
canSupportThreadedTextureMailbox: false,
directComposition: false,
directRendering: true,
glResetNotificationStrategy: 0,
inProcessGpu: true,
initializationTime: 0,
jpegDecodeAcceleratorSupported: false,
optimus: false,
passthroughCmdDecoder: false,
sandboxed: false,
softwareRendering: false,
supportsOverlays: false,
videoDecodeAcceleratorFlags: 0
},
gpuDevice:
[{ active: true, deviceId: 26657, vendorId: 4098 },
{ active: false, deviceId: 3366, vendorId: 32902 }],
machineModelName: 'MacBookPro',
machineModelVersion: '11.5'
}
Using basic
should be preferred if only basic information like vendorId
or driverId
is needed.
app.setBadgeCount(count)
Linux macOS
count
Integer
Returns Boolean
- Whether the call succeeded.
Sets the counter badge for current app. Setting the count to 0
will hide the
badge.
On macOS, it shows on the dock icon. On Linux, it only works for Unity launcher.
Note: Unity launcher requires the existence of a .desktop
file to work,
for more information please read Desktop Environment Integration.
app.getBadgeCount()
Linux macOS
Returns Integer
- The current value displayed in the counter badge.
app.isUnityRunning()
Linux
Returns Boolean
- Whether the current desktop environment is Unity launcher.
app.getLoginItemSettings([options])
macOS Windows
options
Object (optional)path
String (optional) Windows - The executable path to compare against. Defaults toprocess.execPath
.args
String[] (optional) Windows - The command-line arguments to compare against. Defaults to an empty array.
If you provided path
and args
options to app.setLoginItemSettings
, then you
need to pass the same arguments here for openAtLogin
to be set correctly.
Returns Object
:
openAtLogin
Boolean -true
if the app is set to open at login.openAsHidden
Boolean macOS -true
if the app is set to open as hidden at login. This setting is not available on MAS builds.wasOpenedAtLogin
Boolean macOS -true
if the app was opened at login automatically. This setting is not available on MAS builds.wasOpenedAsHidden
Boolean macOS -true
if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. This setting is not available on MAS builds.restoreState
Boolean macOS -true
if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was closed. This setting is not available on MAS builds.executableWillLaunchAtLogin
Boolean Windows -true
if app is set to open at login and its run key is not deactivated. This differs fromopenAtLogin
as it ignores theargs
option, this property will be true if the given executable would be launched at login with any arguments.launchItems
Object[] Windowsname
String Windows - name value of a registry entry.path
String Windows - The executable to an app that corresponds to a registry entry.args
String[] Windows - the command-line arguments to pass to the executable.scope
String Windows - one ofuser
ormachine
. Indicates whether the registry entry is underHKEY_CURRENT USER
orHKEY_LOCAL_MACHINE
.enabled
Boolean Windows -true
if the app registry key is startup approved and therefore shows asenabled
in Task Manager and Windows settings.
app.setLoginItemSettings(settings)
macOS Windows
settings
ObjectopenAtLogin
Boolean (optional) -true
to open the app at login,false
to remove the app as a login item. Defaults tofalse
.openAsHidden
Boolean (optional) macOS -true
to open the app as hidden. Defaults tofalse
. The user can edit this setting from the System Preferences soapp.getLoginItemSettings().wasOpenedAsHidden
should be checked when the app is opened to know the current value. This setting is not available on MAS builds.path
String (optional) Windows - The executable to launch at login. Defaults toprocess.execPath
.args
String[] (optional) Windows - The command-line arguments to pass to the executable. Defaults to an empty array. Take care to wrap paths in quotes.enabled
Boolean (optional) Windows -true
will change the startup approved registry key andenable / disable
the App in Task Manager and Windows Settings. Defaults totrue
.name
String (optional) Windows - value name to write into registry. Defaults to the app's AppUserModelId(). Set the app's login item settings.
To work with Electron's autoUpdater
on Windows, which uses Squirrel,
you'll want to set the launch path to Update.exe, and pass arguments that specify your
application name. For example:
const appFolder = path.dirname(process.execPath)
const updateExe = path.resolve(appFolder, '..', 'Update.exe')
const exeName = path.basename(process.execPath)
app.setLoginItemSettings({
openAtLogin: true,
path: updateExe,
args: [
'--processStart', `"${exeName}"`,
'--process-start-args', `"--hidden"`
]
})
app.isAccessibilitySupportEnabled()
macOS Windows
Returns Boolean
- true
if Chrome's accessibility support is enabled,
false
otherwise. This API will return true
if the use of assistive
technologies, such as screen readers, has been detected. See
https://www.chromium.org/developers/design-documents/accessibility for more
details.
app.setAccessibilitySupportEnabled(enabled)
macOS Windows
enabled
Boolean - Enable or disable accessibility tree rendering
Manually enables Chrome's accessibility support, allowing to expose accessibility switch to users in application settings. See Chromium's accessibility docs for more details. Disabled by default.
This API must be called after the ready
event is emitted.
Note: Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.
app.showAboutPanel()
Show the app's about panel options. These options can be overridden with app.setAboutPanelOptions(options)
.
app.setAboutPanelOptions(options)
options
ObjectapplicationName
String (optional) - The app's name.applicationVersion
String (optional) - The app's version.copyright
String (optional) - Copyright information.version
String (optional) macOS - The app's build version number.credits
String (optional) macOS Windows - Credit information.authors
String[] (optional) Linux - List of app authors.website
String (optional) Linux - The app's website.iconPath
String (optional) Linux Windows - Path to the app's icon in a JPEG or PNG file format. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
Set the about panel options. This will override the values defined in the app's .plist
file on macOS. See the Apple docs for more details. On Linux, values must be set in order to be shown; there are no defaults.
If you do not set credits
but still wish to surface them in your app, AppKit will look for a file named "Credits.html", "Credits.rtf", and "Credits.rtfd", in that order, in the bundle returned by the NSBundle class method main. The first file found is used, and if none is found, the info area is left blank. See Apple documentation for more information.
app.isEmojiPanelSupported()
Returns Boolean
- whether or not the current OS version allows for native emoji pickers.
app.showEmojiPanel()
macOS Windows
Show the platform's native emoji picker.
app.startAccessingSecurityScopedResource(bookmarkData)
mas
bookmarkData
String - The base64 encoded security scoped bookmark data returned by thedialog.showOpenDialog
ordialog.showSaveDialog
methods.
Returns Function
- This function must be called once you have finished accessing the security scoped file. If you do not remember to stop accessing the bookmark, kernel resources will be leaked and your app will lose its ability to reach outside the sandbox completely, until your app is restarted.
// Start accessing the file.
const stopAccessingSecurityScopedResource = app.startAccessingSecurityScopedResource(data)
// You can now access the file outside of the sandbox 🎉
// Remember to stop accessing the file once you've finished with it.
stopAccessingSecurityScopedResource()
Start accessing a security scoped resource. With this method Electron applications that are packaged for the Mac App Store may reach outside their sandbox to access files chosen by the user. See Apple's documentation for a description of how this system works.
app.enableSandbox()
Enables full sandbox mode on the app. This means that all renderers will be launched sandboxed, regardless of the value of the sandbox
flag in WebPreferences.
This method can only be called before app is ready.
app.isInApplicationsFolder()
macOS
Returns Boolean
- Whether the application is currently running from the
systems Application folder. Use in combination with app.moveToApplicationsFolder()
app.moveToApplicationsFolder([options])
macOS
options
Object (optional)conflictHandler
Function\(optional) - A handler for potential conflict in move failure. conflictType
String - The type of move conflict encountered by the handler; can beexists
orexistsAndRunning
, whereexists
means that an app of the same name is present in the Applications directory andexistsAndRunning
means both that it exists and that it's presently running.
Returns Boolean
- Whether the move was successful. Please note that if
the move is successful, your application will quit and relaunch.
No confirmation dialog will be presented by default. If you wish to allow
the user to confirm the operation, you may do so using the
dialog
API.
NOTE: This method throws errors if anything other than the user causes the move to fail. For instance if the user cancels the authorization dialog, this method returns false. If we fail to perform the copy, then this method will throw an error. The message in the error should be informative and tell you exactly what went wrong.
By default, if an app of the same name as the one being moved exists in the Applications directory and is not running, the existing app will be trashed and the active app moved into its place. If it is running, the pre-existing running app will assume focus and the previously active app will quit itself. This behavior can be changed by providing the optional conflict handler, where the boolean returned by the handler determines whether or not the move conflict is resolved with default behavior. i.e. returning false
will ensure no further action is taken, returning true
will result in the default behavior and the method continuing.
For example:
app.moveToApplicationsFolder({
conflictHandler: (conflictType) => {
if (conflictType === 'exists') {
return dialog.showMessageBoxSync({
type: 'question',
buttons: ['Halt Move', 'Continue Move'],
defaultId: 0,
message: 'An app of this name already exists'
}) === 1
}
}
})
Would mean that if an app already exists in the user directory, if the user chooses to 'Continue Move' then the function would continue with its default behavior and the existing app will be trashed and the active app moved into its place.
app.isSecureKeyboardEntryEnabled()
macOS
Returns Boolean
- whether Secure Keyboard Entry
is enabled.
By default this API will return false
.
app.setSecureKeyboardEntryEnabled(enabled)
macOS
enabled
Boolean - Enable or disableSecure Keyboard Entry
Set the Secure Keyboard Entry
is enabled in your application.
By using this API, important information such as password and other sensitive information can be prevented from being intercepted by other processes.
See Apple's documentation for more details.
Note: Enable Secure Keyboard Entry
only when it is needed and disable it when it is no longer needed.
app.accessibilitySupportEnabled
macOS Windows
A Boolean
property that's true
if Chrome's accessibility support is enabled, false
otherwise. This property will be true
if the use of assistive technologies, such as screen readers, has been detected. Setting this property to true
manually enables Chrome's accessibility support, allowing developers to expose accessibility switch to users in application settings.
See Chromium's accessibility docs for more details. Disabled by default.
This API must be called after the ready
event is emitted.
Note: Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.
app.applicationMenu
A Menu | null
property that returns Menu
if one has been set and null
otherwise.
Users can pass a Menu to set this property.
app.badgeCount
Linux macOS
An Integer
property that returns the badge count for current app. Setting the count to 0
will hide the badge.
On macOS, setting this with any nonzero integer shows on the dock icon. On Linux, this property only works for Unity launcher.
Note: Unity launcher requires the existence of a .desktop
file to work,
for more information please read Desktop Environment Integration.
Note: On macOS, you need to ensure that your application has the permission to display notifications for this property to take effect.
app.commandLine
Readonly
A CommandLine
object that allows you to read and manipulate the
command line arguments that Chromium uses.
app.dock
macOS Readonly
A Dock
| undefined
object that allows you to perform actions on your app icon in the user's
dock on macOS.
app.isPackaged
Readonly
A Boolean
property that returns true
if the app is packaged, false
otherwise. For many apps, this property can be used to distinguish development and production environments.
app.name
A String
property that indicates the current application's name, which is the name in the application's package.json
file.
Usually the name
field of package.json
is a short lowercase name, according
to the npm modules spec. You should usually also specify a productName
field, which is your application's full capitalized name, and which will be
preferred over name
by Electron.
app.userAgentFallback
A String
which is the user agent string Electron will use as a global fallback.
This is the user agent that will be used when no user agent is set at the
webContents
or session
level. It is useful for ensuring that your entire
app has the same user agent. Set to a custom value as early as possible
in your app's initialization to ensure that your overridden value is used.
app.allowRendererProcessReuse
A Boolean
which when true
disables the overrides that Electron has in place
to ensure renderer processes are restarted on every navigation. The current
default value for this property is true
.
The intention is for these overrides to become disabled by default and then at some point in the future this property will be removed. This property impacts which native modules you can use in the renderer process. For more information on the direction Electron is going with renderer process restarts and usage of native modules in the renderer process please check out this Tracking Issue.
app.runningUnderRosettaTranslation
macOS Readonly
A Boolean
which when true
indicates that the app is currently running
under the Rosetta Translator Environment.
You can use this property to prompt users to download the arm64 version of your application when they are running the x64 version under Rosetta incorrectly.
Application Debugging
Whenever your Electron application is not behaving the way you wanted it to, an array of debugging tools might help you find coding errors, performance bottlenecks, or optimization opportunities.
Renderer Process
The most comprehensive tool to debug individual renderer processes is the
Chromium Developer Toolset. It is available for all renderer processes,
including instances of BrowserWindow
, BrowserView
, and WebView
. You
can open them programmatically by calling the openDevTools()
API on the
webContents
of the instance:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.webContents.openDevTools()
Google offers excellent documentation for their developer tools. We recommend that you make yourself familiar with them - they are usually one of the most powerful utilities in any Electron Developer's tool belt.
Main Process
Debugging the main process is a bit trickier, since you cannot open
developer tools for them. The Chromium Developer Tools can be used
to debug Electron's main process thanks to a closer collaboration
between Google / Chrome and Node.js, but you might encounter oddities like
require
not being present in the console.
For more information, see the Debugging the Main Process documentation.
V8 Crashes
If the V8 context crashes, the DevTools will display this message.
DevTools was disconnected from the page. Once page is reloaded, DevTools will automatically reconnect.
Chromium logs can be enabled via the ELECTRON_ENABLE_LOGGING
environment variable. For more information, see the environment variables documentation.
Alternatively, the command line argument --enable-logging
can be passed. More information is available in the command line switches documentation.
Overview
To distribute your app with Electron, you need to package and rebrand it. To do this, you can either use specialized tooling or manual approaches.
With tooling
You can use the following tools to distribute your application:
These tools will take care of all the steps you need to take to end up with a distributable Electron application, such as bundling your application, rebranding the executable, and setting the right icons.
You can check the example of how to package your app with electron-forge
in
our Quick Start Guide.
With prebuilt binaries
To distribute your app manually, you need to download Electron's prebuilt
binaries. Next, the folder
containing your app should be named app
and placed in Electron's resources
directory as shown in the following examples.
NOTE: the location of Electron's prebuilt binaries is indicated with
electron/
in the examples below.
On macOS:
electron/Electron.app/Contents/Resources/app/
├── package.json
├── main.js
└── index.html
On Windows and Linux:
electron/resources/app
├── package.json
├── main.js
└── index.html
Then execute Electron.app
on macOS, electron
on Linux, or electron.exe
on Windows, and Electron will start as your app. The electron
directory
will then be your distribution to deliver to users.
With an app source code archive
Instead of from shipping your app by copying all of its source files, you can package your app into an asar archive to improve the performance of reading files on platforms like Windows, if you are not already using a bundler such as Parcel or Webpack.
To use an asar
archive to replace the app
folder, you need to rename the
archive to app.asar
, and put it under Electron's resources directory like
below, and Electron will then try to read the archive and start from it.
On macOS:
electron/Electron.app/Contents/Resources/
└── app.asar
On Windows and Linux:
electron/resources/
└── app.asar
You can find more details on how to use asar
in the
electron/asar
repository.
Rebranding with downloaded binaries
After bundling your app into Electron, you will want to rebrand Electron before distributing it to users.
macOS
You can rename Electron.app
to any name you want, and you also have to rename
the CFBundleDisplayName
, CFBundleIdentifier
and CFBundleName
fields in the
following files:
Electron.app/Contents/Info.plist
Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist
You can also rename the helper app to avoid showing Electron Helper
in the
Activity Monitor, but make sure you have renamed the helper app's executable
file's name.
The structure of a renamed app would be like:
MyApp.app/Contents
├── Info.plist
├── MacOS/
│ └── MyApp
└── Frameworks/
└── MyApp Helper.app
├── Info.plist
└── MacOS/
└── MyApp Helper
Windows
You can rename electron.exe
to any name you like, and edit its icon and other
information with tools like rcedit.
Linux
You can rename the electron
executable to any name you like.
Rebranding by rebuilding Electron from source
It is also possible to rebrand Electron by changing the product name and
building it from source. To do this you need to set the build argument
corresponding to the product name (electron_product_name = "YourProductName"
)
in the args.gn
file and rebuild.
autoUpdater
Enable apps to automatically update themselves.
Process: Main
See also: A detailed guide about how to implement updates in your application.
autoUpdater
is an EventEmitter.
Platform Notices
Currently, only macOS and Windows are supported. There is no built-in support for auto-updater on Linux, so it is recommended to use the distribution's package manager to update your app.
In addition, there are some subtle differences on each platform:
macOS
On macOS, the autoUpdater
module is built upon Squirrel.Mac,
meaning you don't need any special setup to make it work. For server-side
requirements, you can read Server Support. Note that App
Transport Security (ATS) applies to all requests made as part of the
update process. Apps that need to disable ATS can add the
NSAllowsArbitraryLoads
key to their app's plist.
Note: Your application must be signed for automatic updates on macOS.
This is a requirement of Squirrel.Mac
.
Windows
On Windows, you have to install your app into a user's machine before you can
use the autoUpdater
, so it is recommended that you use the
electron-winstaller, electron-forge or the grunt-electron-installer package to generate a Windows installer.
When using electron-winstaller or electron-forge make sure you do not try to update your app the first time it runs (Also see this issue for more info). It's also recommended to use electron-squirrel-startup to get desktop shortcuts for your app.
The installer generated with Squirrel will create a shortcut icon with an
Application User Model ID in the format of
com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE
, examples are
com.squirrel.slack.Slack
and com.squirrel.code.Code
. You have to use the
same ID for your app with app.setAppUserModelId
API, otherwise Windows will
not be able to pin your app properly in task bar.
Unlike Squirrel.Mac, Windows can host updates on S3 or any other static file host. You can read the documents of Squirrel.Windows to get more details about how Squirrel.Windows works.
Events
The autoUpdater
object emits the following events:
Event: 'checking-for-update'
Emitted when checking if an update has started.
Event: 'update-available'
Emitted when there is an available update. The update is downloaded automatically.
Event: 'update-not-available'
Emitted when there is no available update.
Event: 'update-downloaded'
Returns:
event
EventreleaseNotes
StringreleaseName
StringreleaseDate
DateupdateURL
String
Emitted when an update has been downloaded.
On Windows only releaseName
is available.
Note: It is not strictly necessary to handle this event. A successfully downloaded update will still be applied the next time the application starts.
Event: 'before-quit-for-update'
This event is emitted after a user calls quitAndInstall()
.
When this API is called, the before-quit
event is not emitted before all windows are closed. As a result you should listen to this event if you wish to perform actions before the windows are closed while a process is quitting, as well as listening to before-quit
.
Methods
The autoUpdater
object has the following methods:
autoUpdater.setFeedURL(options)
options
Objecturl
Stringheaders
Record<String, String> (optional) macOS - HTTP request headers.serverType
String (optional) macOS - Can bejson
ordefault
, see the Squirrel.Mac README for more information.
Sets the url
and initialize the auto updater.
autoUpdater.getFeedURL()
Returns String
- The current update feed URL.
autoUpdater.checkForUpdates()
Asks the server whether there is an update. You must call setFeedURL
before
using this API.
autoUpdater.quitAndInstall()
Restarts the app and installs the update after it has been downloaded. It
should only be called after update-downloaded
has been emitted.
Under the hood calling autoUpdater.quitAndInstall()
will close all application
windows first, and automatically call app.quit()
after all windows have been
closed.
Note: It is not strictly necessary to call this function to apply an update, as a successfully downloaded update will always be applied the next time the application starts.
Automated Testing with a Custom Driver
To write automated tests for your Electron app, you will need a way to "drive" your application. Spectron is a commonly-used solution which lets you emulate user actions via WebDriver. However, it's also possible to write your own custom driver using node's builtin IPC-over-STDIO. The benefit of a custom driver is that it tends to require less overhead than Spectron, and lets you expose custom methods to your test suite.
To create a custom driver, we'll use Node.js' child_process API. The test suite will spawn the Electron process, then establish a simple messaging protocol:
const childProcess = require('child_process')
const electronPath = require('electron')
// spawn the process
const env = { /* ... */ }
const stdio = ['inherit', 'inherit', 'inherit', 'ipc']
const appProcess = childProcess.spawn(electronPath, ['./app'], { stdio, env })
// listen for IPC messages from the app
appProcess.on('message', (msg) => {
// ...
})
// send an IPC message to the app
appProcess.send({ my: 'message' })
From within the Electron app, you can listen for messages and send replies using the Node.js process API:
// listen for IPC messages from the test suite
process.on('message', (msg) => {
// ...
})
// send an IPC message to the test suite
process.send({ my: 'message' })
We can now communicate from the test suite to the Electron app using the appProcess
object.
For convenience, you may want to wrap appProcess
in a driver object that provides more high-level functions. Here is an example of how you can do this:
class TestDriver {
constructor ({ path, args, env }) {
this.rpcCalls = []
// start child process
env.APP_TEST_DRIVER = 1 // let the app know it should listen for messages
this.process = childProcess.spawn(path, args, { stdio: ['inherit', 'inherit', 'inherit', 'ipc'], env })
// handle rpc responses
this.process.on('message', (message) => {
// pop the handler
const rpcCall = this.rpcCalls[message.msgId]
if (!rpcCall) return
this.rpcCalls[message.msgId] = null
// reject/resolve
if (message.reject) rpcCall.reject(message.reject)
else rpcCall.resolve(message.resolve)
})
// wait for ready
this.isReady = this.rpc('isReady').catch((err) => {
console.error('Application failed to start', err)
this.stop()
process.exit(1)
})
}
// simple RPC call
// to use: driver.rpc('method', 1, 2, 3).then(...)
async rpc (cmd, ...args) {
// send rpc request
const msgId = this.rpcCalls.length
this.process.send({ msgId, cmd, args })
return new Promise((resolve, reject) => this.rpcCalls.push({ resolve, reject }))
}
stop () {
this.process.kill()
}
}
In the app, you'd need to write a simple handler for the RPC calls:
if (process.env.APP_TEST_DRIVER) {
process.on('message', onMessage)
}
async function onMessage ({ msgId, cmd, args }) {
let method = METHODS[cmd]
if (!method) method = () => new Error('Invalid method: ' + cmd)
try {
const resolve = await method(...args)
process.send({ msgId, resolve })
} catch (err) {
const reject = {
message: err.message,
stack: err.stack,
name: err.name
}
process.send({ msgId, reject })
}
}
const METHODS = {
isReady () {
// do any setup needed
return true
}
// define your RPC-able methods here
}
Then, in your test suite, you can use your test-driver as follows:
const test = require('ava')
const electronPath = require('electron')
const app = new TestDriver({
path: electronPath,
args: ['./app'],
env: {
NODE_ENV: 'test'
}
})
test.before(async t => {
await app.isReady
})
test.after.always('cleanup', async t => {
await app.stop()
})
Updating an Appveyor Azure Image
Electron CI on Windows uses AppVeyor, which in turn uses Azure VM images to run. Occasionally, these VM images need to be updated due to changes in Chromium requirements. In order to update you will need PowerShell and the Azure PowerShell module.
Occasionally we need to update these images owing to changes in Chromium or other miscellaneous build requirement changes.
Example Use Case:
* We need `VS15.9` and we have `VS15.7` installed; this would require us to update an Azure image.
-
Identify the image you wish to modify.
- In appveyor.yml, the image is identified by the property image.
- The names used correspond to the "images" defined for a build cloud, eg the libcc-20 cloud.
- Find the image you wish to modify in the build cloud and make note of the VHD Blob Path for that image, which is the value for that corresponding key.
- You will need this URI path to copy into a new image.
- You will also need the storage account name which is labeled in AppVeyor as the Disk Storage Account Name
- In appveyor.yml, the image is identified by the property image.
-
Get the Azure storage account key
- Log into Azure using credentials stored in LastPass (under Azure Enterprise) and then find the storage account corresponding to the name found in AppVeyor.
- Example, for
appveyorlibccbuilds
Disk Storage Account Name you'd look forappveyorlibccbuilds
in the list of storage accounts @ Home < Storage Accounts- Click into it and look for
Access Keys
, and then you can use any of the keys present in the list.
- Click into it and look for
- Example, for
- Log into Azure using credentials stored in LastPass (under Azure Enterprise) and then find the storage account corresponding to the name found in AppVeyor.
-
Get the full virtual machine image URI from Azure
- Navigate to Home < Storage Accounts <
$ACCT_NAME
< Blobs < Images- In the following list, look for the VHD path name you got from Appveyor and then click on it.
- Copy the whole URL from the top of the subsequent window.
- In the following list, look for the VHD path name you got from Appveyor and then click on it.
- Navigate to Home < Storage Accounts <
-
Copy the image using the Copy Master Image PowerShell script.
- It is essential to copy the VM because if you spin up a VM against an image that image cannot at the same time be used by AppVeyor.
- Use the storage account name, key, and URI obtained from Azure to run this script.
- See Step 3 for URI & when prompted, press enter to use same storage account as destination.
- Use default destination container name
(images)
- Also, when naming the copy, use a name that indicates what the new image will contain (if that has changed) and date stamp.
- Ex.
libcc-20core-vs2017-15.9-2019-04-15.vhd
- Ex.
- Go into Azure and get the URI for the newly created image as described in a previous step
-
Spin up a new VM using the Create Master VM from VHD PowerShell.
- From PowerShell, execute
ps1
file with./create_master_vm_from_vhd.ps1
- You will need the credential information available in the AppVeyor build cloud definition.
- This includes:
- Client ID
- Client Secret
- Tenant ID
- Subscription ID
- Resource Group
- Virtual Network
- This includes:
- You will also need to specify
- Master VM name - just a unique name to identify the temporary VM
- Master VM size - use
Standard_F32s_v2
- Master VHD URI - use URI obtained @ end of previous step
- Location use
East US
- From PowerShell, execute
-
Log back into Azure and find the VM you just created in Home < Virtual Machines <
$YOUR_NEW_VM
- You can download a RDP (Remote Desktop) file to access the VM.
-
Using Microsoft Remote Desktop, click
Connect
to connect to the VM.- Credentials for logging into the VM are found in LastPass under the
AppVeyor Enterprise master VM
credentials.
- Credentials for logging into the VM are found in LastPass under the
-
Modify the VM as required.
-
Shut down the VM and then delete it in Azure.
-
Add the new image to the Appveyor Cloud settings or modify an existing image to point to the new VHD.
BluetoothDevice Object
deviceName
StringdeviceId
String
Boilerplates and CLIs
Electron development is unopinionated - there is no "one true way" to develop, build, package, or release an Electron application. Additional features for Electron, both for build- and run-time, can usually be found on npm in individual packages, allowing developers to build both the app and build pipeline they need.
That level of modularity and extendability ensures that all developers working with Electron, both big and small in team-size, are never restricted in what they can or cannot do at any time during their development lifecycle. However, for many developers, one of the community-driven boilerplates or command line tools might make it dramatically easier to compile, package, and release an app.
Boilerplate vs CLI
A boilerplate is only a starting point - a canvas, so to speak - from which you build your application. They usually come in the form of a repository you can clone and customize to your heart's content.
A command line tool on the other hand continues to support you throughout the development and release. They are more helpful and supportive but enforce guidelines on how your code should be structured and built. Especially for beginners, using a command line tool is likely to be helpful.
electron-forge
A "complete tool for building modern Electron applications". Electron Forge unifies the existing (and well maintained) build tools for Electron development into a cohesive package so that anyone can jump right in to Electron development.
Forge comes with a ready-to-use template using Webpack as a bundler. It includes an example typescript configuration and provides two configuration files to enable easy customization. It uses the same core modules used by the
greater Electron community (like electron-packager
) –
changes made by Electron maintainers (like Slack) benefit Forge's users, too.
You can find more information and documentation on electronforge.io.
electron-builder
A "complete solution to package and build a ready-for-distribution Electron app"
that focuses on an integrated experience. electron-builder
adds one
single dependency focused on simplicity and manages all further requirements
internally.
electron-builder
replaces features and modules used by the Electron
maintainers (such as the auto-updater) with custom ones. They are generally
tighter integrated but will have less in common with popular Electron apps
like Atom, Visual Studio Code, or Slack.
You can find more information and documentation in the repository.
electron-react-boilerplate
If you don't want any tools but only a solid boilerplate to build from,
CT Lin's electron-react-boilerplate
might be worth
a look. It's quite popular in the community and uses electron-builder
internally.
Other Tools and Boilerplates
The "Awesome Electron" list contains more tools and boilerplates to choose from. If you find the length of the list intimidating, don't forget that adding tools as you go along is a valid approach, too.
Breaking Changes
Breaking changes will be documented here, and deprecation warnings added to JS code where possible, at least one major version before the change is made.
Types of Breaking Changes
This document uses the following convention to categorize breaking changes:
- API Changed: An API was changed in such a way that code that has not been updated is guaranteed to throw an exception.
- Behavior Changed: The behavior of Electron has changed, but not in such a way that an exception will necessarily be thrown.
- Default Changed: Code depending on the old default may break, not necessarily throwing an exception. The old behavior can be restored by explicitly specifying the value.
- Deprecated: An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
- Removed: An API or feature was removed, and is no longer supported by Electron.
API Changed: session.setPermissionCheckHandler(handler)
The handler
methods first parameter was previously always a webContents
, it can now sometimes be null
. You should use the requestingOrigin
, embeddingOrigin
and securityOrigin
properties to respond to the permission check correctly. As the webContents
can be null
it can no longer be relied on.
// Old code
session.setPermissionCheckHandler((webContents, permission) => {
if (webContents.getURL().startsWith('https://google.com/') && permission === 'notification') {
return true
}
return false
})
// Replace with
session.setPermissionCheckHandler((webContents, permission, requestingOrigin) => {
if (new URL(requestingOrigin).hostname === 'google.com' && permission === 'notification') {
return true
}
return false
})
Removed: shell.moveItemToTrash()
The deprecated synchronous shell.moveItemToTrash()
API has been removed. Use
the asynchronous shell.trashItem()
instead.
// Removed in Electron 13
shell.moveItemToTrash(path)
// Replace with
shell.trashItem(path).then(/* ... */)
Removed: BrowserWindow
extension APIs
The deprecated extension APIs have been removed:
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
Use the session APIs instead:
ses.loadExtension(path)
ses.removeExtension(extension_id)
ses.getAllExtensions()
// Removed in Electron 13
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
// Replace with
session.defaultSession.loadExtension(path)
// Removed in Electron 13
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
// Replace with
session.defaultSession.removeExtension(extension_id)
// Removed in Electron 13
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
// Replace with
session.defaultSession.getAllExtensions()
Removed: methods in systemPreferences
The following systemPreferences
methods have been deprecated:
systemPreferences.isDarkMode()
systemPreferences.isInvertedColorScheme()
systemPreferences.isHighContrastColorScheme()
Use the following nativeTheme
properties instead:
nativeTheme.shouldUseDarkColors
nativeTheme.shouldUseInvertedColorScheme
nativeTheme.shouldUseHighContrastColors
// Removed in Electron 13
systemPreferences.isDarkMode()
// Replace with
nativeTheme.shouldUseDarkColors
// Removed in Electron 13
systemPreferences.isInvertedColorScheme()
// Replace with
nativeTheme.shouldUseInvertedColorScheme
// Removed in Electron 13
systemPreferences.isHighContrastColorScheme()
// Replace with
nativeTheme.shouldUseHighContrastColors
Removed: Pepper Flash support
Chromium has removed support for Flash, and so we must follow suit. See Chromium's Flash Roadmap for more details.
Default Changed: contextIsolation
defaults to true
In Electron 12, contextIsolation
will be enabled by default. To restore
the previous behavior, contextIsolation: false
must be specified in WebPreferences.
We recommend having contextIsolation enabled for the security of your application.
For more details see: https://github.com/electron/electron/issues/23506
Removed: crashReporter.getCrashesDirectory()
The crashReporter.getCrashesDirectory
method has been removed. Usage
should be replaced by app.getPath('crashDumps')
.
// Removed in Electron 12
crashReporter.getCrashesDirectory()
// Replace with
app.getPath('crashDumps')
Removed: crashReporter
methods in the renderer process
The following crashReporter
methods are no longer available in the renderer
process:
crashReporter.start
crashReporter.getLastCrashReport
crashReporter.getUploadedReports
crashReporter.getUploadToServer
crashReporter.setUploadToServer
crashReporter.getCrashesDirectory
They should be called only from the main process.
See #23265 for more details.
Default Changed: crashReporter.start({ compress: true })
The default value of the compress
option to crashReporter.start
has changed
from false
to true
. This means that crash dumps will be uploaded to the
crash ingestion server with the Content-Encoding: gzip
header, and the body
will be compressed.
If your crash ingestion server does not support compressed payloads, you can
turn off compression by specifying { compress: false }
in the crash reporter
options.
Deprecated: remote
module
The remote
module is deprecated in Electron 12, and will be removed in
Electron 14. It is replaced by the
@electron/remote
module.
// Deprecated in Electron 12:
const { BrowserWindow } = require('electron').remote
// Replace with:
const { BrowserWindow } = require('@electron/remote')
// In the main process:
require('@electron/remote/main').initialize()
Deprecated: shell.moveItemToTrash()
The synchronous shell.moveItemToTrash()
has been replaced by the new,
asynchronous shell.trashItem()
.
// Deprecated in Electron 12
shell.moveItemToTrash(path)
// Replace with
shell.trashItem(path).then(/* ... */)
Removed: BrowserView.{destroy, fromId, fromWebContents, getAllViews}
and id
property of BrowserView
The experimental APIs BrowserView.{destroy, fromId, fromWebContents, getAllViews}
have now been removed. Additionally, the id
property of BrowserView
has also been removed.
For more detailed information, see #23578.
Deprecated: companyName
argument to crashReporter.start()
The companyName
argument to crashReporter.start()
, which was previously
required, is now optional, and further, is deprecated. To get the same
behavior in a non-deprecated way, you can pass a companyName
value in
globalExtra
.
// Deprecated in Electron 10
crashReporter.start({ companyName: 'Umbrella Corporation' })
// Replace with
crashReporter.start({ globalExtra: { _companyName: 'Umbrella Corporation' } })
Deprecated: crashReporter.getCrashesDirectory()
The crashReporter.getCrashesDirectory
method has been deprecated. Usage
should be replaced by app.getPath('crashDumps')
.
// Deprecated in Electron 10
crashReporter.getCrashesDirectory()
// Replace with
app.getPath('crashDumps')
Deprecated: crashReporter
methods in the renderer process
Calling the following crashReporter
methods from the renderer process is
deprecated:
crashReporter.start
crashReporter.getLastCrashReport
crashReporter.getUploadedReports
crashReporter.getUploadToServer
crashReporter.setUploadToServer
crashReporter.getCrashesDirectory
The only non-deprecated methods remaining in the crashReporter
module in the
renderer are addExtraParameter
, removeExtraParameter
and getParameters
.
All above methods remain non-deprecated when called from the main process.
See #23265 for more details.
Deprecated: crashReporter.start({ compress: false })
Setting { compress: false }
in crashReporter.start
is deprecated. Nearly
all crash ingestion servers support gzip compression. This option will be
removed in a future version of Electron.
Removed: Browser Window Affinity
The affinity
option when constructing a new BrowserWindow
will be removed
as part of our plan to more closely align with Chromium's process model for security,
performance and maintainability.
For more detailed information see #18397.
Default Changed: enableRemoteModule
defaults to false
In Electron 9, using the remote module without explicitly enabling it via the
enableRemoteModule
WebPreferences option began emitting a warning. In
Electron 10, the remote module is now disabled by default. To use the remote
module, enableRemoteModule: true
must be specified in WebPreferences:
const w = new BrowserWindow({
webPreferences: {
enableRemoteModule: true
}
})
protocol.uninterceptProtocol
The APIs are now synchronous and the optional callback is no longer needed.
// Deprecated
protocol.unregisterProtocol(scheme, () => { /* ... */ })
// Replace with
protocol.unregisterProtocol(scheme)
protocol.interceptStreamProtocol
The APIs are now synchronous and the optional callback is no longer needed.
// Deprecated
protocol.registerFileProtocol(scheme, handler, () => { /* ... */ })
// Replace with
protocol.registerFileProtocol(scheme, handler)
The registered or intercepted protocol does not have effect on current page until navigation happens.
protocol.isProtocolHandled
This API is deprecated and users should use protocol.isProtocolRegistered
and protocol.isProtocolIntercepted
instead.
// Deprecated
protocol.isProtocolHandled(scheme).then(() => { /* ... */ })
// Replace with
const isRegistered = protocol.isProtocolRegistered(scheme)
const isIntercepted = protocol.isProtocolIntercepted(scheme)
Default Changed: Loading non-context-aware native modules in the renderer process is disabled by default
As of Electron 9 we do not allow loading of non-context-aware native modules in the renderer process. This is to improve security, performance and maintainability of Electron as a project.
If this impacts you, you can temporarily set app.allowRendererProcessReuse
to false
to revert to the old behavior. This flag will only be an option until Electron 11 so
you should plan to update your native modules to be context aware.
For more detailed information see #18397.
Deprecated: BrowserWindow
extension APIs
The following extension APIs have been deprecated:
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
Use the session APIs instead:
ses.loadExtension(path)
ses.removeExtension(extension_id)
ses.getAllExtensions()
// Deprecated in Electron 9
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
// Replace with
session.defaultSession.loadExtension(path)
// Deprecated in Electron 9
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
// Replace with
session.defaultSession.removeExtension(extension_id)
// Deprecated in Electron 9
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
// Replace with
session.defaultSession.getAllExtensions()
Removed: <webview>.getWebContents()
This API, which was deprecated in Electron 8.0, is now removed.
// Removed in Electron 9.0
webview.getWebContents()
// Replace with
const { remote } = require('electron')
remote.webContents.fromId(webview.getWebContentsId())
Removed: webFrame.setLayoutZoomLevelLimits()
Chromium has removed support for changing the layout zoom level limits, and it is beyond Electron's capacity to maintain it. The function was deprecated in Electron 8.x, and has been removed in Electron 9.x. The layout zoom level limits are now fixed at a minimum of 0.25 and a maximum of 5.0, as defined here.
Behavior Changed: Sending non-JS objects over IPC now throws an exception
In Electron 8.0, IPC was changed to use the Structured Clone Algorithm,
bringing significant performance improvements. To help ease the transition, the
old IPC serialization algorithm was kept and used for some objects that aren't
serializable with Structured Clone. In particular, DOM objects (e.g. Element
,
Location
and DOMMatrix
), Node.js objects backed by C++ classes (e.g.
process.env
, some members of Stream
), and Electron objects backed by C++
classes (e.g. WebContents
, BrowserWindow
and WebFrame
) are not
serializable with Structured Clone. Whenever the old algorithm was invoked, a
deprecation warning was printed.
In Electron 9.0, the old serialization algorithm has been removed, and sending such non-serializable objects will now throw an "object could not be cloned" error.
API Changed: shell.openItem
is now shell.openPath
The shell.openItem
API has been replaced with an asynchronous shell.openPath
API.
You can see the original API proposal and reasoning here.
Behavior Changed: Values sent over IPC are now serialized with Structured Clone Algorithm
The algorithm used to serialize objects sent over IPC (through
ipcRenderer.send
, ipcRenderer.sendSync
, WebContents.send
and related
methods) has been switched from a custom algorithm to V8's built-in Structured
Clone Algorithm, the same algorithm used to serialize messages for
postMessage
. This brings about a 2x performance improvement for large
messages, but also brings some breaking changes in behavior.
- Sending Functions, Promises, WeakMaps, WeakSets, or objects containing any
such values, over IPC will now throw an exception, instead of silently
converting the functions to
undefined
.
// Previously:
ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
// => results in { value: 3 } arriving in the main process
// From Electron 8:
ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
// => throws Error("() => {} could not be cloned.")
NaN
,Infinity
and-Infinity
will now be correctly serialized, instead of being converted tonull
.- Objects containing cyclic references will now be correctly serialized,
instead of being converted to
null
. Set
,Map
,Error
andRegExp
values will be correctly serialized, instead of being converted to{}
.BigInt
values will be correctly serialized, instead of being converted tonull
.- Sparse arrays will be serialized as such, instead of being converted to dense
arrays with
null
s. Date
objects will be transferred asDate
objects, instead of being converted to their ISO string representation.- Typed Arrays (such as
Uint8Array
,Uint16Array
,Uint32Array
and so on) will be transferred as such, instead of being converted to Node.jsBuffer
. - Node.js
Buffer
objects will be transferred asUint8Array
s. You can convert aUint8Array
back to a Node.jsBuffer
by wrapping the underlyingArrayBuffer
:
Buffer.from(value.buffer, value.byteOffset, value.byteLength)
Sending any objects that aren't native JS types, such as DOM objects (e.g.
Element
, Location
, DOMMatrix
), Node.js objects (e.g. process.env
,
Stream
), or Electron objects (e.g. WebContents
, BrowserWindow
,
WebFrame
) is deprecated. In Electron 8, these objects will be serialized as
before with a DeprecationWarning message, but starting in Electron 9, sending
these kinds of objects will throw a 'could not be cloned' error.
Deprecated: <webview>.getWebContents()
This API is implemented using the remote
module, which has both performance
and security implications. Therefore its usage should be explicit.
// Deprecated
webview.getWebContents()
// Replace with
const { remote } = require('electron')
remote.webContents.fromId(webview.getWebContentsId())
However, it is recommended to avoid using the remote
module altogether.
// main
const { ipcMain, webContents } = require('electron')
const getGuestForWebContents = (webContentsId, contents) => {
const guest = webContents.fromId(webContentsId)
if (!guest) {
throw new Error(`Invalid webContentsId: ${webContentsId}`)
}
if (guest.hostWebContents !== contents) {
throw new Error('Access denied to webContents')
}
return guest
}
ipcMain.handle('openDevTools', (event, webContentsId) => {
const guest = getGuestForWebContents(webContentsId, event.sender)
guest.openDevTools()
})
// renderer
const { ipcRenderer } = require('electron')
ipcRenderer.invoke('openDevTools', webview.getWebContentsId())
Deprecated: webFrame.setLayoutZoomLevelLimits()
Chromium has removed support for changing the layout zoom level limits, and it is beyond Electron's capacity to maintain it. The function will emit a warning in Electron 8.x, and cease to exist in Electron 9.x. The layout zoom level limits are now fixed at a minimum of 0.25 and a maximum of 5.0, as defined here.
Deprecated events in systemPreferences
The following systemPreferences
events have been deprecated:
inverted-color-scheme-changed
high-contrast-color-scheme-changed
Use the new updated
event on the nativeTheme
module instead.
// Deprecated
systemPreferences.on('inverted-color-scheme-changed', () => { /* ... */ })
systemPreferences.on('high-contrast-color-scheme-changed', () => { /* ... */ })
// Replace with
nativeTheme.on('updated', () => { /* ... */ })
Deprecated: methods in systemPreferences
The following systemPreferences
methods have been deprecated:
systemPreferences.isDarkMode()
systemPreferences.isInvertedColorScheme()
systemPreferences.isHighContrastColorScheme()
Use the following nativeTheme
properties instead:
nativeTheme.shouldUseDarkColors
nativeTheme.shouldUseInvertedColorScheme
nativeTheme.shouldUseHighContrastColors
// Deprecated
systemPreferences.isDarkMode()
// Replace with
nativeTheme.shouldUseDarkColors
// Deprecated
systemPreferences.isInvertedColorScheme()
// Replace with
nativeTheme.shouldUseInvertedColorScheme
// Deprecated
systemPreferences.isHighContrastColorScheme()
// Replace with
nativeTheme.shouldUseHighContrastColors
Deprecated: Atom.io Node Headers URL
This is the URL specified as disturl
in a .npmrc
file or as the --dist-url
command line flag when building native Node modules. Both will be supported for
the foreseeable future but it is recommended that you switch.
Deprecated: https://atom.io/download/electron
Replace with: https://electronjs.org/headers
API Changed: session.clearAuthCache()
no longer accepts options
The session.clearAuthCache
API no longer accepts options for what to clear, and instead unconditionally clears the whole cache.
// Deprecated
session.clearAuthCache({ type: 'password' })
// Replace with
session.clearAuthCache()
API Changed: powerMonitor.querySystemIdleState
is now powerMonitor.getSystemIdleState
// Removed in Electron 7.0
powerMonitor.querySystemIdleState(threshold, callback)
// Replace with synchronous API
const idleState = powerMonitor.getSystemIdleState(threshold)
API Changed: powerMonitor.querySystemIdleTime
is now powerMonitor.getSystemIdleTime
// Removed in Electron 7.0
powerMonitor.querySystemIdleTime(callback)
// Replace with synchronous API
const idleTime = powerMonitor.getSystemIdleTime()
API Changed: webFrame.setIsolatedWorldInfo
replaces separate methods
// Removed in Electron 7.0
webFrame.setIsolatedWorldContentSecurityPolicy(worldId, csp)
webFrame.setIsolatedWorldHumanReadableName(worldId, name)
webFrame.setIsolatedWorldSecurityOrigin(worldId, securityOrigin)
// Replace with
webFrame.setIsolatedWorldInfo(
worldId,
{
securityOrigin: 'some_origin',
name: 'human_readable_name',
csp: 'content_security_policy'
})
Removed: marked
property on getBlinkMemoryInfo
This property was removed in Chromium 77, and as such is no longer available.
Behavior Changed: webkitdirectory
attribute for <input type="file"/>
now lists directory contents
The webkitdirectory
property on HTML file inputs allows them to select folders.
Previous versions of Electron had an incorrect implementation where the event.target.files
of the input returned a FileList
that returned one File
corresponding to the selected folder.
As of Electron 7, that FileList
is now list of all files contained within
the folder, similarly to Chrome, Firefox, and Edge
(link to MDN docs).
As an illustration, take a folder with this structure:
folder
├── file1
├── file2
└── file3
In Electron <=6, this would return a FileList
with a File
object for:
path/to/folder
In Electron 7, this now returns a FileList
with a File
object for:
/path/to/folder/file3
/path/to/folder/file2
/path/to/folder/file1
Note that webkitdirectory
no longer exposes the path to the selected folder.
If you require the path to the selected folder rather than the folder contents,
see the dialog.showOpenDialog
API (link).
API Changed: win.setMenu(null)
is now win.removeMenu()
// Deprecated
win.setMenu(null)
// Replace with
win.removeMenu()
API Changed: contentTracing.getTraceBufferUsage()
is now a promise
// Deprecated
contentTracing.getTraceBufferUsage((percentage, value) => {
// do something
})
// Replace with
contentTracing.getTraceBufferUsage().then(infoObject => {
// infoObject has percentage and value fields
})
API Changed: electron.screen
in the renderer process should be accessed via remote
// Deprecated
require('electron').screen
// Replace with
require('electron').remote.screen
API Changed: require()
ing node builtins in sandboxed renderers no longer implicitly loads the remote
version
// Deprecated
require('child_process')
// Replace with
require('electron').remote.require('child_process')
// Deprecated
require('fs')
// Replace with
require('electron').remote.require('fs')
// Deprecated
require('os')
// Replace with
require('electron').remote.require('os')
// Deprecated
require('path')
// Replace with
require('electron').remote.require('path')
Deprecated: powerMonitor.querySystemIdleState
replaced with powerMonitor.getSystemIdleState
// Deprecated
powerMonitor.querySystemIdleState(threshold, callback)
// Replace with synchronous API
const idleState = powerMonitor.getSystemIdleState(threshold)
Deprecated: powerMonitor.querySystemIdleTime
replaced with powerMonitor.getSystemIdleTime
// Deprecated
powerMonitor.querySystemIdleTime(callback)
// Replace with synchronous API
const idleTime = powerMonitor.getSystemIdleTime()
Deprecated: app.enableMixedSandbox()
is no longer needed
// Deprecated
app.enableMixedSandbox()
Mixed-sandbox mode is now enabled by default.
Deprecated: Tray.setHighlightMode
Under macOS Catalina our former Tray implementation breaks. Apple's native substitute doesn't support changing the highlighting behavior.
// Deprecated
tray.setHighlightMode(mode)
// API will be removed in v7.0 without replacement.
Default Changed: nodeIntegration
and webviewTag
default to false, contextIsolation
defaults to true
The following webPreferences
option default values are deprecated in favor of the new defaults listed below.
Property | Deprecated Default | New Default |
---|---|---|
contextIsolation | false | true |
nodeIntegration | true | false |
webviewTag | nodeIntegration if set else true | false |
E.g. Re-enabling the webviewTag
const w = new BrowserWindow({
webPreferences: {
webviewTag: true
}
})
Behavior Changed: nodeIntegration
in child windows opened via nativeWindowOpen
Child windows opened with the nativeWindowOpen
option will always have Node.js integration disabled, unless nodeIntegrationInSubFrames
is true
.
API Changed: Registering privileged schemes must now be done before app ready
Renderer process APIs webFrame.registerURLSchemeAsPrivileged
and webFrame.registerURLSchemeAsBypassingCSP
as well as browser process API protocol.registerStandardSchemes
have been removed.
A new API, protocol.registerSchemesAsPrivileged
has been added and should be used for registering custom schemes with the required privileges. Custom schemes are required to be registered before app ready.
Deprecated: webFrame.setIsolatedWorld*
replaced with webFrame.setIsolatedWorldInfo
// Deprecated
webFrame.setIsolatedWorldContentSecurityPolicy(worldId, csp)
webFrame.setIsolatedWorldHumanReadableName(worldId, name)
webFrame.setIsolatedWorldSecurityOrigin(worldId, securityOrigin)
// Replace with
webFrame.setIsolatedWorldInfo(
worldId,
{
securityOrigin: 'some_origin',
name: 'human_readable_name',
csp: 'content_security_policy'
})
API Changed: webFrame.setSpellCheckProvider
now takes an asynchronous callback
The spellCheck
callback is now asynchronous, and autoCorrectWord
parameter has been removed.
// Deprecated
webFrame.setSpellCheckProvider('en-US', true, {
spellCheck: (text) => {
return !spellchecker.isMisspelled(text)
}
})
// Replace with
webFrame.setSpellCheckProvider('en-US', {
spellCheck: (words, callback) => {
callback(words.filter(text => spellchecker.isMisspelled(text)))
}
})
Planned Breaking API Changes (4.0)
The following list includes the breaking API changes made in Electron 4.0.
app.makeSingleInstance
// Deprecated
app.makeSingleInstance((argv, cwd) => {
/* ... */
})
// Replace with
app.requestSingleInstanceLock()
app.on('second-instance', (event, argv, cwd) => {
/* ... */
})
app.releaseSingleInstance
// Deprecated
app.releaseSingleInstance()
// Replace with
app.releaseSingleInstanceLock()
app.getGPUInfo
app.getGPUInfo('complete')
// Now behaves the same with `basic` on macOS
app.getGPUInfo('basic')
win_delay_load_hook
When building native modules for windows, the win_delay_load_hook
variable in
the module's binding.gyp
must be true (which is the default). If this hook is
not present, then the native module will fail to load on Windows, with an error
message like Cannot find module
. See the native module
guide for more.
Breaking API Changes (3.0)
The following list includes the breaking API changes in Electron 3.0.
app
// Deprecated
app.getAppMemoryInfo()
// Replace with
app.getAppMetrics()
// Deprecated
const metrics = app.getAppMetrics()
const { memory } = metrics[0] // Deprecated property
BrowserWindow
// Deprecated
const optionsA = { webPreferences: { blinkFeatures: '' } }
const windowA = new BrowserWindow(optionsA)
// Replace with
const optionsB = { webPreferences: { enableBlinkFeatures: '' } }
const windowB = new BrowserWindow(optionsB)
// Deprecated
window.on('app-command', (e, cmd) => {
if (cmd === 'media-play_pause') {
// do something
}
})
// Replace with
window.on('app-command', (e, cmd) => {
if (cmd === 'media-play-pause') {
// do something
}
})
clipboard
// Deprecated
clipboard.readRtf()
// Replace with
clipboard.readRTF()
// Deprecated
clipboard.writeRtf()
// Replace with
clipboard.writeRTF()
// Deprecated
clipboard.readHtml()
// Replace with
clipboard.readHTML()
// Deprecated
clipboard.writeHtml()
// Replace with
clipboard.writeHTML()
crashReporter
// Deprecated
crashReporter.start({
companyName: 'Crashly',
submitURL: 'https://crash.server.com',
autoSubmit: true
})
// Replace with
crashReporter.start({
companyName: 'Crashly',
submitURL: 'https://crash.server.com',
uploadToServer: true
})
nativeImage
// Deprecated
nativeImage.createFromBuffer(buffer, 1.0)
// Replace with
nativeImage.createFromBuffer(buffer, {
scaleFactor: 1.0
})
process
// Deprecated
const info = process.getProcessMemoryInfo()
screen
// Deprecated
screen.getMenuBarHeight()
// Replace with
screen.getPrimaryDisplay().workArea
session
// Deprecated
ses.setCertificateVerifyProc((hostname, certificate, callback) => {
callback(true)
})
// Replace with
ses.setCertificateVerifyProc((request, callback) => {
callback(0)
})
Tray
// Deprecated
tray.setHighlightMode(true)
// Replace with
tray.setHighlightMode('on')
// Deprecated
tray.setHighlightMode(false)
// Replace with
tray.setHighlightMode('off')
webContents
// Deprecated
webContents.openDevTools({ detach: true })
// Replace with
webContents.openDevTools({ mode: 'detach' })
// Removed
webContents.setSize(options)
// There is no replacement for this API
webFrame
// Deprecated
webFrame.registerURLSchemeAsSecure('app')
// Replace with
protocol.registerStandardSchemes(['app'], { secure: true })
// Deprecated
webFrame.registerURLSchemeAsPrivileged('app', { secure: true })
// Replace with
protocol.registerStandardSchemes(['app'], { secure: true })
<webview>
// Removed
webview.setAttribute('disableguestresize', '')
// There is no replacement for this API
// Removed
webview.setAttribute('guestinstance', instanceId)
// There is no replacement for this API
// Keyboard listeners no longer work on webview tag
webview.onkeydown = () => { /* handler */ }
webview.onkeyup = () => { /* handler */ }
Node Headers URL
This is the URL specified as disturl
in a .npmrc
file or as the --dist-url
command line flag when building native Node modules.
Deprecated: https://atom.io/download/atom-shell
Replace with: https://atom.io/download/electron
Breaking API Changes (2.0)
The following list includes the breaking API changes made in Electron 2.0.
BrowserWindow
// Deprecated
const optionsA = { titleBarStyle: 'hidden-inset' }
const windowA = new BrowserWindow(optionsA)
// Replace with
const optionsB = { titleBarStyle: 'hiddenInset' }
const windowB = new BrowserWindow(optionsB)
menu
// Removed
menu.popup(browserWindow, 100, 200, 2)
// Replaced with
menu.popup(browserWindow, { x: 100, y: 200, positioningItem: 2 })
nativeImage
// Removed
nativeImage.toPng()
// Replaced with
nativeImage.toPNG()
// Removed
nativeImage.toJpeg()
// Replaced with
nativeImage.toJPEG()
process
process.versions.electron
andprocess.version.chrome
will be made read-only properties for consistency with the otherprocess.versions
properties set by Node.
webContents
// Removed
webContents.setZoomLevelLimits(1, 2)
// Replaced with
webContents.setVisualZoomLevelLimits(1, 2)
webFrame
// Removed
webFrame.setZoomLevelLimits(1, 2)
// Replaced with
webFrame.setVisualZoomLevelLimits(1, 2)
<webview>
// Removed
webview.setZoomLevelLimits(1, 2)
// Replaced with
webview.setVisualZoomLevelLimits(1, 2)
Duplicate ARM Assets
Each Electron release includes two identical ARM builds with slightly different
filenames, like electron-v1.7.3-linux-arm.zip
and
electron-v1.7.3-linux-armv7l.zip
. The asset with the v7l
prefix was added
to clarify to users which ARM version it supports, and to disambiguate it from
future armv6l and arm64 assets that may be produced.
The file without the prefix is still being published to avoid breaking any setups that may be consuming it. Starting at 2.0, the unprefixed file will no longer be published.
Class: BrowserView
Create and control views.
Process: Main
A BrowserView
can be used to embed additional web content into a
BrowserWindow
. It is like a child window, except that it is positioned
relative to its owning window. It is meant to be an alternative to the
webview
tag.
Example
// In the main process.
const { BrowserView, BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
const view = new BrowserView()
win.setBrowserView(view)
view.setBounds({ x: 0, y: 0, width: 300, height: 300 })
view.webContents.loadURL('https://electronjs.org')
new BrowserView([options])
Experimental
options
Object (optional)webPreferences
Object (optional) - See BrowserWindow.
Instance Properties
Objects created with new BrowserView
have the following properties:
view.webContents
Experimental
A WebContents
object owned by this view.
Instance Methods
Objects created with new BrowserView
have the following instance methods:
view.setAutoResize(options)
Experimental
options
Objectwidth
Boolean (optional) - Iftrue
, the view's width will grow and shrink together with the window.false
by default.height
Boolean (optional) - Iftrue
, the view's height will grow and shrink together with the window.false
by default.horizontal
Boolean (optional) - Iftrue
, the view's x position and width will grow and shrink proportionally with the window.false
by default.vertical
Boolean (optional) - Iftrue
, the view's y position and height will grow and shrink proportionally with the window.false
by default.
view.setBounds(bounds)
Experimental
bounds
Rectangle
Resizes and moves the view to the supplied bounds relative to the window.
view.setBackgroundColor(color)
Experimental
color
String - Color in#aarrggbb
or#argb
form. The alpha channel is optional.
BrowserWindow
Create and control browser windows.
Process: Main
// In the main process.
const { BrowserWindow } = require('electron')
// Or use `remote` from the renderer process.
// const { BrowserWindow } = require('electron').remote
const win = new BrowserWindow({ width: 800, height: 600 })
// Load a remote URL
win.loadURL('https://github.com')
// Or load a local HTML file
win.loadURL(`file://${__dirname}/app/index.html`)
Frameless window
To create a window without chrome, or a transparent window in arbitrary shape, you can use the Frameless Window API.
Showing window gracefully
When loading a page in the window directly, users may see the page load incrementally, which is not a good experience for a native app. To make the window display without visual flash, there are two solutions for different situations.
Using ready-to-show
event
While loading the page, the ready-to-show
event will be emitted when the renderer
process has rendered the page for the first time if the window has not been shown yet. Showing
the window after this event will have no visual flash:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ show: false })
win.once('ready-to-show', () => {
win.show()
})
This event is usually emitted after the did-finish-load
event, but for
pages with many remote resources, it may be emitted before the did-finish-load
event.
Please note that using this event implies that the renderer will be considered "visible" and
paint even though show
is false. This event will never fire if you use paintWhenInitiallyHidden: false
Setting backgroundColor
For a complex app, the ready-to-show
event could be emitted too late, making
the app feel slow. In this case, it is recommended to show the window
immediately, and use a backgroundColor
close to your app's background:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ backgroundColor: '#2e2c29' })
win.loadURL('https://github.com')
Note that even for apps that use ready-to-show
event, it is still recommended
to set backgroundColor
to make app feel more native.
Parent and child windows
By using parent
option, you can create child windows:
const { BrowserWindow } = require('electron')
const top = new BrowserWindow()
const child = new BrowserWindow({ parent: top })
child.show()
top.show()
The child
window will always show on top of the top
window.
Modal windows
A modal window is a child window that disables parent window, to create a modal
window, you have to set both parent
and modal
options:
const { BrowserWindow } = require('electron')
const child = new BrowserWindow({ parent: top, modal: true, show: false })
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
child.show()
})
Page visibility
The Page Visibility API works as follows:
- On all platforms, the visibility state tracks whether the window is hidden/minimized or not.
- Additionally, on macOS, the visibility state also tracks the window
occlusion state. If the window is occluded (i.e. fully covered) by another
window, the visibility state will be
hidden
. On other platforms, the visibility state will behidden
only when the window is minimized or explicitly hidden withwin.hide()
. - If a
BrowserWindow
is created withshow: false
, the initial visibility state will bevisible
despite the window actually being hidden. - If
backgroundThrottling
is disabled, the visibility state will remainvisible
even if the window is minimized, occluded, or hidden.
It is recommended that you pause expensive operations when the visibility
state is hidden
in order to minimize power consumption.
Platform notices
- On macOS modal windows will be displayed as sheets attached to the parent window.
- On macOS the child windows will keep the relative position to parent window when parent window moves, while on Windows and Linux child windows will not move.
- On Linux the type of modal windows will be changed to
dialog
. - On Linux many desktop environments do not support hiding a modal window.
Class: BrowserWindow
Create and control browser windows.
Process: Main
BrowserWindow
is an EventEmitter.
It creates a new BrowserWindow
with native properties as set by the options
.
new BrowserWindow([options])
options
Object (optional)width
Integer (optional) - Window's width in pixels. Default is800
.height
Integer (optional) - Window's height in pixels. Default is600
.x
Integer (optional) - (required if y is used) Window's left offset from screen. Default is to center the window.y
Integer (optional) - (required if x is used) Window's top offset from screen. Default is to center the window.useContentSize
Boolean (optional) - Thewidth
andheight
would be used as web page's size, which means the actual window's size will include window frame's size and be slightly larger. Default isfalse
.center
Boolean (optional) - Show window in the center of the screen.minWidth
Integer (optional) - Window's minimum width. Default is0
.minHeight
Integer (optional) - Window's minimum height. Default is0
.maxWidth
Integer (optional) - Window's maximum width. Default is no limit.maxHeight
Integer (optional) - Window's maximum height. Default is no limit.resizable
Boolean (optional) - Whether window is resizable. Default istrue
.movable
Boolean (optional) - Whether window is movable. This is not implemented on Linux. Default istrue
.minimizable
Boolean (optional) - Whether window is minimizable. This is not implemented on Linux. Default istrue
.maximizable
Boolean (optional) - Whether window is maximizable. This is not implemented on Linux. Default istrue
.closable
Boolean (optional) - Whether window is closable. This is not implemented on Linux. Default istrue
.focusable
Boolean (optional) - Whether the window can be focused. Default istrue
. On Windows settingfocusable: false
also implies settingskipTaskbar: true
. On Linux settingfocusable: false
makes the window stop interacting with wm, so the window will always stay on top in all workspaces.alwaysOnTop
Boolean (optional) - Whether the window should always stay on top of other windows. Default isfalse
.fullscreen
Boolean (optional) - Whether the window should show in fullscreen. When explicitly set tofalse
the fullscreen button will be hidden or disabled on macOS. Default isfalse
.fullscreenable
Boolean (optional) - Whether the window can be put into fullscreen mode. On macOS, also whether the maximize/zoom button should toggle full screen mode or maximize window. Default istrue
.simpleFullscreen
Boolean (optional) - Use pre-Lion fullscreen on macOS. Default isfalse
.skipTaskbar
Boolean (optional) - Whether to show the window in taskbar. Default isfalse
.kiosk
Boolean (optional) - Whether the window is in kiosk mode. Default isfalse
.title
String (optional) - Default window title. Default is"Electron"
. If the HTML tag<title>
is defined in the HTML file loaded byloadURL()
, this property will be ignored.icon
(NativeImage | String) (optional) - The window icon. On Windows it is recommended to useICO
icons to get best visual effects, you can also leave it undefined so the executable's icon will be used.show
Boolean (optional) - Whether window should be shown when created. Default istrue
.paintWhenInitiallyHidden
Boolean (optional) - Whether the renderer should be active whenshow
isfalse
and it has just been created. In order fordocument.visibilityState
to work correctly on first load withshow: false
you should set this tofalse
. Setting this tofalse
will cause theready-to-show
event to not fire. Default istrue
.frame
Boolean (optional) - Specifyfalse
to create a Frameless Window. Default istrue
.parent
BrowserWindow (optional) - Specify parent window. Default isnull
.modal
Boolean (optional) - Whether this is a modal window. This only works when the window is a child window. Default isfalse
.acceptFirstMouse
Boolean (optional) - Whether the web view accepts a single mouse-down event that simultaneously activates the window. Default isfalse
.disableAutoHideCursor
Boolean (optional) - Whether to hide cursor when typing. Default isfalse
.autoHideMenuBar
Boolean (optional) - Auto hide the menu bar unless theAlt
key is pressed. Default isfalse
.enableLargerThanScreen
Boolean (optional) - Enable the window to be resized larger than screen. Only relevant for macOS, as other OSes allow larger-than-screen windows by default. Default isfalse
.backgroundColor
String (optional) - Window's background color as a hexadecimal value, like#66CD00
or#FFF
or#80FFFFFF
(alpha in #AARRGGBB format is supported iftransparent
is set totrue
). Default is#FFF
(white).hasShadow
Boolean (optional) - Whether window should have a shadow. Default istrue
.opacity
Number (optional) - Set the initial opacity of the window, between 0.0 (fully transparent) and 1.0 (fully opaque). This is only implemented on Windows and macOS.darkTheme
Boolean (optional) - Forces using dark theme for the window, only works on some GTK+3 desktop environments. Default isfalse
.transparent
Boolean (optional) - Makes the window transparent. Default isfalse
. On Windows, does not work unless the window is frameless.type
String (optional) - The type of window, default is normal window. See more about this below.visualEffectState
String (optional) - Specify how the material appearance should reflect window activity state on macOS. Must be used with thevibrancy
property. Possible values are:followWindow
- The backdrop should automatically appear active when the window is active, and inactive when it is not. This is the default.active
- The backdrop should always appear active.inactive
- The backdrop should always appear inactive.
titleBarStyle
String (optional) - The style of window title bar. Default isdefault
. Possible values are:default
- Results in the standard gray opaque Mac title bar.hidden
- Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls ("traffic lights") in the top left.hiddenInset
- Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge.customButtonsOnHover
Boolean (optional) - Draw custom close, and minimize buttons on macOS frameless windows. These buttons will not display unless hovered over in the top left of the window. These custom buttons prevent issues with mouse events that occur with the standard window toolbar buttons. Note: This option is currently experimental.
trafficLightPosition
Point (optional) - Set a custom position for the traffic light buttons. Can only be used withtitleBarStyle
set tohidden
fullscreenWindowTitle
Boolean (optional) - Shows the title in the title bar in full screen mode on macOS for alltitleBarStyle
options. Default isfalse
.thickFrame
Boolean (optional) - UseWS_THICKFRAME
style for frameless windows on Windows, which adds standard window frame. Setting it tofalse
will remove window shadow and window animations. Default istrue
.vibrancy
String (optional) - Add a type of vibrancy effect to the window, only on macOS. Can beappearance-based
,light
,dark
,titlebar
,selection
,menu
,popover
,sidebar
,medium-light
,ultra-dark
,header
,sheet
,window
,hud
,fullscreen-ui
,tooltip
,content
,under-window
, orunder-page
. Please note that usingframe: false
in combination with a vibrancy value requires that you use a non-defaulttitleBarStyle
as well. Also note thatappearance-based
,light
,dark
,medium-light
, andultra-dark
have been deprecated and will be removed in an upcoming version of macOS.zoomToPageWidth
Boolean (optional) - Controls the behavior on macOS when option-clicking the green stoplight button on the toolbar or by clicking the Window > Zoom menu item. Iftrue
, the window will grow to the preferred width of the web page when zoomed,false
will cause it to zoom to the width of the screen. This will also affect the behavior when callingmaximize()
directly. Default isfalse
.tabbingIdentifier
String (optional) - Tab group name, allows opening the window as a native tab on macOS 10.12+. Windows with the same tabbing identifier will be grouped together. This also adds a native new tab button to your window's tab bar and allows yourapp
and window to receive thenew-window-for-tab
event.webPreferences
Object (optional) - Settings of web page's features.devTools
Boolean (optional) - Whether to enable DevTools. If it is set tofalse
, can not useBrowserWindow.webContents.openDevTools()
to open DevTools. Default istrue
.nodeIntegration
Boolean (optional) - Whether node integration is enabled. Default isfalse
.nodeIntegrationInWorker
Boolean (optional) - Whether node integration is enabled in web workers. Default isfalse
. More about this can be found in Multithreading.nodeIntegrationInSubFrames
Boolean (optional) - Experimental option for enabling Node.js support in sub-frames such as iframes and child windows. All your preloads will load for every iframe, you can useprocess.isMainFrame
to determine if you are in the main frame or not.preload
String (optional) - Specifies a script that will be loaded before other scripts run in the page. This script will always have access to node APIs no matter whether node integration is turned on or off. The value should be the absolute file path to the script. When node integration is turned off, the preload script can reintroduce Node global symbols back to the global scope. See example here.sandbox
Boolean (optional) - If set, this will sandbox the renderer associated with the window, making it compatible with the Chromium OS-level sandbox and disabling the Node.js engine. This is not the same as thenodeIntegration
option and the APIs available to the preload script are more limited. Read more about the option here.enableRemoteModule
Boolean (optional) - Whether to enable theremote
module. Default isfalse
.session
Session (optional) - Sets the session used by the page. Instead of passing the Session object directly, you can also choose to use thepartition
option instead, which accepts a partition string. When bothsession
andpartition
are provided,session
will be preferred. Default is the default session.partition
String (optional) - Sets the session used by the page according to the session's partition string. Ifpartition
starts withpersist:
, the page will use a persistent session available to all pages in the app with the samepartition
. If there is nopersist:
prefix, the page will use an in-memory session. By assigning the samepartition
, multiple pages can share the same session. Default is the default session.affinity
String (optional) - When specified, web pages with the sameaffinity
will run in the same renderer process. Note that due to reusing the renderer process, certainwebPreferences
options will also be shared between the web pages even when you specified different values for them, including but not limited topreload
,sandbox
andnodeIntegration
. So it is suggested to use exact samewebPreferences
for web pages with the sameaffinity
. DeprecatedzoomFactor
Number (optional) - The default zoom factor of the page,3.0
represents300%
. Default is1.0
.javascript
Boolean (optional) - Enables JavaScript support. Default istrue
.webSecurity
Boolean (optional) - Whenfalse
, it will disable the same-origin policy (usually using testing websites by people), and setallowRunningInsecureContent
totrue
if this options has not been set by user. Default istrue
.allowRunningInsecureContent
Boolean (optional) - Allow an https page to run JavaScript, CSS or plugins from http URLs. Default isfalse
.images
Boolean (optional) - Enables image support. Default istrue
.textAreasAreResizable
Boolean (optional) - Make TextArea elements resizable. Default istrue
.webgl
Boolean (optional) - Enables WebGL support. Default istrue
.plugins
Boolean (optional) - Whether plugins should be enabled. Default isfalse
.experimentalFeatures
Boolean (optional) - Enables Chromium's experimental features. Default isfalse
.scrollBounce
Boolean (optional) - Enables scroll bounce (rubber banding) effect on macOS. Default isfalse
.enableBlinkFeatures
String (optional) - A list of feature strings separated by,
, likeCSSVariables,KeyboardEventKey
to enable. The full list of supported feature strings can be found in the RuntimeEnabledFeatures.json5 file.disableBlinkFeatures
String (optional) - A list of feature strings separated by,
, likeCSSVariables,KeyboardEventKey
to disable. The full list of supported feature strings can be found in the RuntimeEnabledFeatures.json5 file.defaultFontFamily
Object (optional) - Sets the default font for the font-family.standard
String (optional) - Defaults toTimes New Roman
.serif
String (optional) - Defaults toTimes New Roman
.sansSerif
String (optional) - Defaults toArial
.monospace
String (optional) - Defaults toCourier New
.cursive
String (optional) - Defaults toScript
.fantasy
String (optional) - Defaults toImpact
.
defaultFontSize
Integer (optional) - Defaults to16
.defaultMonospaceFontSize
Integer (optional) - Defaults to13
.minimumFontSize
Integer (optional) - Defaults to0
.defaultEncoding
String (optional) - Defaults toISO-8859-1
.backgroundThrottling
Boolean (optional) - Whether to throttle animations and timers when the page becomes background. This also affects the Page Visibility API. Defaults totrue
.offscreen
Boolean (optional) - Whether to enable offscreen rendering for the browser window. Defaults tofalse
. See the offscreen rendering tutorial for more details.contextIsolation
Boolean (optional) - Whether to run Electron APIs and the specifiedpreload
script in a separate JavaScript context. Defaults tofalse
. The context that thepreload
script runs in will still have full access to thedocument
andwindow
globals but it will use its own set of JavaScript builtins (Array
,Object
,JSON
, etc.) and will be isolated from any changes made to the global environment by the loaded page. The Electron API will only be available in thepreload
script and not the loaded page. This option should be used when loading potentially untrusted remote content to ensure the loaded content cannot tamper with thepreload
script and any Electron APIs being used. This option uses the same technique used by Chrome Content Scripts. You can access this context in the dev tools by selecting the 'Electron Isolated Context' entry in the combo box at the top of the Console tab.worldSafeExecuteJavaScript
Boolean (optional) - If true, values returned fromwebFrame.executeJavaScript
will be sanitized to ensure JS values can't unsafely cross between worlds when usingcontextIsolation
. The default isfalse
. In Electron 12, the default will be changed totrue
. DeprecatednativeWindowOpen
Boolean (optional) - Whether to use nativewindow.open()
. Defaults tofalse
. Child windows will always have node integration disabled unlessnodeIntegrationInSubFrames
is true. Note: This option is currently experimental.webviewTag
Boolean (optional) - Whether to enable the<webview>
tag. Defaults tofalse
. Note: Thepreload
script configured for the<webview>
will have node integration enabled when it is executed so you should ensure remote/untrusted content is not able to create a<webview>
tag with a possibly maliciouspreload
script. You can use thewill-attach-webview
event on webContents to strip away thepreload
script and to validate or alter the<webview>
's initial settings.additionalArguments
String[] (optional) - A list of strings that will be appended toprocess.argv
in the renderer process of this app. Useful for passing small bits of data down to renderer process preload scripts.safeDialogs
Boolean (optional) - Whether to enable browser style consecutive dialog protection. Default isfalse
.safeDialogsMessage
String (optional) - The message to display when consecutive dialog protection is triggered. If not defined the default message would be used, note that currently the default message is in English and not localized.disableDialogs
Boolean (optional) - Whether to disable dialogs completely. OverridessafeDialogs
. Default isfalse
.navigateOnDragDrop
Boolean (optional) - Whether dragging and dropping a file or link onto the page causes a navigation. Default isfalse
.autoplayPolicy
String (optional) - Autoplay policy to apply to content in the window, can beno-user-gesture-required
,user-gesture-required
,document-user-activation-required
. Defaults tono-user-gesture-required
.disableHtmlFullscreenWindowResize
Boolean (optional) - Whether to prevent the window from resizing when entering HTML Fullscreen. Default isfalse
.accessibleTitle
String (optional) - An alternative title string provided only to accessibility tools such as screen readers. This string is not directly visible to users.spellcheck
Boolean (optional) - Whether to enable the builtin spellchecker. Default istrue
.enableWebSQL
Boolean (optional) - Whether to enable the WebSQL api. Default istrue
.v8CacheOptions
String (optional) - Enforces the v8 code caching policy used by blink. Accepted values arenone
- Disables code cachingcode
- Heuristic based code cachingbypassHeatCheck
- Bypass code caching heuristics but with lazy compilationbypassHeatCheckAndEagerCompile
- Same as above except compilation is eager. Default policy iscode
.
When setting minimum or maximum window size with minWidth
/maxWidth
/
minHeight
/maxHeight
, it only constrains the users. It won't prevent you from
passing a size that does not follow size constraints to setBounds
/setSize
or
to the constructor of BrowserWindow
.
The possible values and behaviors of the type
option are platform dependent.
Possible values are:
- On Linux, possible types are
desktop
,dock
,toolbar
,splash
,notification
. - On macOS, possible types are
desktop
,textured
.- The
textured
type adds metal gradient appearance (NSTexturedBackgroundWindowMask
). - The
desktop
type places the window at the desktop background window level (kCGDesktopWindowLevel - 1
). Note that desktop window will not receive focus, keyboard or mouse events, but you can useglobalShortcut
to receive input sparingly.
- The
- On Windows, possible type is
toolbar
.
Instance Events
Objects created with new BrowserWindow
emit the following events:
Note: Some events are only available on specific operating systems and are labeled as such.
Event: 'page-title-updated'
Returns:
event
Eventtitle
StringexplicitSet
Boolean
Emitted when the document changed its title, calling event.preventDefault()
will prevent the native window's title from changing.
explicitSet
is false when title is synthesized from file URL.
Event: 'close'
Returns:
event
Event
Emitted when the window is going to be closed. It's emitted before the
beforeunload
and unload
event of the DOM. Calling event.preventDefault()
will cancel the close.
Usually you would want to use the beforeunload
handler to decide whether the
window should be closed, which will also be called when the window is
reloaded. In Electron, returning any value other than undefined
would cancel the
close. For example:
window.onbeforeunload = (e) => {
console.log('I do not want to be closed')
// Unlike usual browsers that a message box will be prompted to users, returning
// a non-void value will silently cancel the close.
// It is recommended to use the dialog API to let the user confirm closing the
// application.
e.returnValue = false // equivalent to `return false` but not recommended
}
Note: There is a subtle difference between the behaviors of window.onbeforeunload = handler
and window.addEventListener('beforeunload', handler)
. It is recommended to always set the event.returnValue
explicitly, instead of only returning a value, as the former works more consistently within Electron.
Event: 'closed'
Emitted when the window is closed. After you have received this event you should remove the reference to the window and avoid using it any more.
Event: 'session-end' Windows
Emitted when window session is going to end due to force shutdown or machine restart or session log off.
Event: 'unresponsive'
Emitted when the web page becomes unresponsive.
Event: 'responsive'
Emitted when the unresponsive web page becomes responsive again.
Event: 'blur'
Emitted when the window loses focus.
Event: 'focus'
Emitted when the window gains focus.
Event: 'show'
Emitted when the window is shown.
Event: 'hide'
Emitted when the window is hidden.
Event: 'ready-to-show'
Emitted when the web page has been rendered (while not being shown) and window can be displayed without a visual flash.
Please note that using this event implies that the renderer will be considered "visible" and
paint even though show
is false. This event will never fire if you use paintWhenInitiallyHidden: false
Event: 'maximize'
Emitted when window is maximized.
Event: 'unmaximize'
Emitted when the window exits from a maximized state.
Event: 'minimize'
Emitted when the window is minimized.
Event: 'restore'
Emitted when the window is restored from a minimized state.
Event: 'will-resize' macOS Windows
Returns:
event
EventnewBounds
Rectangle - Size the window is being resized to.
Emitted before the window is resized. Calling event.preventDefault()
will prevent the window from being resized.
Note that this is only emitted when the window is being resized manually. Resizing the window with setBounds
/setSize
will not emit this event.
Event: 'resize'
Emitted after the window has been resized.
Event: 'resized' macOS Windows
Emitted once when the window has finished being resized.
This is usually emitted when the window has been resized manually. On macOS, resizing the window with setBounds
/setSize
and setting the animate
parameter to true
will also emit this event once resizing has finished.
Event: 'will-move' macOS Windows
Returns:
event
EventnewBounds
Rectangle - Location the window is being moved to.
Emitted before the window is moved. On Windows, calling event.preventDefault()
will prevent the window from being moved.
Note that this is only emitted when the window is being resized manually. Resizing the window with setBounds
/setSize
will not emit this event.
Event: 'move'
Emitted when the window is being moved to a new position.
Event: 'moved' macOS Windows
Emitted once when the window is moved to a new position.
Note: On macOS this event is an alias of move
.
Event: 'enter-full-screen'
Emitted when the window enters a full-screen state.
Event: 'leave-full-screen'
Emitted when the window leaves a full-screen state.
Event: 'enter-html-full-screen'
Emitted when the window enters a full-screen state triggered by HTML API.
Event: 'leave-html-full-screen'
Emitted when the window leaves a full-screen state triggered by HTML API.
Event: 'always-on-top-changed'
Returns:
event
EventisAlwaysOnTop
Boolean
Emitted when the window is set or unset to show always on top of other windows.
Event: 'app-command' Windows Linux
Returns:
event
Eventcommand
String
Emitted when an App Command is invoked. These are typically related to keyboard media keys or browser commands, as well as the "Back" button built into some mice on Windows.
Commands are lowercased, underscores are replaced with hyphens, and the
APPCOMMAND_
prefix is stripped off.
e.g. APPCOMMAND_BROWSER_BACKWARD
is emitted as browser-backward
.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.on('app-command', (e, cmd) => {
// Navigate the window back when the user hits their mouse back button
if (cmd === 'browser-backward' && win.webContents.canGoBack()) {
win.webContents.goBack()
}
})
The following app commands are explicitly supported on Linux:
browser-backward
browser-forward
Event: 'scroll-touch-begin' macOS
Emitted when scroll wheel event phase has begun.
Event: 'scroll-touch-end' macOS
Emitted when scroll wheel event phase has ended.
Event: 'scroll-touch-edge' macOS
Emitted when scroll wheel event phase filed upon reaching the edge of element.
Event: 'swipe' macOS
Returns:
event
Eventdirection
String
Emitted on 3-finger swipe. Possible directions are up
, right
, down
, left
.
The method underlying this event is built to handle older macOS-style trackpad swiping,
where the content on the screen doesn't move with the swipe. Most macOS trackpads are not
configured to allow this kind of swiping anymore, so in order for it to emit properly the
'Swipe between pages' preference in System Preferences > Trackpad > More Gestures
must be
set to 'Swipe with two or three fingers'.
Event: 'rotate-gesture' macOS
Returns:
event
Eventrotation
Float
Emitted on trackpad rotation gesture. Continually emitted until rotation gesture is
ended. The rotation
value on each emission is the angle in degrees rotated since
the last emission. The last emitted event upon a rotation gesture will always be of
value 0
. Counter-clockwise rotation values are positive, while clockwise ones are
negative.
Event: 'sheet-begin' macOS
Emitted when the window opens a sheet.
Event: 'sheet-end' macOS
Emitted when the window has closed a sheet.
Event: 'new-window-for-tab' macOS
Emitted when the native new tab button is clicked.
Event: 'system-context-menu' Windows
Returns:
event
Eventpoint
Point - The screen coordinates the context menu was triggered at
Emitted when the system context menu is triggered on the window, this is
normally only triggered when the user right clicks on the non-client area
of your window. This is the window titlebar or any area you have declared
as -webkit-app-region: drag
in a frameless window.
Calling event.preventDefault()
will prevent the menu from being displayed.
Static Methods
The BrowserWindow
class has the following static methods:
BrowserWindow.getAllWindows()
Returns BrowserWindow[]
- An array of all opened browser windows.
BrowserWindow.getFocusedWindow()
Returns BrowserWindow | null
- The window that is focused in this application, otherwise returns null
.
BrowserWindow.fromWebContents(webContents)
webContents
WebContents
Returns BrowserWindow | null
- The window that owns the given webContents
or null
if the contents are not owned by a window.
BrowserWindow.fromBrowserView(browserView)
browserView
BrowserView
Returns BrowserWindow | null
- The window that owns the given browserView
. If the given view is not attached to any window, returns null
.
BrowserWindow.addExtension(path)
Deprecated
path
String
Adds Chrome extension located at path
, and returns extension's name.
The method will also not return if the extension's manifest is missing or incomplete.
Note: This API cannot be called before the ready
event of the app
module
is emitted.
Note: This method is deprecated. Instead, use
ses.loadExtension(path)
.
BrowserWindow.removeExtension(name)
Deprecated
name
String
Remove a Chrome extension by name.
Note: This API cannot be called before the ready
event of the app
module
is emitted.
Note: This method is deprecated. Instead, use
ses.removeExtension(extension_id)
.
BrowserWindow.getExtensions()
Deprecated
Returns Record<String, ExtensionInfo>
- The keys are the extension names and each value is
an Object containing name
and version
properties.
Note: This API cannot be called before the ready
event of the app
module
is emitted.
Note: This method is deprecated. Instead, use
ses.getAllExtensions()
.
BrowserWindow.addDevToolsExtension(path)
Deprecated
path
String
Adds DevTools extension located at path
, and returns extension's name.
The extension will be remembered so you only need to call this API once, this API is not for programming use. If you try to add an extension that has already been loaded, this method will not return and instead log a warning to the console.
The method will also not return if the extension's manifest is missing or incomplete.
Note: This API cannot be called before the ready
event of the app
module
is emitted.
Note: This method is deprecated. Instead, use
ses.loadExtension(path)
.
BrowserWindow.removeDevToolsExtension(name)
Deprecated
name
String
Remove a DevTools extension by name.
Note: This API cannot be called before the ready
event of the app
module
is emitted.
Note: This method is deprecated. Instead, use
ses.removeExtension(extension_id)
.
BrowserWindow.getDevToolsExtensions()
Deprecated
Returns Record<string, ExtensionInfo>
- The keys are the extension names and each value is
an Object containing name
and version
properties.
To check if a DevTools extension is installed you can run the following:
const { BrowserWindow } = require('electron')
const installed = 'devtron' in BrowserWindow.getDevToolsExtensions()
console.log(installed)
Note: This API cannot be called before the ready
event of the app
module
is emitted.
Note: This method is deprecated. Instead, use
ses.getAllExtensions()
.
Instance Properties
Objects created with new BrowserWindow
have the following properties:
const { BrowserWindow } = require('electron')
// In this example `win` is our instance
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')
win.webContents
Readonly
A WebContents
object this window owns. All web page related events and
operations will be done via it.
See the webContents
documentation for its methods and
events.
win.id
Readonly
A Integer
property representing the unique ID of the window. Each ID is unique among all BrowserWindow
instances of the entire Electron application.
win.autoHideMenuBar
A Boolean
property that determines whether the window menu bar should hide itself automatically. Once set, the menu bar will only show when users press the single Alt
key.
If the menu bar is already visible, setting this property to true
won't
hide it immediately.
win.simpleFullScreen
A Boolean
property that determines whether the window is in simple (pre-Lion) fullscreen mode.
win.fullScreen
A Boolean
property that determines whether the window is in fullscreen mode.
win.visibleOnAllWorkspaces
A Boolean
property that determines whether the window is visible on all workspaces.
Note: Always returns false on Windows.
win.shadow
A Boolean
property that determines whether the window has a shadow.
win.menuBarVisible
Windows Linux
A Boolean
property that determines whether the menu bar should be visible.
Note: If the menu bar is auto-hide, users can still bring up the menu bar by pressing the single Alt
key.
win.kiosk
A Boolean
property that determines whether the window is in kiosk mode.
win.documentEdited
macOS
A Boolean
property that specifies whether the window’s document has been edited.
The icon in title bar will become gray when set to true
.
win.representedFilename
macOS
A String
property that determines the pathname of the file the window represents,
and the icon of the file will show in window's title bar.
win.title
A String
property that determines the title of the native window.
Note: The title of the web page can be different from the title of the native window.
win.minimizable
A Boolean
property that determines whether the window can be manually minimized by user.
On Linux the setter is a no-op, although the getter returns true
.
win.maximizable
A Boolean
property that determines whether the window can be manually maximized by user.
On Linux the setter is a no-op, although the getter returns true
.
win.fullScreenable
A Boolean
property that determines whether the maximize/zoom window button toggles fullscreen mode or
maximizes the window.
win.resizable
A Boolean
property that determines whether the window can be manually resized by user.
win.closable
A Boolean
property that determines whether the window can be manually closed by user.
On Linux the setter is a no-op, although the getter returns true
.
win.movable
A Boolean
property that determines Whether the window can be moved by user.
On Linux the setter is a no-op, although the getter returns true
.
win.excludedFromShownWindowsMenu
macOS
A Boolean
property that determines whether the window is excluded from the application’s Windows menu. false
by default.
const win = new BrowserWindow({ height: 600, width: 600 })
const template = [
{
role: 'windowmenu'
}
]
win.excludedFromShownWindowsMenu = true
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
win.accessibleTitle
A String
property that defines an alternative title provided only to
accessibility tools such as screen readers. This string is not directly
visible to users.
Instance Methods
Objects created with new BrowserWindow
have the following instance methods:
Note: Some methods are only available on specific operating systems and are labeled as such.
win.destroy()
Force closing the window, the unload
and beforeunload
event won't be emitted
for the web page, and close
event will also not be emitted
for this window, but it guarantees the closed
event will be emitted.
win.close()
Try to close the window. This has the same effect as a user manually clicking the close button of the window. The web page may cancel the close though. See the close event.
win.focus()
Focuses on the window.
win.blur()
Removes focus from the window.
win.isFocused()
Returns Boolean
- Whether the window is focused.
win.isDestroyed()
Returns Boolean
- Whether the window is destroyed.
win.show()
Shows and gives focus to the window.
win.showInactive()
Shows the window but doesn't focus on it.
win.hide()
Hides the window.
win.isVisible()
Returns Boolean
- Whether the window is visible to the user.
win.isModal()
Returns Boolean
- Whether current window is a modal window.
win.maximize()
Maximizes the window. This will also show (but not focus) the window if it isn't being displayed already.
win.unmaximize()
Unmaximizes the window.
win.isMaximized()
Returns Boolean
- Whether the window is maximized.
win.minimize()
Minimizes the window. On some platforms the minimized window will be shown in the Dock.
win.restore()
Restores the window from minimized state to its previous state.
win.isMinimized()
Returns Boolean
- Whether the window is minimized.
win.isFullScreen()
Returns Boolean
- Whether the window is in fullscreen mode.
win.setSimpleFullScreen(flag)
macOS
flag
Boolean
Enters or leaves simple fullscreen mode.
Simple fullscreen mode emulates the native fullscreen behavior found in versions of macOS prior to Lion (10.7).
win.isSimpleFullScreen()
macOS
Returns Boolean
- Whether the window is in simple (pre-Lion) fullscreen mode.
win.isNormal()
Returns Boolean
- Whether the window is in normal state (not maximized, not minimized, not in fullscreen mode).
win.setAspectRatio(aspectRatio[, extraSize])
aspectRatio
Float - The aspect ratio to maintain for some portion of the content view.extraSize
Size (optional) macOS - The extra size not to be included while maintaining the aspect ratio.
This will make a window maintain an aspect ratio. The extra size allows a developer to have space, specified in pixels, not included within the aspect ratio calculations. This API already takes into account the difference between a window's size and its content size.
Consider a normal window with an HD video player and associated controls. Perhaps there are 15 pixels of controls on the left edge, 25 pixels of controls on the right edge and 50 pixels of controls below the player. In order to maintain a 16:9 aspect ratio (standard aspect ratio for HD @1920x1080) within the player itself we would call this function with arguments of 16/9 and { width: 40, height: 50 }. The second argument doesn't care where the extra width and height are within the content view--only that they exist. Sum any extra width and height areas you have within the overall content view.
The aspect ratio is not respected when window is resized programmingly with
APIs like win.setSize
.
win.setBackgroundColor(backgroundColor)
backgroundColor
String - Window's background color as a hexadecimal value, like#66CD00
or#FFF
or#80FFFFFF
(alpha is supported iftransparent
istrue
). Default is#FFF
(white).
Sets the background color of the window. See Setting
backgroundColor
.
win.previewFile(path[, displayName])
macOS
path
String - The absolute path to the file to preview with QuickLook. This is important as Quick Look uses the file name and file extension on the path to determine the content type of the file to open.displayName
String (optional) - The name of the file to display on the Quick Look modal view. This is purely visual and does not affect the content type of the file. Defaults topath
.
Uses Quick Look to preview a file at a given path.
win.closeFilePreview()
macOS
Closes the currently open Quick Look panel.
win.setBounds(bounds[, animate])
bounds
Partial<Rectangle>animate
Boolean (optional) macOS
Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
// set all bounds properties
win.setBounds({ x: 440, y: 225, width: 800, height: 600 })
// set a single bounds property
win.setBounds({ width: 100 })
// { x: 440, y: 225, width: 100, height: 600 }
console.log(win.getBounds())
win.getBounds()
Returns Rectangle
- The bounds
of the window as Object
.
win.getBackgroundColor()
Returns String
- Gets the background color of the window. See Setting
backgroundColor
.
win.setContentBounds(bounds[, animate])
bounds
Rectangleanimate
Boolean (optional) macOS
Resizes and moves the window's client area (e.g. the web page) to the supplied bounds.
win.getContentBounds()
Returns Rectangle
- The bounds
of the window's client area as Object
.
win.getNormalBounds()
Returns Rectangle
- Contains the window bounds of the normal state
Note: whatever the current state of the window : maximized, minimized or in fullscreen, this function always returns the position and size of the window in normal state. In normal state, getBounds and getNormalBounds returns the same Rectangle
.
win.isEnabled()
Returns Boolean
- whether the window is enabled.
win.setSize(width, height[, animate])
width
Integerheight
Integeranimate
Boolean (optional) macOS
Resizes the window to width
and height
. If width
or height
are below any set minimum size constraints the window will snap to its minimum size.
win.getSize()
Returns Integer[]
- Contains the window's width and height.
win.setContentSize(width, height[, animate])
width
Integerheight
Integeranimate
Boolean (optional) macOS
Resizes the window's client area (e.g. the web page) to width
and height
.
win.getContentSize()
Returns Integer[]
- Contains the window's client area's width and height.
win.setMinimumSize(width, height)
width
Integerheight
Integer
Sets the minimum size of window to width
and height
.
win.getMinimumSize()
Returns Integer[]
- Contains the window's minimum width and height.
win.setMaximumSize(width, height)
width
Integerheight
Integer
Sets the maximum size of window to width
and height
.
win.getMaximumSize()
Returns Integer[]
- Contains the window's maximum width and height.
win.setResizable(resizable)
resizable
Boolean
Sets whether the window can be manually resized by the user.
win.isResizable()
Returns Boolean
- Whether the window can be manually resized by the user.
win.setMovable(movable)
macOS Windows
movable
Boolean
Sets whether the window can be moved by user. On Linux does nothing.
win.isMovable()
macOS Windows
Returns Boolean
- Whether the window can be moved by user.
On Linux always returns true
.
win.setMinimizable(minimizable)
macOS Windows
minimizable
Boolean
Sets whether the window can be manually minimized by user. On Linux does nothing.
win.isMinimizable()
macOS Windows
Returns Boolean
- Whether the window can be manually minimized by the user.
On Linux always returns true
.
win.setMaximizable(maximizable)
macOS Windows
maximizable
Boolean
Sets whether the window can be manually maximized by user. On Linux does nothing.
win.isMaximizable()
macOS Windows
Returns Boolean
- Whether the window can be manually maximized by user.
On Linux always returns true
.
win.setFullScreenable(fullscreenable)
fullscreenable
Boolean
Sets whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.
win.isFullScreenable()
Returns Boolean
- Whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.
win.setClosable(closable)
macOS Windows
closable
Boolean
Sets whether the window can be manually closed by user. On Linux does nothing.
win.isClosable()
macOS Windows
Returns Boolean
- Whether the window can be manually closed by user.
On Linux always returns true
.
win.setAlwaysOnTop(flag[, level][, relativeLevel])
flag
Booleanlevel
String (optional) macOS Windows - Values includenormal
,floating
,torn-off-menu
,modal-panel
,main-menu
,status
,pop-up-menu
,screen-saver
, and(Deprecated). The default isdock
floating
whenflag
is true. Thelevel
is reset tonormal
when the flag is false. Note that fromfloating
tostatus
included, the window is placed below the Dock on macOS and below the taskbar on Windows. Frompop-up-menu
to a higher it is shown above the Dock on macOS and above the taskbar on Windows. See the macOS docs for more details.relativeLevel
Integer (optional) macOS - The number of layers higher to set this window relative to the givenlevel
. The default is0
. Note that Apple discourages setting levels higher than 1 abovescreen-saver
.
Sets whether the window should show always on top of other windows. After setting this, the window is still a normal window, not a toolbox window which can not be focused on.
win.isAlwaysOnTop()
Returns Boolean
- Whether the window is always on top of other windows.
win.moveAbove(mediaSourceId)
mediaSourceId
String - Window id in the format of DesktopCapturerSource's id. For example "window:1869:0".
Moves window above the source window in the sense of z-order. If the
mediaSourceId
is not of type window or if the window does not exist then
this method throws an error.
win.moveTop()
Moves window to top(z-order) regardless of focus
win.center()
Moves window to the center of the screen.
win.setPosition(x, y[, animate])
x
Integery
Integeranimate
Boolean (optional) macOS
Moves window to x
and y
.
win.getPosition()
Returns Integer[]
- Contains the window's current position.
win.getTitle()
Returns String
- The title of the native window.
Note: The title of the web page can be different from the title of the native window.
win.setSheetOffset(offsetY[, offsetX])
macOS
offsetY
FloatoffsetX
Float (optional)
Changes the attachment point for sheets on macOS. By default, sheets are attached just below the window frame, but you may want to display them beneath a HTML-rendered toolbar. For example:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
const toolbarRect = document.getElementById('toolbar').getBoundingClientRect()
win.setSheetOffset(toolbarRect.height)
win.isKiosk()
Returns Boolean
- Whether the window is in kiosk mode.
win.getMediaSourceId()
Returns String
- Window id in the format of DesktopCapturerSource's id. For example "window🔢0".
More precisely the format is window:id:other_id
where id
is HWND
on
Windows, CGWindowID
(uint64_t
) on macOS and Window
(unsigned long
) on
Linux. other_id
is used to identify web contents (tabs) so within the same
top level window.
win.getNativeWindowHandle()
Returns Buffer
- The platform-specific handle of the window.
The native type of the handle is HWND
on Windows, NSView*
on macOS, and
Window
(unsigned long
) on Linux.
win.hookWindowMessage(message, callback)
Windows
message
Integercallback
Function
Hooks a windows message. The callback
is called when
the message is received in the WndProc.
win.isWindowMessageHooked(message)
Windows
message
Integer
Returns Boolean
- true
or false
depending on whether the message is hooked.
win.unhookAllWindowMessages()
Windows
Unhooks all of the window messages.
win.setRepresentedFilename(filename)
macOS
filename
String
Sets the pathname of the file the window represents, and the icon of the file will show in window's title bar.
win.getRepresentedFilename()
macOS
Returns String
- The pathname of the file the window represents.
win.setDocumentEdited(edited)
macOS
edited
Boolean
Specifies whether the window’s document has been edited, and the icon in title
bar will become gray when set to true
.
win.isDocumentEdited()
macOS
Returns Boolean
- Whether the window's document has been edited.
win.capturePage([rect])
rect
Rectangle (optional) - The bounds to capture
Returns Promise<NativeImage>
- Resolves with a NativeImage
Captures a snapshot of the page within rect
. Omitting rect
will capture the whole visible page.
win.loadURL(url[, options])
url
Stringoptions
Object (optional)httpReferrer
(String | Referrer) (optional) - An HTTP Referrer URL.userAgent
String (optional) - A user agent originating the request.extraHeaders
String (optional) - Extra headers separated by "\n"postData
(UploadRawData[] | UploadFile[] | UploadBlob[]) (optional)baseURLForDataURL
String (optional) - Base URL (with trailing path separator) for files to be loaded by the data URL. This is needed only if the specifiedurl
is a data URL and needs to load other files.
Returns Promise<void>
- the promise will resolve when the page has finished loading
(see did-finish-load
), and rejects
if the page fails to load (see did-fail-load
).
Same as webContents.loadURL(url[, options])
.
The url
can be a remote address (e.g. http://
) or a path to a local
HTML file using the file://
protocol.
To ensure that file URLs are properly formatted, it is recommended to use
Node's url.format
method:
const url = require('url').format({
protocol: 'file',
slashes: true,
pathname: require('path').join(__dirname, 'index.html')
})
win.loadURL(url)
You can load a URL using a POST
request with URL-encoded data by doing
the following:
win.loadURL('http://localhost:8000/post', {
postData: [{
type: 'rawData',
bytes: Buffer.from('hello=world')
}],
extraHeaders: 'Content-Type: application/x-www-form-urlencoded'
})
win.loadFile(filePath[, options])
filePath
Stringoptions
Object (optional)query
Record<String, String> (optional) - Passed tourl.format()
.search
String (optional) - Passed tourl.format()
.hash
String (optional) - Passed tourl.format()
.
Returns Promise<void>
- the promise will resolve when the page has finished loading
(see did-finish-load
), and rejects
if the page fails to load (see did-fail-load
).
Same as webContents.loadFile
, filePath
should be a path to an HTML
file relative to the root of your application. See the webContents
docs
for more information.
win.reload()
Same as webContents.reload
.
win.removeMenu()
Linux Windows
Remove the window's menu bar.
win.setProgressBar(progress[, options])
progress
Doubleoptions
Object (optional)mode
String Windows - Mode for the progress bar. Can benone
,normal
,indeterminate
,error
orpaused
.
Sets progress value in progress bar. Valid range is [0, 1.0].
Remove progress bar when progress < 0; Change to indeterminate mode when progress > 1.
On Linux platform, only supports Unity desktop environment, you need to specify
the *.desktop
file name to desktopName
field in package.json
. By default,
it will assume {app.name}.desktop
.
On Windows, a mode can be passed. Accepted values are none
, normal
,
indeterminate
, error
, and paused
. If you call setProgressBar
without a
mode set (but with a value within the valid range), normal
will be assumed.
win.setOverlayIcon(overlay, description)
Windows
overlay
NativeImage | null - the icon to display on the bottom right corner of the taskbar icon. If this parameter isnull
, the overlay is cleareddescription
String - a description that will be provided to Accessibility screen readers
Sets a 16 x 16 pixel overlay onto the current taskbar icon, usually used to convey some sort of application status or to passively notify the user.
win.hasShadow()
Returns Boolean
- Whether the window has a shadow.
win.setOpacity(opacity)
Windows macOS
opacity
Number - between 0.0 (fully transparent) and 1.0 (fully opaque)
Sets the opacity of the window. On Linux, does nothing. Out of bound number values are clamped to the [0, 1] range.
win.getOpacity()
Returns Number
- between 0.0 (fully transparent) and 1.0 (fully opaque). On
Linux, always returns 1.
win.setShape(rects)
Windows Linux Experimental
rects
Rectangle[] - Sets a shape on the window. Passing an empty list reverts the window to being rectangular.
Setting a window shape determines the area within the window where the system permits drawing and user interaction. Outside of the given region, no pixels will be drawn and no mouse events will be registered. Mouse events outside of the region will not be received by that window, but will fall through to whatever is behind the window.
win.setThumbarButtons(buttons)
Windows
buttons
ThumbarButton[]
Returns Boolean
- Whether the buttons were added successfully
Add a thumbnail toolbar with a specified set of buttons to the thumbnail image
of a window in a taskbar button layout. Returns a Boolean
object indicates
whether the thumbnail has been added successfully.
The number of buttons in thumbnail toolbar should be no greater than 7 due to the limited room. Once you setup the thumbnail toolbar, the toolbar cannot be removed due to the platform's limitation. But you can call the API with an empty array to clean the buttons.
The buttons
is an array of Button
objects:
Button
Objecticon
NativeImage - The icon showing in thumbnail toolbar.click
Functiontooltip
String (optional) - The text of the button's tooltip.flags
String[] (optional) - Control specific states and behaviors of the button. By default, it is['enabled']
.
The flags
is an array that can include following String
s:
enabled
- The button is active and available to the user.disabled
- The button is disabled. It is present, but has a visual state indicating it will not respond to user action.dismissonclick
- When the button is clicked, the thumbnail window closes immediately.nobackground
- Do not draw a button border, use only the image.hidden
- The button is not shown to the user.noninteractive
- The button is enabled but not interactive; no pressed button state is drawn. This value is intended for instances where the button is used in a notification.
win.setThumbnailClip(region)
Windows
region
Rectangle - Region of the window
Sets the region of the window to show as the thumbnail image displayed when
hovering over the window in the taskbar. You can reset the thumbnail to be
the entire window by specifying an empty region:
{ x: 0, y: 0, width: 0, height: 0 }
.
win.setThumbnailToolTip(toolTip)
Windows
toolTip
String
Sets the toolTip that is displayed when hovering over the window thumbnail in the taskbar.
win.setAppDetails(options)
Windows
options
ObjectappId
String (optional) - Window's App User Model ID. It has to be set, otherwise the other options will have no effect.appIconPath
String (optional) - Window's Relaunch Icon.appIconIndex
Integer (optional) - Index of the icon inappIconPath
. Ignored whenappIconPath
is not set. Default is0
.relaunchCommand
String (optional) - Window's Relaunch Command.relaunchDisplayName
String (optional) - Window's Relaunch Display Name.
Sets the properties for the window's taskbar button.
Note: relaunchCommand
and relaunchDisplayName
must always be set
together. If one of those properties is not set, then neither will be used.
win.showDefinitionForSelection()
macOS
Same as webContents.showDefinitionForSelection()
.
win.setWindowButtonVisibility(visible)
macOS
visible
Boolean
Sets whether the window traffic light buttons should be visible.
This cannot be called when titleBarStyle
is set to customButtonsOnHover
.
win.setAutoHideMenuBar(hide)
hide
Boolean
Sets whether the window menu bar should hide itself automatically. Once set the
menu bar will only show when users press the single Alt
key.
If the menu bar is already visible, calling setAutoHideMenuBar(true)
won't hide it immediately.
win.isMenuBarAutoHide()
Returns Boolean
- Whether menu bar automatically hides itself.
win.setMenuBarVisibility(visible)
Windows Linux
visible
Boolean
Sets whether the menu bar should be visible. If the menu bar is auto-hide, users can still bring up the menu bar by pressing the single Alt
key.
win.isMenuBarVisible()
Returns Boolean
- Whether the menu bar is visible.
win.setVisibleOnAllWorkspaces(visible[, options])
visible
Booleanoptions
Object (optional)visibleOnFullScreen
Boolean (optional) macOS - Sets whether the window should be visible above fullscreen windows
Sets whether the window should be visible on all workspaces.
Note: This API does nothing on Windows.
win.isVisibleOnAllWorkspaces()
Returns Boolean
- Whether the window is visible on all workspaces.
Note: This API always returns false on Windows.
win.setIgnoreMouseEvents(ignore[, options])
ignore
Booleanoptions
Object (optional)forward
Boolean (optional) macOS Windows - If true, forwards mouse move messages to Chromium, enabling mouse related events such asmouseleave
. Only used whenignore
is true. Ifignore
is false, forwarding is always disabled regardless of this value.
Makes the window ignore all mouse events.
All mouse events happened in this window will be passed to the window below this window, but if this window has focus, it will still receive keyboard events.
win.setContentProtection(enable)
macOS Windows
enable
Boolean
Prevents the window contents from being captured by other apps.
On macOS it sets the NSWindow's sharingType to NSWindowSharingNone.
On Windows it calls SetWindowDisplayAffinity with WDA_MONITOR
.
win.setFocusable(focusable)
macOS Windows
focusable
Boolean
Changes whether the window can be focused.
On macOS it does not remove the focus from the window.
win.setParentWindow(parent)
parent
BrowserWindow | null
Sets parent
as current window's parent window, passing null
will turn
current window into a top-level window.
win.getParentWindow()
Returns BrowserWindow
- The parent window.
win.getChildWindows()
Returns BrowserWindow[]
- All child windows.
win.selectPreviousTab()
macOS
Selects the previous tab when native tabs are enabled and there are other tabs in the window.
win.selectNextTab()
macOS
Selects the next tab when native tabs are enabled and there are other tabs in the window.
win.mergeAllWindows()
macOS
Merges all windows into one window with multiple tabs when native tabs are enabled and there is more than one open window.
win.moveTabToNewWindow()
macOS
Moves the current tab into a new window if native tabs are enabled and there is more than one tab in the current window.
win.toggleTabBar()
macOS
Toggles the visibility of the tab bar if native tabs are enabled and there is only one tab in the current window.
win.addTabbedWindow(browserWindow)
macOS
browserWindow
BrowserWindow
Adds a window as a tab on this window, after the tab for the window instance.
win.setVibrancy(type)
macOS
type
String | null - Can beappearance-based
,light
,dark
,titlebar
,selection
,menu
,popover
,sidebar
,medium-light
,ultra-dark
,header
,sheet
,window
,hud
,fullscreen-ui
,tooltip
,content
,under-window
, orunder-page
. See the macOS documentation for more details.
Adds a vibrancy effect to the browser window. Passing null
or an empty string
will remove the vibrancy effect on the window.
Note that appearance-based
, light
, dark
, medium-light
, and ultra-dark
have been
deprecated and will be removed in an upcoming version of macOS.
win.setTrafficLightPosition(position)
macOS
position
Point
Set a custom position for the traffic light buttons. Can only be used with titleBarStyle
set to hidden
.
win.getTrafficLightPosition()
macOS
Returns Point
- The current position for the traffic light buttons. Can only be used with titleBarStyle
set to hidden
.
win.setTouchBar(touchBar)
macOS
touchBar
TouchBar | null
Sets the touchBar layout for the current window. Specifying null
or
undefined
clears the touch bar. This method only has an effect if the
machine has a touch bar and is running on macOS 10.12.1+.
Note: The TouchBar API is currently experimental and may change or be removed in future Electron releases.
win.setBrowserView(browserView)
Experimental
browserView
BrowserView | null - AttachbrowserView
towin
. If there are otherBrowserView
s attached, they will be removed from this window.
win.getBrowserView()
Experimental
Returns BrowserView | null
- The BrowserView
attached to win
. Returns null
if one is not attached. Throws an error if multiple BrowserView
s are attached.
win.addBrowserView(browserView)
Experimental
browserView
BrowserView
Replacement API for setBrowserView supporting work with multi browser views.
win.getBrowserViews()
Experimental
Returns BrowserView[]
- an array of all BrowserViews that have been attached
with addBrowserView
or setBrowserView
.
Note: The BrowserView API is currently experimental and may change or be removed in future Electron releases.
Class: BrowserWindowProxy
Manipulate the child browser window
Process: Renderer
The BrowserWindowProxy
object is returned from window.open
and provides
limited functionality with the child window.
Instance Methods
The BrowserWindowProxy
object has the following instance methods:
win.blur()
Removes focus from the child window.
win.close()
Forcefully closes the child window without calling its unload event.
win.focus()
Focuses the child window (brings the window to front).
win.print()
Invokes the print dialog on the child window.
win.postMessage(message, targetOrigin)
message
anytargetOrigin
String
Sends a message to the child window with the specified origin or *
for no
origin preference.
In addition to these methods, the child window implements window.opener
object
with no properties and a single method.
Instance Properties
The BrowserWindowProxy
object has the following instance properties:
win.closed
A Boolean
that is set to true after the child window gets closed.
Build Instructions
Follow the guidelines below for building Electron.
Platform prerequisites
Check the build prerequisites for your platform before proceeding
Build Tools
Electron's Build Tools automate much of the setup for compiling Electron from source with different configurations and build targets. If you wish to set up the environment manually, the instructions are listed below.
GN prerequisites
You'll need to install depot_tools
, the toolset
used for fetching Chromium and its dependencies.
Also, on Windows, you'll need to set the environment variable
DEPOT_TOOLS_WIN_TOOLCHAIN=0
. To do so, open Control Panel
→ System and Security
→ System
→ Advanced system settings
and add a system variable
DEPOT_TOOLS_WIN_TOOLCHAIN
with value 0
. This tells depot_tools
to use
your locally installed version of Visual Studio (by default, depot_tools
will
try to download a Google-internal version that only Googlers have access to).
Setting up the git cache
If you plan on checking out Electron more than once (for example, to have
multiple parallel directories checked out to different branches), using the git
cache will speed up subsequent calls to gclient
. To do this, set a
GIT_CACHE_PATH
environment variable:
$ export GIT_CACHE_PATH="${HOME}/.git_cache"
$ mkdir -p "${GIT_CACHE_PATH}"
# This will use about 16G.
Getting the code
$ mkdir electron && cd electron
$ gclient config --name "src/electron" --unmanaged https://github.com/electron/electron
$ gclient sync --with_branch_heads --with_tags
# This will take a while, go get a coffee.
Instead of
https://github.com/electron/electron
, you can use your own fork here (something likehttps://github.com/<username>/electron
).
A note on pulling/pushing
If you intend to git pull
or git push
from the official electron
repository in the future, you now need to update the respective folder's
origin URLs.
$ cd src/electron
$ git remote remove origin
$ git remote add origin https://github.com/electron/electron
$ git checkout master
$ git branch --set-upstream-to=origin/master
$ cd -
📝 gclient
works by checking a file called DEPS
inside the
src/electron
folder for dependencies (like Chromium or Node.js).
Running gclient sync -f
ensures that all dependencies required
to build Electron match that file.
So, in order to pull, you'd run the following commands:
$ cd src/electron
$ git pull
$ gclient sync -f
Building
$ cd src
$ export CHROMIUM_BUILDTOOLS_PATH=`pwd`/buildtools
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\") $GN_EXTRA_ARGS"
Or on Windows (without the optional argument):
$ cd src
$ set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\")"
This will generate a build directory out/Testing
under src/
with
the testing build configuration. You can replace Testing
with another name,
but it should be a subdirectory of out
.
Also you shouldn't have to run gn gen
again—if you want to change the
build arguments, you can run gn args out/Testing
to bring up an editor.
To see the list of available build configuration options, run gn args out/Testing --list
.
For generating Testing build config of Electron:
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\") $GN_EXTRA_ARGS"
For generating Release (aka "non-component" or "static") build config of Electron:
$ gn gen out/Release --args="import(\"//electron/build/args/release.gn\") $GN_EXTRA_ARGS"
To build, run ninja
with the electron
target:
Nota Bene: This will also take a while and probably heat up your lap.
For the testing configuration:
$ ninja -C out/Testing electron
For the release configuration:
$ ninja -C out/Release electron
This will build all of what was previously 'libchromiumcontent' (i.e. the
content/
directory of chromium
and its dependencies, incl. WebKit and V8),
so it will take a while.
The built executable will be under ./out/Testing
:
$ ./out/Testing/Electron.app/Contents/MacOS/Electron
# or, on Windows
$ ./out/Testing/electron.exe
# or, on Linux
$ ./out/Testing/electron
Packaging
On linux, first strip the debugging and symbol information:
electron/script/strip-binaries.py -d out/Release
To package the electron build as a distributable zip file:
ninja -C out/Release electron:electron_dist_zip
Cross-compiling
To compile for a platform that isn't the same as the one you're building on,
set the target_cpu
and target_os
GN arguments. For example, to compile an
x86 target from an x64 host, specify target_cpu = "x86"
in gn args
.
$ gn gen out/Testing-x86 --args='... target_cpu = "x86"'
Not all combinations of source and target CPU/OS are supported by Chromium.
Host | Target | Status |
---|---|---|
Windows x64 | Windows arm64 | Experimental |
Windows x64 | Windows x86 | Automatically tested |
Linux x64 | Linux x86 | Automatically tested |
If you test other combinations and find them to work, please update this document :)
See the GN reference for allowable values of target_os
and target_cpu
.
Windows on Arm (experimental)
To cross-compile for Windows on Arm, follow Chromium's guide to get the necessary dependencies, SDK and libraries, then build with ELECTRON_BUILDING_WOA=1
in your environment before running gclient sync
.
set ELECTRON_BUILDING_WOA=1
gclient sync -f --with_branch_heads --with_tags
Or (if using PowerShell):
$env:ELECTRON_BUILDING_WOA=1
gclient sync -f --with_branch_heads --with_tags
Next, run gn gen
as above with target_cpu="arm64"
.
Tests
To run the tests, you'll first need to build the test modules against the
same version of Node.js that was built as part of the build process. To
generate build headers for the modules to compile against, run the following
under src/
directory.
$ ninja -C out/Testing third_party/electron_node:headers
You can now run the tests.
If you're debugging something, it can be helpful to pass some extra flags to the Electron binary:
$ npm run test -- \
--enable-logging -g 'BrowserWindow module'
Sharing the git cache between multiple machines
It is possible to share the gclient git cache with other machines by exporting it as SMB share on linux, but only one process/machine can be using the cache at a time. The locks created by git-cache script will try to prevent this, but it may not work perfectly in a network.
On Windows, SMBv2 has a directory cache that will cause problems with the git cache script, so it is necessary to disable it by setting the registry key
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Lanmanworkstation\Parameters\DirectoryCacheLifetime
to 0. More information: https://stackoverflow.com/a/9935126
This can be set quickly in powershell (ran as administrator):
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\Lanmanworkstation\Parameters" -Name DirectoryCacheLifetime -Value 0 -PropertyType DWORD -Force
gclient sync complains about rebase
If gclient sync
is interrupted the git tree may be left in a bad state, leading to a cryptic message when running gclient sync
in the future:
2> Conflict while rebasing this branch.
2> Fix the conflict and run gclient again.
2> See man git-rebase for details.
If there are no git conflicts or rebases in src/electron
, you may need to abort a git am
in src
:
$ cd ../
$ git am --abort
$ cd electron
$ gclient sync -f
I'm being asked for a username/password for chromium-internal.googlesource.com
If you see a prompt for Username for 'https://chrome-internal.googlesource.com':
when running gclient sync
on Windows, it's probably because the DEPOT_TOOLS_WIN_TOOLCHAIN
environment variable is not set to 0. Open Control Panel
→ System and Security
→ System
→ Advanced system settings
and add a system variable
DEPOT_TOOLS_WIN_TOOLCHAIN
with value 0
. This tells depot_tools
to use
your locally installed version of Visual Studio (by default, depot_tools
will
try to download a Google-internal version that only Googlers have access to).
Build Instructions (Linux)
Follow the guidelines below for building Electron on Linux.
Prerequisites
-
At least 25GB disk space and 8GB RAM.
-
Python 2.7.x. Some distributions like CentOS 6.x still use Python 2.6.x so you may need to check your Python version with
python -V
.Please also ensure that your system and Python version support at least TLS 1.2. For a quick test, run the following script:
$ npx @electron/check-python-tls
If the script returns that your configuration is using an outdated security protocol, use your system's package manager to update Python to the latest version in the 2.7.x branch. Alternatively, visit https://www.python.org/downloads/ for detailed instructions.
-
Node.js. There are various ways to install Node. You can download source code from nodejs.org and compile it. Doing so permits installing Node on your own home directory as a standard user. Or try repositories such as NodeSource.
-
clang 3.4 or later.
-
Development headers of GTK 3 and libnotify.
On Ubuntu, install the following libraries:
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \
libnotify-dev libgnome-keyring-dev \
libasound2-dev libcap-dev libcups2-dev libxtst-dev \
libxss1 libnss3-dev gcc-multilib g++-multilib curl \
gperf bison python-dbusmock openjdk-8-jre
On RHEL / CentOS, install the following libraries:
$ sudo yum install clang dbus-devel gtk3-devel libnotify-devel \
libgnome-keyring-devel xorg-x11-server-utils libcap-devel \
cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \
nss-devel python-dbusmock openjdk-8-jre
On Fedora, install the following libraries:
$ sudo dnf install clang dbus-devel gtk3-devel libnotify-devel \
libgnome-keyring-devel xorg-x11-server-utils libcap-devel \
cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \
nss-devel python-dbusmock openjdk-8-jre
On Arch Linux / Manjaro, install the following libraries:
$ sudo pacman -Syu base-devel clang libdbus gtk2 libnotify \
libgnome-keyring alsa-lib libcap libcups libxtst \
libxss nss gcc-multilib curl gperf bison \
python2 python-dbusmock jdk8-openjdk
Other distributions may offer similar packages for installation via package managers such as pacman. Or one can compile from source code.
Cross compilation
If you want to build for an arm
target you should also install the following
dependencies:
$ sudo apt-get install libc6-dev-armhf-cross linux-libc-dev-armhf-cross \
g++-arm-linux-gnueabihf
Similarly for arm64
, install the following:
$ sudo apt-get install libc6-dev-arm64-cross linux-libc-dev-arm64-cross \
g++-aarch64-linux-gnu
And to cross-compile for arm
or ia32
targets, you should pass the
target_cpu
parameter to gn gen
:
$ gn gen out/Testing --args='import(...) target_cpu="arm"'
Error While Loading Shared Libraries: libtinfo.so.5
Prebuilt clang
will try to link to libtinfo.so.5
. Depending on the host
architecture, symlink to appropriate libncurses
:
$ sudo ln -s /usr/lib/libncurses.so.5 /usr/lib/libtinfo.so.5
Advanced topics
The default building configuration is targeted for major desktop Linux distributions. To build for a specific distribution or device, the following information may help you.
Using system clang
instead of downloaded clang
binaries
By default Electron is built with prebuilt
clang
binaries provided by the
Chromium project. If for some reason you want to build with the clang
installed in your system, you can specify the clang_base_path
argument in the
GN args.
For example if you installed clang
under /usr/local/bin/clang
:
$ gn gen out/Testing --args='import("//electron/build/args/testing.gn") clang_base_path = "/usr/local/bin"'
Using compilers other than clang
Building Electron with compilers other than clang
is not supported.
Build Instructions (macOS)
Follow the guidelines below for building Electron on macOS.
Python
Please also ensure that your system and Python version support at least TLS 1.2. This depends on both your version of macOS and Python. For a quick test, run:
$ npx @electron/check-python-tls
If the script returns that your configuration is using an outdated security protocol, you can either update macOS to High Sierra or install a new version of Python 2.7.x. To upgrade Python, use Homebrew:
$ brew install python@2 && brew link python@2 --force
If you are using Python as provided by Homebrew, you also need to install the following Python modules:
You can use pip
to install it:
$ pip install pyobjc
macOS SDK
If you're developing Electron and don't plan to redistribute your custom Electron build, you may skip this section.
Official Electron builds are built with Xcode 9.4.1, and the macOS 10.13 SDK. Building with a newer SDK works too, but the releases currently use the 10.13 SDK.
Build Instructions (Windows)
Follow the guidelines below for building Electron on Windows.
Prerequisites
- Windows 10 / Server 2012 R2 or higher
- Visual Studio 2017 15.7.2 or higher - download VS 2019 Community Edition for
free
- See the Chromium build documentation for more details on which Visual Studio components are required.
- If your Visual Studio is installed in a directory other than the default, you'll need to
set a few environment variables to point the toolchains to your installation path.
vs2019_install = DRIVE:\path\to\Microsoft Visual Studio\2019\Community
, replacing2019
andCommunity
with your installed versions and replacingDRIVE:
with the drive that Visual Studio is on. Often, this will beC:
.WINDOWSSDKDIR = DRIVE:\path\to\Windows Kits\10
, replacingDRIVE:
with the drive that Windows Kits is on. Often, this will beC:
.
- Python for Windows (pywin32) Extensions is also needed in order to run the build process.
- Node.js
- Git
- Debugging Tools for Windows of Windows SDK 10.0.15063.468 if you plan on
creating a full distribution since
symstore.exe
is used for creating a symbol store from.pdb
files.- Different versions of the SDK can be installed side by side. To install the
SDK, open Visual Studio Installer, select
Change
→Individual Components
, scroll down and select the appropriate Windows SDK to install. Another option would be to look at the Windows SDK and emulator archive and download the standalone version of the SDK respectively. - The SDK Debugging Tools must also be installed. If the Windows 10 SDK was installed
via the Visual Studio installer, then they can be installed by going to:
Control Panel
→Programs
→Programs and Features
→ Select the "Windows Software Development Kit" →Change
→Change
→ Check "Debugging Tools For Windows" →Change
. Or, you can download the standalone SDK installer and use it to install the Debugging Tools.
- Different versions of the SDK can be installed side by side. To install the
SDK, open Visual Studio Installer, select
If you don't currently have a Windows installation, dev.microsoftedge.com has timebombed versions of Windows that you can use to build Electron.
Building Electron is done entirely with command-line scripts and cannot be done with Visual Studio. You can develop Electron with any editor but support for building with Visual Studio will come in the future.
Note: Even though Visual Studio is not used for building, it's still required because we need the build toolchains it provides.
Exclude source tree from Windows Security
Windows Security doesn't like one of the files in the Chromium source code
(see https://crbug.com/441184), so it will constantly delete it, causing gclient sync
issues.
You can exclude the source tree from being monitored by Windows Security by
following these instructions.
32bit Build
To build for the 32bit target, you need to pass target_cpu = "x86"
as a GN
arg. You can build the 32bit target alongside the 64bit target by using a
different output directory for GN, e.g. out/Release-x86
, with different
arguments.
$ gn gen out/Release-x86 --args="import(\"//electron/build/args/release.gn\") target_cpu=\"x86\""
The other building steps are exactly the same.
Visual Studio project
To generate a Visual Studio project, you can pass the --ide=vs2017
parameter
to gn gen
:
$ gn gen out/Testing --ide=vs2017
Command xxxx not found
If you encountered an error like Command xxxx not found
, you may try to use
the VS2015 Command Prompt
console to execute the build scripts.
Fatal internal compiler error: C1001
Make sure you have the latest Visual Studio update installed.
LNK1181: cannot open input file 'kernel32.lib'
Try reinstalling 32bit Node.js.
Error: ENOENT, stat 'C:\Users\USERNAME\AppData\Roaming\npm'
Creating that directory should fix the problem:
$ mkdir ~\AppData\Roaming\npm
node-gyp is not recognized as an internal or external command
You may get this error if you are using Git Bash for building, you should use PowerShell or VS2015 Command Prompt instead.
cannot create directory at '...': Filename too long
node.js has some extremely long pathnames, and by default git on windows doesn't handle long pathnames correctly (even though windows supports them). This should fix it:
$ git config --system core.longpaths true
error: use of undeclared identifier 'DefaultDelegateCheckMode'
This can happen during build, when Debugging Tools for Windows has been installed with Windows Driver Kit. Uninstall Windows Driver Kit and install Debugging Tools with steps described above.
ImportError: No module named win32file
Make sure you have installed pywin32
with pip install pywin32
.
Build Scripts Hang Until Keypress
This bug is a "feature" of Windows' command prompt. It happens when clicking inside the prompt window with
QuickEdit
enabled and is intended to allow selecting and copying output text easily.
Since each accidental click will pause the build process, you might want to disable this
feature in the command prompt properties.
Build System Overview
Electron uses GN for project generation and
ninja for building. Project configurations can
be found in the .gn
and .gni
files.
GN Files
The following gn
files contain the main rules for building Electron:
BUILD.gn
defines how Electron itself is built and includes the default configurations for linking with Chromium.build/args/{debug,release,all}.gn
contain the default build arguments for building Electron.
Component Build
Since Chromium is quite a large project, the final linking stage can take quite a few minutes, which makes it hard for development. In order to solve this, Chromium introduced the "component build", which builds each component as a separate shared library, making linking very quick but sacrificing file size and performance.
Electron inherits this build option from Chromium. In Debug
builds, the
binary will be linked to a shared library version of Chromium's components to
achieve fast linking time; for Release
builds, the binary will be linked to
the static library versions, so we can have the best possible binary size and
performance.
Tests
NB this section is out of date and contains information that is no longer relevant to the GN-built electron.
Test your changes conform to the project coding style using:
$ npm run lint
Test functionality using:
$ npm test
Whenever you make changes to Electron source code, you'll need to re-run the build before the tests:
$ npm run build && npm test
You can make the test suite run faster by isolating the specific test or block
you're currently working on using Mocha's
exclusive tests feature. Append
.only
to any describe
or it
function call:
describe.only('some feature', () => {
// ... only tests in this block will be run
})
Alternatively, you can use mocha's grep
option to only run tests matching the
given regular expression pattern:
$ npm test -- --grep child_process
Tests that include native modules (e.g. runas
) can't be executed with the
debug build (see #2558 for
details), but they will work with the release build.
To run the tests with the release build use:
$ npm test -- -R
Certificate Object
data
String - PEM encoded dataissuer
CertificatePrincipal - Issuer principalissuerName
String - Issuer's Common NameissuerCert
Certificate - Issuer certificate (if not self-signed)subject
CertificatePrincipal - Subject principalsubjectName
String - Subject's Common NameserialNumber
String - Hex value represented stringvalidStart
Number - Start date of the certificate being valid in secondsvalidExpiry
Number - End date of the certificate being valid in secondsfingerprint
String - Fingerprint of the certificate
CertificatePrincipal Object
commonName
String - Common Name.organizations
String[] - Organization names.organizationUnits
String[] - Organization Unit names.locality
String - Locality.state
String - State or province.country
String - Country or region.
Chromium Development
A collection of resources for learning about Chromium and tracking its development
- @ChromiumDev on Twitter
- @googlechrome on Twitter
- Blog
- Code Search
- Source Code
- Development Calendar and Release Info
- Discussion Groups
See also V8 Development
Using clang-format on C++ Code
clang-format
is a tool to
automatically format C/C++/Objective-C code, so that developers don't need to
worry about style issues during code reviews.
It is highly recommended to format your changed C++ code before opening pull requests, which will save you and the reviewers' time.
You can install clang-format
and git-clang-format
via
npm install -g clang-format
.
To automatically format a file according to Electron C++ code style, run
clang-format -i path/to/electron/file.cc
. It should work on macOS/Linux/Windows.
The workflow to format your changed code:
- Make codes changes in Electron repository.
- Run
git add your_changed_file.cc
. - Run
git-clang-format
, and you will probably see modifications inyour_changed_file.cc
, these modifications are generated fromclang-format
. - Run
git add your_changed_file.cc
, and commit your change. - Now the branch is ready to be opened as a pull request.
If you want to format the changed code on your latest git commit (HEAD), you can
run git-clang-format HEAD~1
. See git-clang-format -h
for more details.
Editor Integration
You can also integrate clang-format
directly into your favorite editors.
For further guidance on setting up editor integration, see these pages:
Using clang-tidy on C++ Code
clang-tidy
is a tool to
automatically check C/C++/Objective-C code for style violations, programming
errors, and best practices.
Electron's clang-tidy
integration is provided as a linter script which can
be run with npm run lint:clang-tidy
. While clang-tidy
checks your on-disk
files, you need to have built Electron so that it knows which compiler flags
were used. There is one required option for the script --output-dir
, which
tells the script which build directory to pull the compilation information
from. A typical usage would be:
npm run lint:clang-tiy --out-dir ../out/Testing
With no filenames provided, all C/C++/Objective-C files will be checked.
You can provide a list of files to be checked by passing the filenames after
the options:
npm run lint:clang-tiy --out-dir ../out/Testing shell/browser/api/electron_api_app.cc
While clang-tidy
has a
long list
of possible checks, in Electron only a few are enabled by default. At the
moment Electron doesn't have a .clang-tidy
config, so clang-tidy
will
find the one from Chromium at src/.clang-tidy
and use the checks which
Chromium has enabled. You can change which checks are run by using the
--checks=
option. This is passed straight through to clang-tidy
, so see
its documentation for full details. Wildcards can be used, and checks can
be disabled by prefixing a -
. By default any checks listed are added to
those in .clang-tidy
, so if you'd like to limit the checks to specific
ones you should first exclude all checks then add back what you want, like
--checks=-*,performance*
.
Running clang-tidy
is rather slow - internally it compiles each file and
then runs the checks so it will always be some factor slower than compilation.
While you can use parallel runs to speed it up using the --jobs|-j
option,
clang-tidy
also uses a lot of memory during its checks, so it can easily
run into out-of-memory errors. As such the default number of jobs is one.
Class: ClientRequest
Make HTTP/HTTPS requests.
Process: Main
ClientRequest
implements the Writable Stream
interface and is therefore an EventEmitter.
new ClientRequest(options)
options
(Object | String) - Ifoptions
is a String, it is interpreted as the request URL. If it is an object, it is expected to fully specify an HTTP request via the following properties:method
String (optional) - The HTTP request method. Defaults to the GET method.url
String (optional) - The request URL. Must be provided in the absolute form with the protocol scheme specified as http or https.session
Session (optional) - TheSession
instance with which the request is associated.partition
String (optional) - The name of thepartition
with which the request is associated. Defaults to the empty string. Thesession
option prevails onpartition
. Thus if asession
is explicitly specified,partition
is ignored.useSessionCookies
Boolean (optional) - Whether to send cookies with this request from the provided session. This will make thenet
request's cookie behavior match afetch
request. Default isfalse
.protocol
String (optional) - The protocol scheme in the form 'scheme:'. Currently supported values are 'http:' or 'https:'. Defaults to 'http:'.host
String (optional) - The server host provided as a concatenation of the hostname and the port number 'hostname:port'.hostname
String (optional) - The server host name.port
Integer (optional) - The server's listening port number.path
String (optional) - The path part of the request URL.redirect
String (optional) - The redirect mode for this request. Should be one offollow
,error
ormanual
. Defaults tofollow
. When mode iserror
, any redirection will be aborted. When mode ismanual
the redirection will be cancelled unlessrequest.followRedirect
is invoked synchronously during theredirect
event.
options
properties such as protocol
, host
, hostname
, port
and path
strictly follow the Node.js model as described in the
URL module.
For instance, we could have created the same request to 'github.com' as follows:
const request = net.request({
method: 'GET',
protocol: 'https:',
hostname: 'github.com',
port: 443,
path: '/'
})
Event: 'response'
Returns:
response
IncomingMessage - An object representing the HTTP response message.
Event: 'login'
Returns:
authInfo
ObjectisProxy
Booleanscheme
Stringhost
Stringport
Integerrealm
String
callback
Functionusername
String (optional)password
String (optional)
Emitted when an authenticating proxy is asking for user credentials.
The callback
function is expected to be called back with user credentials:
username
Stringpassword
String
request.on('login', (authInfo, callback) => {
callback('username', 'password')
})
Providing empty credentials will cancel the request and report an authentication error on the response object:
request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`);
response.on('error', (error) => {
console.log(`ERROR: ${JSON.stringify(error)}`)
})
})
request.on('login', (authInfo, callback) => {
callback()
})
Event: 'finish'
Emitted just after the last chunk of the request
's data has been written into
the request
object.
Event: 'abort'
Emitted when the request
is aborted. The abort
event will not be fired if
the request
is already closed.
Event: 'error'
Returns:
error
Error - an error object providing some information about the failure.
Emitted when the net
module fails to issue a network request. Typically when
the request
object emits an error
event, a close
event will subsequently
follow and no response object will be provided.
Event: 'close'
Emitted as the last event in the HTTP request-response transaction. The close
event indicates that no more events will be emitted on either the request
or
response
objects.
Event: 'redirect'
Returns:
statusCode
Integermethod
StringredirectUrl
StringresponseHeaders
Record<String, String[]>
Emitted when the server returns a redirect response (e.g. 301 Moved
Permanently). Calling request.followRedirect
will
continue with the redirection. If this event is handled,
request.followRedirect
must be called
synchronously, otherwise the request will be cancelled.
request.chunkedEncoding
A Boolean
specifying whether the request will use HTTP chunked transfer encoding
or not. Defaults to false. The property is readable and writable, however it can
be set only before the first write operation as the HTTP headers are not yet put
on the wire. Trying to set the chunkedEncoding
property after the first write
will throw an error.
Using chunked encoding is strongly recommended if you need to send a large request body as data will be streamed in small chunks instead of being internally buffered inside Electron process memory.
request.setHeader(name, value)
name
String - An extra HTTP header name.value
String - An extra HTTP header value.
Adds an extra HTTP header. The header name will be issued as-is without
lowercasing. It can be called only before first write. Calling this method after
the first write will throw an error. If the passed value is not a String
, its
toString()
method will be called to obtain the final value.
Certain headers are restricted from being set by apps. These headers are listed below. More information on restricted headers can be found in Chromium's header utils.
Content-Length
Host
Trailer
orTe
Upgrade
Cookie2
Keep-Alive
Transfer-Encoding
Additionally, setting the Connection
header to the value upgrade
is also disallowed.
request.getHeader(name)
name
String - Specify an extra header name.
Returns String
- The value of a previously set extra header name.
request.removeHeader(name)
name
String - Specify an extra header name.
Removes a previously set extra header name. This method can be called only before first write. Trying to call it after the first write will throw an error.
request.write(chunk[, encoding][, callback])
chunk
(String | Buffer) - A chunk of the request body's data. If it is a string, it is converted into a Buffer using the specified encoding.encoding
String (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'.callback
Function (optional) - Called after the write operation ends.
callback
is essentially a dummy function introduced in the purpose of keeping
similarity with the Node.js API. It is called asynchronously in the next tick
after chunk
content have been delivered to the Chromium networking layer.
Contrary to the Node.js implementation, it is not guaranteed that chunk
content have been flushed on the wire before callback
is called.
Adds a chunk of data to the request body. The first write operation may cause the request headers to be issued on the wire. After the first write operation, it is not allowed to add or remove a custom header.
request.end([chunk][, encoding][, callback])
chunk
(String | Buffer) (optional)encoding
String (optional)callback
Function (optional)
Sends the last chunk of the request data. Subsequent write or end operations
will not be allowed. The finish
event is emitted just after the end operation.
request.abort()
Cancels an ongoing HTTP transaction. If the request has already emitted the
close
event, the abort operation will have no effect. Otherwise an ongoing
event will emit abort
and close
events. Additionally, if there is an ongoing
response object,it will emit the aborted
event.
request.followRedirect()
Continues any pending redirection. Can only be called during a 'redirect'
event.
request.getUploadProgress()
Returns Object
:
active
Boolean - Whether the request is currently active. If this is false no other properties will be setstarted
Boolean - Whether the upload has started. If this is false bothcurrent
andtotal
will be set to 0.current
Integer - The number of bytes that have been uploaded so fartotal
Integer - The number of bytes that will be uploaded this request
You can use this method in conjunction with POST
requests to get the progress
of a file upload or other data transfer.
clipboard
Perform copy and paste operations on the system clipboard.
On Linux, there is also a selection
clipboard. To manipulate it
you need to pass selection
to each method:
const { clipboard } = require('electron')
clipboard.writeText('Example String', 'selection')
console.log(clipboard.readText('selection'))
Methods
The clipboard
module has the following methods:
Note: Experimental APIs are marked as such and could be removed in future.
clipboard.readText([type])
type
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Returns String
- The content in the clipboard as plain text.
const { clipboard } = require('electron')
clipboard.writeText('hello i am a bit of text!')
const text = clipboard.readText()
console.log(text)
// hello i am a bit of text!'
clipboard.writeText(text[, type])
text
Stringtype
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Writes the text
into the clipboard as plain text.
const { clipboard } = require('electron')
const text = 'hello i am a bit of text!'
clipboard.writeText(text)
clipboard.readHTML([type])
type
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Returns String
- The content in the clipboard as markup.
const { clipboard } = require('electron')
clipboard.writeHTML('<b>Hi</b>')
const html = clipboard.readHTML()
console.log(html)
// <meta charset='utf-8'><b>Hi</b>
clipboard.writeHTML(markup[, type])
markup
Stringtype
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Writes markup
to the clipboard.
const { clipboard } = require('electron')
clipboard.writeHTML('<b>Hi</b')
clipboard.readImage([type])
type
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Returns NativeImage
- The image content in the clipboard.
clipboard.writeImage(image[, type])
image
NativeImagetype
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Writes image
to the clipboard.
clipboard.readRTF([type])
type
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Returns String
- The content in the clipboard as RTF.
const { clipboard } = require('electron')
clipboard.writeRTF('{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}')
const rtf = clipboard.readRTF()
console.log(rtf)
// {\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}
clipboard.writeRTF(text[, type])
text
Stringtype
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Writes the text
into the clipboard in RTF.
const { clipboard } = require('electron')
const rtf = '{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}'
clipboard.writeRTF(rtf)
clipboard.readBookmark()
macOS Windows
Returns Object
:
title
Stringurl
String
Returns an Object containing title
and url
keys representing the bookmark in
the clipboard. The title
and url
values will be empty strings when the
bookmark is unavailable.
clipboard.writeBookmark(title, url[, type])
macOS Windows
title
Stringurl
Stringtype
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Writes the title
and url
into the clipboard as a bookmark.
Note: Most apps on Windows don't support pasting bookmarks into them so
you can use clipboard.write
to write both a bookmark and fallback text to the
clipboard.
const { clipboard } = require('electron')
clipboard.writeBookmark({
text: 'https://electronjs.org',
bookmark: 'Electron Homepage'
})
clipboard.readFindText()
macOS
Returns String
- The text on the find pasteboard, which is the pasteboard that holds information about the current state of the active application’s find panel.
This method uses synchronous IPC when called from the renderer process. The cached value is reread from the find pasteboard whenever the application is activated.
clipboard.writeFindText(text)
macOS
text
String
Writes the text
into the find pasteboard (the pasteboard that holds information about the current state of the active application’s find panel) as plain text. This method uses synchronous IPC when called from the renderer process.
clipboard.clear([type])
type
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Clears the clipboard content.
clipboard.availableFormats([type])
type
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Returns String[]
- An array of supported formats for the clipboard type
.
const { clipboard } = require('electron')
const formats = clipboard.availableFormats()
console.log(formats)
// [ 'text/plain', 'text/html' ]
clipboard.has(format[, type])
Experimental
format
Stringtype
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Returns Boolean
- Whether the clipboard supports the specified format
.
const { clipboard } = require('electron')
const hasFormat = clipboard.has('<p>selection</p>')
console.log(hasFormat)
// 'true' or 'false
clipboard.read(format)
Experimental
format
String
Returns String
- Reads format
type from the clipboard.
clipboard.readBuffer(format)
Experimental
format
String
Returns Buffer
- Reads format
type from the clipboard.
const { clipboard } = require('electron')
const buffer = Buffer.from('this is binary', 'utf8')
clipboard.writeBuffer('public.utf8-plain-text', buffer)
const ret = clipboard.readBuffer('public.utf8-plain-text')
console.log(buffer.equals(out))
// true
clipboard.writeBuffer(format, buffer[, type])
Experimental
format
Stringbuffer
Buffertype
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Writes the buffer
into the clipboard as format
.
const { clipboard } = require('electron')
const buffer = Buffer.from('writeBuffer', 'utf8')
clipboard.writeBuffer('public.utf8-plain-text', buffer)
clipboard.write(data[, type])
data
Objecttext
String (optional)html
String (optional)image
NativeImage (optional)rtf
String (optional)bookmark
String (optional) - The title of the URL attext
.
type
String (optional) - Can beselection
orclipboard
; default is 'clipboard'.selection
is only available on Linux.
Writes data
to the clipboard.
const { clipboard } = require('electron')
clipboard.write({
text: 'test',
html: '<b>Hi</b>',
rtf: '{\\rtf1\\utf8 text}',
bookmark: 'a title'
})
console.log(clipboard.readText())
// 'test'
console.log(clipboard.readHTML())
// <meta charset='utf-8'><b>Hi</b>
console.log(clipboard.readRTF())
// '{\\rtf1\\utf8 text}'
console.log(clipboard.readBookmark())
// { title: 'a title', url: 'test' }
Code Signing
Code signing is a security technology that you use to certify that an app was created by you.
On macOS the system can detect any change to the app, whether the change is introduced accidentally or by malicious code.
On Windows, the system assigns a trust level to your code signing certificate which if you don't have, or if your trust level is low, will cause security dialogs to appear when users start using your application. Trust level builds over time so it's better to start code signing as early as possible.
While it is possible to distribute unsigned apps, it is not recommended. Both Windows and macOS will, by default, prevent either the download or the execution of unsigned applications. Starting with macOS Catalina (version 10.15), users have to go through multiple manual steps to open unsigned applications.
As you can see, users get two options: Move the app straight to the trash or cancel running it. You don't want your users to see that dialog.
If you are building an Electron app that you intend to package and distribute, it should be code-signed.
Signing & notarizing macOS builds
Properly preparing macOS applications for release requires two steps: First, the app needs to be code-signed. Then, the app needs to be uploaded to Apple for a process called "notarization", where automated systems will further verify that your app isn't doing anything to endanger its users.
To start the process, ensure that you fulfill the requirements for signing and notarizing your app:
- Enroll in the Apple Developer Program (requires an annual fee)
- Download and install Xcode - this requires a computer running macOS
- Generate, download, and install signing certificates
Electron's ecosystem favors configuration and freedom, so there are multiple ways to get your application signed and notarized.
electron-forge
If you're using Electron's favorite build tool, getting your application signed
and notarized requires a few additions to your configuration. Forge is a
collection of the official Electron tools, using electron-packager
,
electron-osx-sign
, and electron-notarize
under the hood.
Let's take a look at an example configuration with all required fields. Not all
of them are required: the tools will be clever enough to automatically find a
suitable identity
, for instance, but we recommend that you are explicit.
{
"name": "my-app",
"version": "0.0.1",
"config": {
"forge": {
"packagerConfig": {
"osxSign": {
"identity": "Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)",
"hardened-runtime": true,
"entitlements": "entitlements.plist",
"entitlements-inherit": "entitlements.plist",
"signature-flags": "library"
},
"osxNotarize": {
"appleId": "felix@felix.fun",
"appleIdPassword": "my-apple-id-password",
}
}
}
}
}
The plist
file referenced here needs the following macOS-specific entitlements
to assure the Apple security mechanisms that your app is doing these things
without meaning any harm:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
</dict>
</plist>
To see all of this in action, check out Electron Fiddle's source code,
especially its electron-forge
configuration
file.
If you plan to access the microphone or camera within your app using Electron's APIs, you'll also need to add the following entitlements:
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
If these are not present in your app's entitlements when you invoke, for example:
const { systemPreferences } = require('electron')
const microphone = systemPreferences.askForMediaAccess('microphone')
Your app may crash. See the Resource Access section in Hardened Runtime for more information and entitlements you may need.
electron-builder
Electron Builder comes with a custom solution for signing your application. You can find its documentation here.
electron-packager
If you're not using an integrated build pipeline like Forge or Builder, you
are likely using electron-packager
, which includes electron-osx-sign
and
electron-notarize
.
If you're using Packager's API, you can pass in configuration that both signs and notarizes your application.
const packager = require('electron-packager')
packager({
dir: '/path/to/my/app',
osxSign: {
identity: 'Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)',
'hardened-runtime': true,
entitlements: 'entitlements.plist',
'entitlements-inherit': 'entitlements.plist',
'signature-flags': 'library'
},
osxNotarize: {
appleId: 'felix@felix.fun',
appleIdPassword: 'my-apple-id-password'
}
})
The plist
file referenced here needs the following macOS-specific entitlements
to assure the Apple security mechanisms that your app is doing these things
without meaning any harm:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
</dict>
</plist>
Mac App Store
See the Mac App Store Guide.
Signing Windows builds
Before signing Windows builds, you must do the following:
- Get a Windows Authenticode code signing certificate (requires an annual fee)
- Install Visual Studio to get the signing utility (the free Community Edition is enough)
You can get a code signing certificate from a lot of resellers. Prices vary, so it may be worth your time to shop around. Popular resellers include:
- digicert
- Sectigo
- GoDaddy
- Amongst others, please shop around to find one that suits your needs, Google is your friend 😄
There are a number of tools for signing your packaged app:
electron-winstaller
will generate an installer for windows and sign it for youelectron-forge
can sign installers it generates through the Squirrel.Windows or MSI targets.electron-builder
can sign some of its windows targets
Windows Store
See the Windows Store Guide.
Coding Style
These are the style guidelines for coding in Electron.
You can run npm run lint
to show any style issues detected by cpplint
and
eslint
.
General Code
- End files with a newline.
- Place requires in the following order:
- Built in Node Modules (such as
path
) - Built in Electron Modules (such as
ipc
,app
) - Local Modules (using relative paths)
- Built in Node Modules (such as
- Place class properties in the following order:
- Class methods and properties (methods starting with a
@
) - Instance methods and properties
- Class methods and properties (methods starting with a
- Avoid platform-dependent code:
- Use
path.join()
to concatenate filenames. - Use
os.tmpdir()
rather than/tmp
when you need to reference the temporary directory.
- Use
- Using a plain
return
when returning explicitly at the end of a function.- Not
return null
,return undefined
,null
orundefined
- Not
C++ and Python
For C++ and Python, we follow Chromium's Coding
Style. You can use
clang-format to format the C++ code automatically. There is
also a script script/cpplint.py
to check whether all files conform.
The Python version we are using now is Python 2.7.
The C++ code uses a lot of Chromium's abstractions and types, so it's recommended to get acquainted with them. A good place to start is Chromium's Important Abstractions and Data Structures document. The document mentions some special types, scoped types (that automatically release their memory when going out of scope), logging mechanisms etc.
Documentation
- Write remark markdown style.
You can run npm run lint-docs
to ensure that your documentation changes are
formatted correctly.
JavaScript
- Write standard JavaScript style.
- File names should be concatenated with
-
instead of_
, e.g.file-name.js
rather thanfile_name.js
, because in github/atom module names are usually in themodule-name
form. This rule only applies to.js
files. - Use newer ES6/ES2015 syntax where appropriate
const
for requires and other constants. If the value is a primitive, use uppercase naming (egconst NUMBER_OF_RETRIES = 5
).let
for defining variables- Arrow functions
instead of
function () { }
- Template literals
instead of string concatenation using
+
Naming Things
Electron APIs uses the same capitalization scheme as Node.js:
- When the module itself is a class like
BrowserWindow
, usePascalCase
. - When the module is a set of APIs, like
globalShortcut
, usecamelCase
. - When the API is a property of object, and it is complex enough to be in a
separate chapter like
win.webContents
, usemixedCase
. - For other non-module APIs, use natural titles, like
<webview> Tag
orProcess Object
.
When creating a new API, it is preferred to use getters and setters instead of
jQuery's one-function style. For example, .getText()
and .setText(text)
are preferred to .text([text])
. There is a
discussion on this.
Class: CommandLine
Manipulate the command line arguments for your app that Chromium reads
Process: Main
The following example shows how to check if the --disable-gpu
flag is set.
const { app } = require('electron')
app.commandLine.hasSwitch('disable-gpu')
For more information on what kinds of flags and switches you can use, check out the Command Line Switches document.
commandLine.appendSwitch(switch[, value])
switch
String - A command-line switch, without the leading--
value
String (optional) - A value for the given switch
Append a switch (with optional value
) to Chromium's command line.
Note: This will not affect process.argv
. The intended usage of this function is to
control Chromium's behavior.
commandLine.appendArgument(value)
value
String - The argument to append to the command line
Append an argument to Chromium's command line. The argument will be quoted correctly. Switches will precede arguments regardless of appending order.
If you're appending an argument like --switch=value
, consider using appendSwitch('switch', 'value')
instead.
Note: This will not affect process.argv
. The intended usage of this function is to
control Chromium's behavior.
commandLine.hasSwitch(switch)
switch
String - A command-line switch
Returns Boolean
- Whether the command-line switch is present.
commandLine.getSwitchValue(switch)
switch
String - A command-line switch
Returns String
- The command-line switch value.
Note: When the switch is not present or has no value, it returns empty string.
Supported Command Line Switches
Command line switches supported by Electron.
You can use app.commandLine.appendSwitch to append them in your app's main script before the ready event of the app module is emitted:
const { app } = require('electron')
app.commandLine.appendSwitch('remote-debugging-port', '8315')
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1')
app.whenReady().then(() => {
// Your code here
})
--auth-server-whitelist=url
A comma-separated list of servers for which integrated authentication is enabled.
For example:
--auth-server-whitelist='*example.com, *foobar.com, *baz'
then any url
ending with example.com
, foobar.com
, baz
will be considered
for integrated authentication. Without *
prefix the URL has to match exactly.
--auth-negotiate-delegate-whitelist=url
A comma-separated list of servers for which delegation of user credentials is required.
Without *
prefix the URL has to match exactly.
--disable-ntlm-v2
Disables NTLM v2 for posix platforms, no effect elsewhere.
--disable-http-cache
Disables the disk cache for HTTP requests.
--disable-http2
Disable HTTP/2 and SPDY/3.1 protocols.
--disable-renderer-backgrounding
Prevents Chromium from lowering the priority of invisible pages' renderer processes.
This flag is global to all renderer processes, if you only want to disable throttling in one window, you can take the hack of playing silent audio.
--disk-cache-size=size
Forces the maximum disk space to be used by the disk cache, in bytes.
--enable-api-filtering-logging
Enables caller stack logging for the following APIs (filtering events):
desktopCapturer.getSources()
/desktop-capturer-get-sources
remote.require()
/remote-require
remote.getGlobal()
/remote-get-builtin
remote.getBuiltin()
/remote-get-global
remote.getCurrentWindow()
/remote-get-current-window
remote.getCurrentWebContents()
/remote-get-current-web-contents
--enable-logging
Prints Chromium's logging into console.
This switch can not be used in app.commandLine.appendSwitch
since it is parsed
earlier than user's app is loaded, but you can set the ELECTRON_ENABLE_LOGGING
environment variable to achieve the same effect.
--host-rules=rules
A comma-separated list of rules
that control how hostnames are mapped.
For example:
MAP * 127.0.0.1
Forces all hostnames to be mapped to 127.0.0.1MAP *.google.com proxy
Forces all google.com subdomains to be resolved to "proxy".MAP test.com [::1]:77
Forces "test.com" to resolve to IPv6 loopback. Will also force the port of the resulting socket address to be 77.MAP * baz, EXCLUDE www.google.com
Remaps everything to "baz", except for "www.google.com".
These mappings apply to the endpoint host in a net request (the TCP connect
and host resolver in a direct connection, and the CONNECT
in an HTTP proxy
connection, and the endpoint host in a SOCKS
proxy connection).
--host-resolver-rules=rules
Like --host-rules
but these rules
only apply to the host resolver.
--ignore-certificate-errors
Ignores certificate related errors.
--ignore-connections-limit=domains
Ignore the connections limit for domains
list separated by ,
.
--js-flags=flags
Specifies the flags passed to the Node.js engine. It has to be passed when starting
Electron if you want to enable the flags
in the main process.
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
See the Node.js documentation or run node --help
in your terminal for a list of available flags. Additionally, run node --v8-options
to see a list of flags that specifically refer to Node.js's V8 JavaScript engine.
--lang
Set a custom locale.
--log-net-log=path
Enables net log events to be saved and writes them to path
.
--no-proxy-server
Don't use a proxy server and always make direct connections. Overrides any other proxy server flags that are passed.
--no-sandbox
Disables Chromium sandbox, which is now enabled by default. Should only be used for testing.
--proxy-bypass-list=hosts
Instructs Electron to bypass the proxy server for the given semi-colon-separated
list of hosts. This flag has an effect only if used in tandem with
--proxy-server
.
For example:
const { app } = require('electron')
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
Will use the proxy server for all hosts except for local addresses (localhost
,
127.0.0.1
etc.), google.com
subdomains, hosts that contain the suffix
foo.com
and anything at 1.2.3.4:5678
.
--proxy-pac-url=url
Uses the PAC script at the specified url
.
--proxy-server=address:port
Use a specified proxy server, which overrides the system setting. This switch only affects requests with HTTP protocol, including HTTPS and WebSocket requests. It is also noteworthy that not all proxy servers support HTTPS and WebSocket requests. The proxy URL does not support username and password authentication per Chromium issue.
--remote-debugging-port=port
Enables remote debugging over HTTP on the specified port
.
--ppapi-flash-path=path
Sets the path
of the pepper flash plugin.
--ppapi-flash-version=version
Sets the version
of the pepper flash plugin.
--v=log_level
Gives the default maximal active V-logging level; 0 is the default. Normally positive values are used for V-logging levels.
This switch only works when --enable-logging
is also passed.
--vmodule=pattern
Gives the per-module maximal V-logging levels to override the value given by
--v
. E.g. my_module=2,foo*=3
would change the logging level for all code in
source files my_module.*
and foo*.*
.
Any pattern containing a forward or backward slash will be tested against the
whole pathname and not only the module. E.g. */foo/bar/*=2
would change the
logging level for all code in the source files under a foo/bar
directory.
This switch only works when --enable-logging
is also passed.
--force_high_performance_gpu
Force using discrete GPU when there are multiple GPUs available.
--force_low_power_gpu
Force using integrated GPU when there are multiple GPUs available.
Node.js Flags
Electron supports some of the CLI flags supported by Node.js.
Note: Passing unsupported command line switches to Electron when it is not running in ELECTRON_RUN_AS_NODE
will have no effect.
--inspect-brk[=[host:]port]
Activate inspector on host:port and break at start of user script. Default host:port is 127.0.0.1:9229.
Aliased to --debug-brk=[host:]port
.
--inspect-port=[host:]port
Set the host:port
to be used when the inspector is activated. Useful when activating the inspector by sending the SIGUSR1 signal. Default host is 127.0.0.1
.
Aliased to --debug-port=[host:]port
.
--inspect[=[host:]port]
Activate inspector on host:port
. Default is 127.0.0.1:9229
.
V8 inspector integration allows tools such as Chrome DevTools and IDEs to debug and profile Electron instances. The tools attach to Electron instances via a TCP port and communicate using the Chrome DevTools Protocol.
See the Debugging the Main Process guide for more details.
Aliased to --debug[=[host:]port
.
--inspect-publish-uid=stderr,http
Specify ways of the inspector web socket url exposure.
By default inspector websocket url is available in stderr and under /json/list endpoint on http://host:port/json/list.
contentTracing
Collect tracing data from Chromium to find performance bottlenecks and slow operations.
Process: Main
This module does not include a web interface. To view recorded traces, use
trace viewer, available at chrome://tracing
in Chrome.
Note: You should not use this module until the ready
event of the app
module is emitted.
const { app, contentTracing } = require('electron')
app.whenReady().then(() => {
(async () => {
await contentTracing.startRecording({
included_categories: ['*']
})
console.log('Tracing started')
await new Promise(resolve => setTimeout(resolve, 5000))
const path = await contentTracing.stopRecording()
console.log('Tracing data recorded to ' + path)
})()
})
Methods
The contentTracing
module has the following methods:
contentTracing.getCategories()
Returns Promise<String[]>
- resolves with an array of category groups once all child processes have acknowledged the getCategories
request
Get a set of category groups. The category groups can change as new code paths are reached. See also the list of built-in tracing categories.
NOTE: Electron adds a non-default tracing category called
"electron"
. This category can be used to capture Electron-specific tracing events.
contentTracing.startRecording(options)
options
(TraceConfig | TraceCategoriesAndOptions)
Returns Promise<void>
- resolved once all child processes have acknowledged the startRecording
request.
Start recording on all processes.
Recording begins immediately locally and asynchronously on child processes as soon as they receive the EnableRecording request.
If a recording is already running, the promise will be immediately resolved, as only one trace operation can be in progress at a time.
contentTracing.stopRecording([resultFilePath])
resultFilePath
String (optional)
Returns Promise<String>
- resolves with a path to a file that contains the traced data once all child processes have acknowledged the stopRecording
request
Stop recording on all processes.
Child processes typically cache trace data and only rarely flush and send trace data back to the main process. This helps to minimize the runtime overhead of tracing since sending trace data over IPC can be an expensive operation. So, to end tracing, Chromium asynchronously asks all child processes to flush any pending trace data.
Trace data will be written into resultFilePath
. If resultFilePath
is empty
or not provided, trace data will be written to a temporary file, and the path
will be returned in the promise.
contentTracing.getTraceBufferUsage()
Returns Promise<Object>
- Resolves with an object containing the value
and percentage
of trace buffer maximum usage
value
Numberpercentage
Number
Get the maximum usage across processes of trace buffer as a percentage of the full state.
contextBridge
Create a safe, bi-directional, synchronous bridge across isolated contexts
Process: Renderer
An example of exposing an API to a renderer from an isolated preload script is given below:
// Preload (Isolated World)
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// Renderer (Main World)
window.electron.doThing()
Main World
The "Main World" is the JavaScript context that your main renderer code runs in. By default, the page you load in your renderer executes code in this world.
Isolated World
When contextIsolation
is enabled in your webPreferences
, your preload
scripts run in an
"Isolated World". You can read more about context isolation and what it affects in the
security docs.
Methods
The contextBridge
module has the following methods:
contextBridge.exposeInMainWorld(apiKey, api)
Experimental
apiKey
String - The key to inject the API ontowindow
with. The API will be accessible onwindow[apiKey]
.api
Record<String, any> - Your API object, more information on what this API can be and how it works is available below.
API Objects
The api
object provided to exposeInMainWorld
must be an object
whose keys are strings and values are a Function
, String
, Number
, Array
, Boolean
, or another nested object that meets the same conditions.
Function
values are proxied to the other context and all other values are copied and frozen. Any data / primitives sent in
the API object become immutable and updates on either side of the bridge do not result in an update on the other side.
An example of a complex API object is shown below:
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing'),
myPromises: [Promise.resolve(), Promise.reject(new Error('whoops'))],
anAsyncFunction: async () => 123,
data: {
myFlags: ['a', 'b', 'c'],
bootTime: 1234
},
nestedAPI: {
evenDeeper: {
youCanDoThisAsMuchAsYouWant: {
fn: () => ({
returnData: 123
})
}
}
}
}
)
API Functions
Function
values that you bind through the contextBridge
are proxied through Electron to ensure that contexts remain isolated. This
results in some key limitations that we've outlined below.
Parameter / Error / Return Type support
Because parameters, errors and return values are copied when they are sent over the bridge, there are only certain types that can be used. At a high level, if the type you want to use can be serialized and deserialized into the same object it will work. A table of type support has been included below for completeness:
Type | Complexity | Parameter Support | Return Value Support | Limitations |
---|---|---|---|---|
String | Simple | ✅ | ✅ | N/A |
Number | Simple | ✅ | ✅ | N/A |
Boolean | Simple | ✅ | ✅ | N/A |
Object | Complex | ✅ | ✅ | Keys must be supported using only "Simple" types in this table. Values must be supported in this table. Prototype modifications are dropped. Sending custom classes will copy values but not the prototype. |
Array | Complex | ✅ | ✅ | Same limitations as the Object type |
Error | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context |
Promise | Complex | ✅ | ✅ | Promises are only proxied if they are the return value or exact parameter. Promises nested in arrays or objects will be dropped. |
Function | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
Cloneable Types | Simple | ✅ | ✅ | See the linked document on cloneable types |
Symbol | N/A | ❌ | ❌ | Symbols cannot be copied across contexts so they are dropped |
If the type you care about is not in the above table, it is probably not supported.
What is it?
Context Isolation is a feature that ensures that both your preload
scripts and Electron's internal logic run in a separate context to the website you load in a webContents
. This is important for security purposes as it helps prevent the website from accessing Electron internals or the powerful APIs your preload script has access to.
This means that the window
object that your preload script has access to is actually a different object than the website would have access to. For example, if you set window.hello = 'wave'
in your preload script and context isolation is enabled window.hello
will be undefined if the website tries to access it.
Every single application should have context isolation enabled and from Electron 12 it will be enabled by default.
How do I enable it?
From Electron 12, it will be enabled by default. For lower versions it is an option in the webPreferences
option when constructing new BrowserWindow
's.
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true
}
})
Migration
I used to provide APIs from my preload script using
window.X = apiObject
now what?
Exposing APIs from your preload script to the loaded website is a common usecase and there is a dedicated module in Electron to help you do this in a painless way.
Before: With context isolation disabled
window.myAPI = {
doAThing: () => {}
}
After: With context isolation enabled
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
doAThing: () => {}
})
The contextBridge
module can be used to safely expose APIs from the isolated context your preload script runs in to the context the website is running in. The API will also be accessible from the website on window.myAPI
just like it was before.
You should read the contextBridge
documentation linked above to fully understand its limitations. For instance you can't send custom prototypes or symbols over the bridge.
Security Considerations
Just enabling contextIsolation
and using contextBridge
does not automatically mean that everything you do is safe. For instance this code is unsafe.
// ❌ Bad code
contextBridge.exposeInMainWorld('myAPI', {
send: ipcRenderer.send
})
It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.
// ✅ Good code
contextBridge.exposeInMainWorld('myAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})
Cookie Object
name
String - The name of the cookie.value
String - The value of the cookie.domain
String (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains.hostOnly
Boolean (optional) - Whether the cookie is a host-only cookie; this will only betrue
if no domain was passed.path
String (optional) - The path of the cookie.secure
Boolean (optional) - Whether the cookie is marked as secure.httpOnly
Boolean (optional) - Whether the cookie is marked as HTTP only.session
Boolean (optional) - Whether the cookie is a session cookie or a persistent cookie with an expiration date.expirationDate
Double (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch. Not provided for session cookies.sameSite
String - The Same Site policy applied to this cookie. Can beunspecified
,no_restriction
,lax
orstrict
.
Class: Cookies
Query and modify a session's cookies.
Process: Main
Instances of the Cookies
class are accessed by using cookies
property of
a Session
.
For example:
const { session } = require('electron')
// Query all cookies.
session.defaultSession.cookies.get({})
.then((cookies) => {
console.log(cookies)
}).catch((error) => {
console.log(error)
})
// Query all cookies associated with a specific url.
session.defaultSession.cookies.get({ url: 'http://www.github.com' })
.then((cookies) => {
console.log(cookies)
}).catch((error) => {
console.log(error)
})
// Set a cookie with the given cookie data;
// may overwrite equivalent cookies if they exist.
const cookie = { url: 'http://www.github.com', name: 'dummy_name', value: 'dummy' }
session.defaultSession.cookies.set(cookie)
.then(() => {
// success
}, (error) => {
console.error(error)
})
Instance Events
The following events are available on instances of Cookies
:
Event: 'changed'
event
Eventcookie
Cookie - The cookie that was changed.cause
String - The cause of the change with one of the following values:explicit
- The cookie was changed directly by a consumer's action.overwrite
- The cookie was automatically removed due to an insert operation that overwrote it.expired
- The cookie was automatically removed as it expired.evicted
- The cookie was automatically evicted during garbage collection.expired-overwrite
- The cookie was overwritten with an already-expired expiration date.
removed
Boolean -true
if the cookie was removed,false
otherwise.
Emitted when a cookie is changed because it was added, edited, removed, or expired.
Instance Methods
The following methods are available on instances of Cookies
:
cookies.get(filter)
filter
Objecturl
String (optional) - Retrieves cookies which are associated withurl
. Empty implies retrieving cookies of all URLs.name
String (optional) - Filters cookies by name.domain
String (optional) - Retrieves cookies whose domains match or are subdomains ofdomains
.path
String (optional) - Retrieves cookies whose path matchespath
.secure
Boolean (optional) - Filters cookies by their Secure property.session
Boolean (optional) - Filters out session or persistent cookies.
Returns Promise<Cookie[]>
- A promise which resolves an array of cookie objects.
Sends a request to get all cookies matching filter
, and resolves a promise with
the response.
cookies.set(details)
details
Objecturl
String - The URL to associate the cookie with. The promise will be rejected if the URL is invalid.name
String (optional) - The name of the cookie. Empty by default if omitted.value
String (optional) - The value of the cookie. Empty by default if omitted.domain
String (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains. Empty by default if omitted.path
String (optional) - The path of the cookie. Empty by default if omitted.secure
Boolean (optional) - Whether the cookie should be marked as Secure. Defaults to false.httpOnly
Boolean (optional) - Whether the cookie should be marked as HTTP only. Defaults to false.expirationDate
Double (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch. If omitted then the cookie becomes a session cookie and will not be retained between sessions.sameSite
String (optional) - The Same Site policy to apply to this cookie. Can beunspecified
,no_restriction
,lax
orstrict
. Default isno_restriction
.
Returns Promise<void>
- A promise which resolves when the cookie has been set
Sets a cookie with details
.
cookies.remove(url, name)
url
String - The URL associated with the cookie.name
String - The name of cookie to remove.
Returns Promise<void>
- A promise which resolves when the cookie has been removed
Removes the cookies matching url
and name
cookies.flushStore()
Returns Promise<void>
- A promise which resolves when the cookie store has been flushed
Writes any unwritten cookies data to disk.
CPUUsage Object
percentCPUUsage
Number - Percentage of CPU used since the last call to getCPUUsage. First call returns 0.idleWakeupsPerSecond
Number - The number of average idle CPU wakeups per second since the last call to getCPUUsage. First call returns 0. Will always return 0 on Windows.
CrashReport Object
date
Dateid
String
crashReporter
Submit crash reports to a remote server.
The following is an example of setting up Electron to automatically submit crash reports to a remote server:
const { crashReporter } = require('electron')
crashReporter.start({ submitURL: 'https://your-domain.com/url-to-submit' })
For setting up a server to accept and process crash reports, you can use following projects:
Or use a 3rd party hosted solution:
Crash reports are stored temporarily before being uploaded in a directory
underneath the app's user data directory (called 'Crashpad' on Windows and Mac,
or 'Crash Reports' on Linux). You can override this directory by calling
app.setPath('crashDumps', '/path/to/crashes')
before starting the crash
reporter.
On Windows and macOS, Electron uses crashpad to monitor and report crashes. On Linux, Electron uses breakpad. This is an implementation detail driven by Chromium, and it may change in future. In particular, crashpad is newer and will likely eventually replace breakpad on all platforms.
Methods
The crashReporter
module has the following methods:
crashReporter.start(options)
options
ObjectsubmitURL
String - URL that crash reports will be sent to as POST.productName
String (optional) - Defaults toapp.name
.companyName
String (optional) Deprecated - Deprecated alias for{ globalExtra: { _companyName: ... } }
.uploadToServer
Boolean (optional) - Whether crash reports should be sent to the server. If false, crash reports will be collected and stored in the crashes directory, but not uploaded. Default istrue
.ignoreSystemCrashHandler
Boolean (optional) - If true, crashes generated in the main process will not be forwarded to the system crash handler. Default isfalse
.rateLimit
Boolean (optional) macOS Windows - If true, limit the number of crashes uploaded to 1/hour. Default isfalse
.compress
Boolean (optional) - If true, crash reports will be compressed and uploaded withContent-Encoding: gzip
. Default isfalse
.extra
Record<String, String> (optional) - Extra string key/value annotations that will be sent along with crash reports that are generated in the main process. Only string values are supported. Crashes generated in child processes will not contain these extra parameters to crash reports generated from child processes, calladdExtraParameter
from the child process.globalExtra
Record<String, String> (optional) - Extra string key/value annotations that will be sent along with any crash reports generated in any process. These annotations cannot be changed once the crash reporter has been started. If a key is present in both the global extra parameters and the process-specific extra parameters, then the global one will take precedence. By default,productName
and the app version are included, as well as the Electron version.
This method must be called before using any other crashReporter
APIs. Once
initialized this way, the crashpad handler collects crashes from all
subsequently created processes. The crash reporter cannot be disabled once
started.
This method should be called as early as possible in app startup, preferably
before app.on('ready')
. If the crash reporter is not initialized at the time
a renderer process is created, then that renderer process will not be monitored
by the crash reporter.
Note: You can test out the crash reporter by generating a crash using
process.crash()
.
Note: If you need to send additional/updated extra
parameters after your
first call start
you can call addExtraParameter
.
Note: Parameters passed in extra
, globalExtra
or set with
addExtraParameter
have limits on the length of the keys and values. Key names
must be at most 39 bytes long, and values must be no longer than 127 bytes.
Keys with names longer than the maximum will be silently ignored. Key values
longer than the maximum length will be truncated.
Note: Calling this method from the renderer process is deprecated.
crashReporter.getLastCrashReport()
Returns CrashReport
- The date and ID of the
last crash report. Only crash reports that have been uploaded will be returned;
even if a crash report is present on disk it will not be returned until it is
uploaded. In the case that there are no uploaded reports, null
is returned.
Note: Calling this method from the renderer process is deprecated.
crashReporter.getUploadedReports()
Returns CrashReport[]
:
Returns all uploaded crash reports. Each report contains the date and uploaded ID.
Note: Calling this method from the renderer process is deprecated.
crashReporter.getUploadToServer()
Returns Boolean
- Whether reports should be submitted to the server. Set through
the start
method or setUploadToServer
.
Note: Calling this method from the renderer process is deprecated.
crashReporter.setUploadToServer(uploadToServer)
uploadToServer
Boolean - Whether reports should be submitted to the server.
This would normally be controlled by user preferences. This has no effect if
called before start
is called.
Note: Calling this method from the renderer process is deprecated.
crashReporter.getCrashesDirectory()
Deprecated
Returns String
- The directory where crashes are temporarily stored before being uploaded.
Note: This method is deprecated, use app.getPath('crashDumps')
instead.
crashReporter.addExtraParameter(key, value)
key
String - Parameter key, must be no longer than 39 bytes.value
String - Parameter value, must be no longer than 127 bytes.
Set an extra parameter to be sent with the crash report. The values specified
here will be sent in addition to any values set via the extra
option when
start
was called.
Parameters added in this fashion (or via the extra
parameter to
crashReporter.start
) are specific to the calling process. Adding extra
parameters in the main process will not cause those parameters to be sent along
with crashes from renderer or other child processes. Similarly, adding extra
parameters in a renderer process will not result in those parameters being sent
with crashes that occur in other renderer processes or in the main process.
Note: Parameters have limits on the length of the keys and values. Key names must be no longer than 39 bytes, and values must be no longer than 20320 bytes. Keys with names longer than the maximum will be silently ignored. Key values longer than the maximum length will be truncated.
Note: On linux values that are longer than 127 bytes will be chunked into
multiple keys, each 127 bytes in length. E.g. addExtraParameter('foo', 'a'.repeat(130))
will result in two chunked keys foo__1
and foo__2
, the first will contain
the first 127 bytes and the second will contain the remaining 3 bytes. On
your crash reporting backend you should stitch together keys in this format.
crashReporter.removeExtraParameter(key)
key
String - Parameter key, must be no longer than 39 bytes.
Remove an extra parameter from the current set of parameters. Future crashes will not include this parameter.
crashReporter.getParameters()
Returns Record<String, String>
- The current 'extra' parameters of the crash reporter.
Crash Report Payload
The crash reporter will send the following data to the submitURL
as
a multipart/form-data
POST
:
ver
String - The version of Electron.platform
String - e.g. 'win32'.process_type
String - e.g. 'renderer'.guid
String - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72'._version
String - The version inpackage.json
._productName
String - The product name in thecrashReporter
options
object.prod
String - Name of the underlying product. In this case Electron._companyName
String - The company name in thecrashReporter
options
object.upload_file_minidump
File - The crash report in the format ofminidump
.- All level one properties of the
extra
object in thecrashReporter
options
object.
CustomScheme Object
scheme
String - Custom schemes to be registered with options.privileges
Object (optional)standard
Boolean (optional) - Default false.secure
Boolean (optional) - Default false.bypassCSP
Boolean (optional) - Default false.allowServiceWorkers
Boolean (optional) - Default false.supportFetchAPI
Boolean (optional) - Default false.corsEnabled
Boolean (optional) - Default false.stream
Boolean (optional) - Default false.
Automatically update the native interfaces
"Native interfaces" include the file picker, window border, dialogs, context menus, and more - anything where the UI comes from your operating system and not from your app. The default behavior is to opt into this automatic theming from the OS.
Automatically update your own interfaces
If your app has its own dark mode, you should toggle it on and off in sync with the system's dark mode setting. You can do this by using the prefer-color-scheme CSS media query.
Manually update your own interfaces
If you want to manually switch between light/dark modes, you can do this by
setting the desired mode in the
themeSource
property of the nativeTheme
module. This property's value will be propagated
to your Renderer process. Any CSS rules related to prefers-color-scheme
will
be updated accordingly.
macOS settings
In macOS 10.14 Mojave, Apple introduced a new system-wide dark mode
for all macOS computers. If your Electron app has a dark mode, you can make it
follow the system-wide dark mode setting using
the nativeTheme
api.
In macOS 10.15 Catalina, Apple introduced a new "automatic" dark mode option
for all macOS computers. In order for the nativeTheme.shouldUseDarkColors
and
Tray
APIs to work correctly in this mode on Catalina, you need to use Electron
>=7.0.0
, or set NSRequiresAquaSystemAppearance
to false
in your
Info.plist
file for older versions. Both Electron Packager
and Electron Forge have a
darwinDarkModeSupport
option
to automate the Info.plist
changes during app build time.
If you wish to opt-out while using Electron > 8.0.0, you must
set the NSRequiresAquaSystemAppearance
key in the Info.plist
file to
true
. Please note that Electron 8.0.0 and above will not let you opt-out
of this theming, due to the use of the macOS 10.14 SDK.
Example
We'll start with a working application from the Quick Start Guide and add functionality gradually.
First, let's edit our interface so users can toggle between light and dark
modes. This basic UI contains buttons to change the nativeTheme.themeSource
setting and a text element indicating which themeSource
value is selected.
By default, Electron follows the system's dark mode preference, so we
will hardcode the theme source as "System".
Add the following lines to the index.html
file:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Current theme source: <strong id="theme-source">System</strong></p>
<button id="toggle-dark-mode">Toggle Dark Mode</button>
<button id="reset-to-system">Reset to System Theme</button>
<script src="renderer.js"></script>
</body>
</body>
</html>
Next, add event listeners
that listen for click
events on the toggle buttons. Because the nativeTheme
module only exposed in the Main process, you need to set up each listener's
callback to use IPC to send messages to and handle responses from the Main
process:
- when the "Toggle Dark Mode" button is clicked, we send the
dark-mode:toggle
message (event) to tell the Main process to trigger a theme change, and update the "Current Theme Source" label in the UI based on the response from the Main process. - when the "Reset to System Theme" button is clicked, we send the
dark-mode:system
message (event) to tell the Main process to use the system color scheme, and update the "Current Theme Source" label toSystem
.
To add listeners and handlers, add the following lines to the renderer.js
file:
const { ipcRenderer } = require('electron')
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
const isDarkMode = await ipcRenderer.invoke('dark-mode:toggle')
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
})
document.getElementById('reset-to-system').addEventListener('click', async () => {
await ipcRenderer.invoke('dark-mode:system')
document.getElementById('theme-source').innerHTML = 'System'
})
If you run your code at this point, you'll see that your buttons don't do
anything just yet, and your Main process will output an error like this when
you click on your buttons:
Error occurred in handler for 'dark-mode:toggle': No handler registered for 'dark-mode:toggle'
This is expected — we haven't actually touched any nativeTheme
code yet.
Now that we're done wiring the IPC from the Renderer's side, the next step
is to update the main.js
file to handle events from the Renderer process.
Depending on the received event, we update the
nativeTheme.themeSource
property to apply the desired theme on the system's native UI elements
(e.g. context menus) and propagate the preferred color scheme to the Renderer
process:
- Upon receiving
dark-mode:toggle
, we check if the dark theme is currently active using thenativeTheme.shouldUseDarkColors
property, and set thethemeSource
to the opposite theme. - Upon receiving
dark-mode:system
, we reset thethemeSource
tosystem
.
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
ipcMain.handle('dark-mode:toggle', () => {
if (nativeTheme.shouldUseDarkColors) {
nativeTheme.themeSource = 'light'
} else {
nativeTheme.themeSource = 'dark'
}
return nativeTheme.shouldUseDarkColors
})
ipcMain.handle('dark-mode:system', () => {
nativeTheme.themeSouce = 'system'
})
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
The final step is to add a bit of styling to enable dark mode for the web parts
of the UI by leveraging the prefers-color-scheme
CSS
attribute. The value of prefers-color-scheme
will follow your
nativeTheme.themeSource
setting.
Create a styles.css
file and add the following lines:
@media (prefers-color-scheme: dark) {
body { background: #333; color: white; }
}
@media (prefers-color-scheme: light) {
body { background: #ddd; color: black; }
}
After launching the Electron application, you can change modes or reset the theme to system default by clicking corresponding buttons:
Debugging on Windows
If you experience crashes or issues in Electron that you believe are not caused by your JavaScript application, but instead by Electron itself, debugging can be a little bit tricky, especially for developers not used to native/C++ debugging. However, using Visual Studio, Electron's hosted Symbol Server, and the Electron source code, you can enable step-through debugging with breakpoints inside Electron's source code.
See also: There's a wealth of information on debugging Chromium, much of which also applies to Electron, on the Chromium developers site: Debugging Chromium on Windows.
Requirements
-
A debug build of Electron: The easiest way is usually building it yourself, using the tools and prerequisites listed in the build instructions for Windows. While you can attach to and debug Electron as you can download it directly, you will find that it is heavily optimized, making debugging substantially more difficult: The debugger will not be able to show you the content of all variables and the execution path can seem strange because of inlining, tail calls, and other compiler optimizations.
-
Visual Studio with C++ Tools: The free community editions of Visual Studio 2013 and Visual Studio 2015 both work. Once installed, configure Visual Studio to use Electron's Symbol server. It will enable Visual Studio to gain a better understanding of what happens inside Electron, making it easier to present variables in a human-readable format.
-
ProcMon: The free SysInternals tool allows you to inspect a processes parameters, file handles, and registry operations.
Attaching to and Debugging Electron
To start a debugging session, open up PowerShell/CMD and execute your debug build of Electron, using the application to open as a parameter.
$ ./out/Testing/electron.exe ~/my-electron-app/
Setting Breakpoints
Then, open up Visual Studio. Electron is not built with Visual Studio and hence does not contain a project file - you can however open up the source code files "As File", meaning that Visual Studio will open them up by themselves. You can still set breakpoints - Visual Studio will automatically figure out that the source code matches the code running in the attached process and break accordingly.
Relevant code files can be found in ./shell/
.
Attaching
You can attach the Visual Studio debugger to a running process on a local or
remote computer. After the process is running, click Debug / Attach to Process
(or press CTRL+ALT+P
) to open the "Attach to Process" dialog box. You can use
this capability to debug apps that are running on a local or remote computer,
debug multiple processes simultaneously.
If Electron is running under a different user account, select the
Show processes from all users
check box. Notice that depending on how many
BrowserWindows your app opened, you will see multiple processes. A typical
one-window app will result in Visual Studio presenting you with two
Electron.exe
entries - one for the main process and one for the renderer
process. Since the list only gives you names, there's currently no reliable
way of figuring out which is which.
Which Process Should I Attach to?
Code executed within the main process (that is, code found in or eventually run by your main JavaScript file) will run inside the main process, while other code will execute inside its respective renderer process.
You can be attached to multiple programs when you are debugging, but only one
program is active in the debugger at any time. You can set the active program
in the Debug Location
toolbar or the Processes window
.
Using ProcMon to Observe a Process
While Visual Studio is fantastic for inspecting specific code paths, ProcMon's strength is really in observing everything your application is doing with the operating system - it captures File, Registry, Network, Process, and Profiling details of processes. It attempts to log all events occurring and can be quite overwhelming, but if you seek to understand what and how your application is doing to the operating system, it can be a valuable resource.
For an introduction to ProcMon's basic and advanced debugging features, go check out this video tutorial provided by Microsoft.
Class: Debugger
An alternate transport for Chrome's remote debugging protocol.
Process: Main
Chrome Developer Tools has a special binding available at JavaScript runtime that allows interacting with pages and instrumenting them.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
try {
win.webContents.debugger.attach('1.1')
} catch (err) {
console.log('Debugger attach failed : ', err)
}
win.webContents.debugger.on('detach', (event, reason) => {
console.log('Debugger detached due to : ', reason)
})
win.webContents.debugger.on('message', (event, method, params) => {
if (method === 'Network.requestWillBeSent') {
if (params.request.url === 'https://www.github.com') {
win.webContents.debugger.detach()
}
}
})
win.webContents.debugger.sendCommand('Network.enable')
Event: 'detach'
Returns:
event
Eventreason
String - Reason for detaching debugger.
Emitted when the debugging session is terminated. This happens either when
webContents
is closed or devtools is invoked for the attached webContents
.
Event: 'message'
Returns:
event
Eventmethod
String - Method name.params
any - Event parameters defined by the 'parameters' attribute in the remote debugging protocol.sessionId
String - Unique identifier of attached debugging session, will match the value sent fromdebugger.sendCommand
.
Emitted whenever the debugging target issues an instrumentation event.
debugger.attach([protocolVersion])
protocolVersion
String (optional) - Requested debugging protocol version.
Attaches the debugger to the webContents
.
debugger.isAttached()
Returns Boolean
- Whether a debugger is attached to the webContents
.
debugger.detach()
Detaches the debugger from the webContents
.
debugger.sendCommand(method[, commandParams, sessionId])
method
String - Method name, should be one of the methods defined by the remote debugging protocol.commandParams
any (optional) - JSON object with request parameters.sessionId
String (optional) - send command to the target with associated debugging session id. The initial value can be obtained by sending Target.attachToTarget message.
Returns Promise<any>
- A promise that resolves with the response defined by
the 'returns' attribute of the command description in the remote debugging protocol
or is rejected indicating the failure of the command.
Send given command to the debugging target.
Debugging on macOS
If you experience crashes or issues in Electron that you believe are not caused by your JavaScript application, but instead by Electron itself, debugging can be a little bit tricky, especially for developers not used to native/C++ debugging. However, using lldb, and the Electron source code, you can enable step-through debugging with breakpoints inside Electron's source code. You can also use XCode for debugging if you prefer a graphical interface.
Requirements
-
A debug build of Electron: The easiest way is usually building it yourself, using the tools and prerequisites listed in the build instructions for macOS. While you can attach to and debug Electron as you can download it directly, you will find that it is heavily optimized, making debugging substantially more difficult: The debugger will not be able to show you the content of all variables and the execution path can seem strange because of inlining, tail calls, and other compiler optimizations.
-
Xcode: In addition to Xcode, also install the Xcode command line tools. They include LLDB, the default debugger in Xcode on macOS. It supports debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.
-
.lldbinit: Create or edit
~/.lldbinit
to allow Chromium code to be properly source-mapped.command script import ~/electron/src/tools/lldb/lldbinit.py
Attaching to and Debugging Electron
To start a debugging session, open up Terminal and start lldb
, passing a non-release
build of Electron as a parameter.
$ lldb ./out/Testing/Electron.app
(lldb) target create "./out/Testing/Electron.app"
Current executable set to './out/Testing/Electron.app' (x86_64).
Setting Breakpoints
LLDB is a powerful tool and supports multiple strategies for code inspection. For this basic introduction, let's assume that you're calling a command from JavaScript that isn't behaving correctly - so you'd like to break on that command's C++ counterpart inside the Electron source.
Relevant code files can be found in ./shell/
.
Let's assume that you want to debug app.setName()
, which is defined in browser.cc
as Browser::SetName()
. Set the breakpoint using the breakpoint
command, specifying
file and line to break on:
(lldb) breakpoint set --file browser.cc --line 117
Breakpoint 1: where = Electron Framework`atom::Browser::SetName(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 20 at browser.cc:118, address = 0x000000000015fdb4
Then, start Electron:
(lldb) run
The app will immediately be paused, since Electron sets the app's name on launch:
(lldb) run
Process 25244 launched: '/Users/fr/Code/electron/out/Testing/Electron.app/Contents/MacOS/Electron' (x86_64)
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118
115 }
116
117 void Browser::SetName(const std::string& name) {
-> 118 name_override_ = name;
119 }
120
121 int Browser::GetBadgeCount() {
(lldb)
To show the arguments and local variables for the current frame, run frame variable
(or fr v
),
which will show you that the app is currently setting the name to "Electron".
(lldb) frame variable
(atom::Browser *) this = 0x0000000108b14f20
(const string &) name = "Electron": {
[...]
}
To do a source level single step in the currently selected thread, execute step
(or s
).
This would take you into name_override_.empty()
. To proceed and do a step over,
run next
(or n
).
(lldb) step
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119, queue = 'com.apple.main-thread', stop reason = step in
frame #0: 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119
116
117 void Browser::SetName(const std::string& name) {
118 name_override_ = name;
-> 119 }
120
121 int Browser::GetBadgeCount() {
122 return badge_count_;
NOTE: If you don't see source code when you think you should, you may not have added the ~/.lldbinit
file above.
To finish debugging at this point, run process continue
. You can also continue until a certain
line is hit in this thread (thread until 100
). This command will run the thread in the current
frame till it reaches line 100 in this frame or stops if it leaves the current frame.
Now, if you open up Electron's developer tools and call setName
, you will once again hit the
breakpoint.
Further Reading
LLDB is a powerful tool with a great documentation. To learn more about it, consider Apple's debugging documentation, for instance the LLDB Command Structure Reference or the introduction to Using LLDB as a Standalone Debugger.
You can also check out LLDB's fantastic manual and tutorial, which will explain more complex debugging scenarios.
Generate xcode project for debugging sources (cannot build code from xcode)
Run gn gen
with the --ide=xcode argument.
$ gn gen out/Testing --ide=xcode
This will generate the electron.ninja.xcworkspace. You will have to open this workspace to set breakpoints and inspect.
See gn help gen
for more information on generating IDE projects with GN.
Debugging and breakpoints
Launch Electron app after build. You can now open the xcode workspace created above and attach to the Electron process through the Debug > Attach To Process > Electron debug menu. [Note: If you want to debug the renderer process, you need to attach to the Electron Helper as well.]
You can now set breakpoints in any of the indexed files. However, you will not be able to set breakpoints directly in the Chromium source. To set break points in the Chromium source, you can choose Debug > Breakpoints > Create Symbolic Breakpoint and set any function name as the symbol. This will set the breakpoint for all functions with that name, from all the classes if there are more than one. You can also do this step of setting break points prior to attaching the debugger, however, actual breakpoints for symbolic breakpoint functions may not show up until the debugger is attached to the app.
Debugging the Main Process
The DevTools in an Electron browser window can only debug JavaScript that's
executed in that window (i.e. the web pages). To debug JavaScript that's
executed in the main process you will need to use an external debugger and
launch Electron with the --inspect
or --inspect-brk
switch.
Command Line Switches
Use one of the following command line switches to enable debugging of the main process:
--inspect=[port]
Electron will listen for V8 inspector protocol messages on the specified port
,
an external debugger will need to connect on this port. The default port
is
5858
.
electron --inspect=5858 your/app
--inspect-brk=[port]
Like --inspect
but pauses execution on the first line of JavaScript.
External Debuggers
You will need to use a debugger that supports the V8 inspector protocol.
- Connect Chrome by visiting
chrome://inspect
and selecting to inspect the launched Electron app present there. - Debugging in VSCode
Debugging in VSCode
This guide goes over how to set up VSCode debugging for both your own Electron project as well as the native Electron codebase.
1. Open an Electron project in VSCode.
$ git clone git@github.com:electron/electron-quick-start.git
$ code electron-quick-start
2. Add a file .vscode/launch.json
with the following configuration:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Main Process",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
},
"args" : ["."],
"outputCapture": "std"
}
]
}
3. Debugging
Set some breakpoints in main.js
, and start debugging in the Debug View. You should be able to hit the breakpoints.
Here is a pre-configured project that you can download and directly debug in VSCode: https://github.com/octref/vscode-electron-debug/tree/master/electron-quick-start
Debugging the Electron codebase
If you want to build Electron from source and modify the native Electron codebase, this section will help you in testing your modifications.
For those unsure where to acquire this code or how to build it, Electron's Build Tools automates and explains most of this process. If you wish to manually set up the environment, you can instead use these build instructions.
1. Open an Electron project in VSCode.
$ git clone git@github.com:electron/electron-quick-start.git
$ code electron-quick-start
2. Add a file .vscode/launch.json
with the following configuration:
{
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) Launch",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}\\out\\your-executable-location\\electron.exe",
"args": ["your-electron-project-path"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{"name": "ELECTRON_ENABLE_LOGGING", "value": "true"},
{"name": "ELECTRON_ENABLE_STACK_DUMPING", "value": "true"},
{"name": "ELECTRON_RUN_AS_NODE", "value": ""},
],
"externalConsole": false,
"sourceFileMap": {
"o:\\": "${workspaceFolder}",
},
},
]
}
Configuration Notes
cppvsdbg
requires the built-in C/C++ extension be enabled.${workspaceFolder}
is the full path to Chromium'ssrc
directory.your-executable-location
will be one of the following depending on a few items:Testing
: If you are using the default settings of Electron's Build-Tools or the default instructions when building from source.Release
: If you built a Release build rather than a Testing build.your-directory-name
: If you modified this during your build process from the default, this will be whatever you specified.
- The
args
array string"your-electron-project-path"
should be the absolute path to either the directory ormain.js
file of the Electron project you are using for testing. In this example, it should be your path toelectron-quick-start
.
3. Debugging
Set some breakpoints in the .cc files of your choosing in the native Electron C++ code, and start debugging in the Debug View.
desktopCapturer
Access information about media sources that can be used to capture audio and video from the desktop using the
navigator.mediaDevices.getUserMedia
API.
The following example shows how to capture video from a desktop window whose
title is Electron
:
// In the renderer process.
const { desktopCapturer } = require('electron')
desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => {
for (const source of sources) {
if (source.name === 'Electron') {
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: source.id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
}
}
})
handleStream(stream)
} catch (e) {
handleError(e)
}
return
}
}
})
function handleStream (stream) {
const video = document.querySelector('video')
video.srcObject = stream
video.onloadedmetadata = (e) => video.play()
}
function handleError (e) {
console.log(e)
}
To capture video from a source provided by desktopCapturer
the constraints
passed to navigator.mediaDevices.getUserMedia
must include
chromeMediaSource: 'desktop'
, and audio: false
.
To capture both audio and video from the entire desktop the constraints passed
to navigator.mediaDevices.getUserMedia
must include chromeMediaSource: 'desktop'
,
for both audio
and video
, but should not include a chromeMediaSourceId
constraint.
const constraints = {
audio: {
mandatory: {
chromeMediaSource: 'desktop'
}
},
video: {
mandatory: {
chromeMediaSource: 'desktop'
}
}
}
Methods
The desktopCapturer
module has the following methods:
desktopCapturer.getSources(options)
options
Objecttypes
String[] - An array of Strings that lists the types of desktop sources to be captured, available types arescreen
andwindow
.thumbnailSize
Size (optional) - The size that the media source thumbnail should be scaled to. Default is150
x150
. Set width or height to 0 when you do not need the thumbnails. This will save the processing time required for capturing the content of each window and screen.fetchWindowIcons
Boolean (optional) - Set to true to enable fetching window icons. The default value is false. When false the appIcon property of the sources return null. Same if a source has the type screen.
Returns Promise<DesktopCapturerSource[]>
- Resolves with an array of DesktopCapturerSource
objects, each DesktopCapturerSource
represents a screen or an individual window that can be captured.
Note Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher,
which can detected by systemPreferences.getMediaAccessStatus
.
Caveats
navigator.mediaDevices.getUserMedia
does not work on macOS for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a signed kernel extension. Chromium, and by extension Electron, does not provide this.
It is possible to circumvent this limitation by capturing system audio with another macOS app like Soundflower and passing it through a virtual audio input device. This virtual device can then be queried with navigator.mediaDevices.getUserMedia
.
DesktopCapturerSource Object
id
String - The identifier of a window or screen that can be used as achromeMediaSourceId
constraint when calling [navigator.webkitGetUserMedia
]. The format of the identifier will bewindow:XX
orscreen:XX
, whereXX
is a random generated number.name
String - A screen source will be named eitherEntire Screen
orScreen <index>
, while the name of a window source will match the window title.thumbnail
NativeImage - A thumbnail image. Note: There is no guarantee that the size of the thumbnail is the same as thethumbnailSize
specified in theoptions
passed todesktopCapturer.getSources
. The actual size depends on the scale of the screen or window.display_id
String - A unique identifier that will correspond to theid
of the matching Display returned by the Screen API. On some platforms, this is equivalent to theXX
portion of theid
field above and on others it will differ. It will be an empty string if not available.appIcon
NativeImage - An icon image of the application that owns the window or null if the source has a type screen. The size of the icon is not known in advance and depends on what the application provides.
Desktop Environment Integration
Different operating systems provide different features for integrating desktop applications into their desktop environments. For example, on Windows, applications can put shortcuts in the JumpList of task bar, and on Mac, applications can put a custom menu in the dock menu.
This guide explains how to integrate your application into those desktop environments with Electron APIs.
Notifications
See the Notifications documentation.
Progress Bar
See the Progress Bar documentation.
DevTools Extension
Electron supports Chrome DevTools extensions, which can be used to extend the ability of Chrome's developer tools for debugging popular web frameworks.
Loading a DevTools extension with tooling
The easiest way to load a DevTools extension is to use third-party tooling to automate the process for you. electron-devtools-installer is a popular NPM package that does just that.
Manually loading a DevTools extension
If you don't want to use the tooling approach, you can also do all of the necessary
operations by hand. To load an extension in Electron, you need to download it via Chrome,
locate its filesystem path, and then load it into your Session by calling the
[ses.loadExtension
] API.
Using the React Developer Tools as an example:
-
Install the extension in Google Chrome.
-
Navigate to
chrome://extensions
, and find its extension ID, which is a hash string likefmkadmapgofadopljbjfkapdkoienihi
. -
Find out the filesystem location used by Chrome for storing extensions:
- on Windows it is
%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions
; - on Linux it could be:
~/.config/google-chrome/Default/Extensions/
~/.config/google-chrome-beta/Default/Extensions/
~/.config/google-chrome-canary/Default/Extensions/
~/.config/chromium/Default/Extensions/
- on macOS it is
~/Library/Application Support/Google/Chrome/Default/Extensions
.
- on Windows it is
-
Pass the location of the extension to the
ses.loadExtension
API. For React Developer Toolsv4.9.0
, it looks something like:const { app, session } = require('electron') const path = require('path') const os = require('os') // on macOS const reactDevToolsPath = path.join( os.homedir(), '/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0' ) app.whenReady().then(async () => { await session.defaultSession.loadExtension(reactDevToolsPath) })
Notes:
loadExtension
returns a Promise with an Extension object, which contains metadata about the extension that was loaded. This promise needs to resolve (e.g. with anawait
expression) before loading a page. Otherwise, the extension won't be guaranteed to load.loadExtension
cannot be called before theready
event of theapp
module is emitted, nor can it be called on in-memory (non-persistent) sessions.loadExtension
must be called on every boot of your app if you want the extension to be loaded.
Removing a DevTools extension
You can pass the extension's ID to the ses.removeExtension
API to
remove it from your Session. Loaded extensions are not persisted between
app launches.
DevTools extension support
Electron only supports
a limited set of chrome.*
APIs,
so extensions using unsupported chrome.*
APIs under the hood may not work.
The following Devtools extensions have been tested to work in Electron:
What should I do if a DevTools extension is not working?
First, please make sure the extension is still being maintained and is compatible with the latest version of Google Chrome. We cannot provide additional support for unsupported extensions.
If the extension works on Chrome but not on Electron, file a bug in Electron's issue tracker and describe which part of the extension is not working as expected.
dialog
Display native system dialogs for opening and saving files, alerting, etc.
Process: Main
An example of showing a dialog to select multiple files:
const { dialog } = require('electron')
console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] }))
The Dialog is opened from Electron's main thread. If you want to use the dialog object from a renderer process, remember to access it using the remote:
const { dialog } = require('electron').remote
console.log(dialog)
Methods
The dialog
module has the following methods:
dialog.showOpenDialogSync([browserWindow, ]options)
browserWindow
BrowserWindow (optional)options
Objecttitle
String (optional)defaultPath
String (optional)buttonLabel
String (optional) - Custom label for the confirmation button, when left empty the default label will be used.filters
FileFilter[] (optional)properties
String[] (optional) - Contains which features the dialog should use. The following values are supported:openFile
- Allow files to be selected.openDirectory
- Allow directories to be selected.multiSelections
- Allow multiple paths to be selected.showHiddenFiles
- Show hidden files in dialog.createDirectory
macOS - Allow creating new directories from dialog.promptToCreate
Windows - Prompt for creation if the file path entered in the dialog does not exist. This does not actually create the file at the path but allows non-existent paths to be returned that should be created by the application.noResolveAliases
macOS - Disable the automatic alias (symlink) path resolution. Selected aliases will now return the alias path instead of their target path.treatPackageAsDirectory
macOS - Treat packages, such as.app
folders, as a directory instead of a file.dontAddToRecent
Windows - Do not add the item being opened to the recent documents list.
message
String (optional) macOS - Message to display above input boxes.securityScopedBookmarks
Boolean (optional) macOS mas - Create security scoped bookmarks when packaged for the Mac App Store.
Returns String[] | undefined
, the file paths chosen by the user; if the dialog is cancelled it returns undefined
.
The browserWindow
argument allows the dialog to attach itself to a parent window, making it modal.
The filters
specifies an array of file types that can be displayed or
selected when you want to limit the user to a specific type. For example:
{
filters: [
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
{ name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
{ name: 'Custom File Type', extensions: ['as'] },
{ name: 'All Files', extensions: ['*'] }
]
}
The extensions
array should contain extensions without wildcards or dots (e.g.
'png'
is good but '.png'
and '*.png'
are bad). To show all files, use the
'*'
wildcard (no other wildcard is supported).
Note: On Windows and Linux an open dialog can not be both a file selector
and a directory selector, so if you set properties
to
['openFile', 'openDirectory']
on these platforms, a directory selector will be
shown.
dialog.showOpenDialogSync(mainWindow, {
properties: ['openFile', 'openDirectory']
})
dialog.showOpenDialog([browserWindow, ]options)
browserWindow
BrowserWindow (optional)options
Objecttitle
String (optional)defaultPath
String (optional)buttonLabel
String (optional) - Custom label for the confirmation button, when left empty the default label will be used.filters
FileFilter[] (optional)properties
String[] (optional) - Contains which features the dialog should use. The following values are supported:openFile
- Allow files to be selected.openDirectory
- Allow directories to be selected.multiSelections
- Allow multiple paths to be selected.showHiddenFiles
- Show hidden files in dialog.createDirectory
macOS - Allow creating new directories from dialog.promptToCreate
Windows - Prompt for creation if the file path entered in the dialog does not exist. This does not actually create the file at the path but allows non-existent paths to be returned that should be created by the application.noResolveAliases
macOS - Disable the automatic alias (symlink) path resolution. Selected aliases will now return the alias path instead of their target path.treatPackageAsDirectory
macOS - Treat packages, such as.app
folders, as a directory instead of a file.dontAddToRecent
Windows - Do not add the item being opened to the recent documents list.
message
String (optional) macOS - Message to display above input boxes.securityScopedBookmarks
Boolean (optional) macOS mas - Create security scoped bookmarks when packaged for the Mac App Store.
Returns Promise<Object>
- Resolve with an object containing the following:
canceled
Boolean - whether or not the dialog was canceled.filePaths
String[] - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array.bookmarks
String[] (optional) macOS mas - An array matching thefilePaths
array of base64 encoded strings which contains security scoped bookmark data.securityScopedBookmarks
must be enabled for this to be populated. (For return values, see table here.)
The browserWindow
argument allows the dialog to attach itself to a parent window, making it modal.
The filters
specifies an array of file types that can be displayed or
selected when you want to limit the user to a specific type. For example:
{
filters: [
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
{ name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
{ name: 'Custom File Type', extensions: ['as'] },
{ name: 'All Files', extensions: ['*'] }
]
}
The extensions
array should contain extensions without wildcards or dots (e.g.
'png'
is good but '.png'
and '*.png'
are bad). To show all files, use the
'*'
wildcard (no other wildcard is supported).
Note: On Windows and Linux an open dialog can not be both a file selector
and a directory selector, so if you set properties
to
['openFile', 'openDirectory']
on these platforms, a directory selector will be
shown.
dialog.showOpenDialog(mainWindow, {
properties: ['openFile', 'openDirectory']
}).then(result => {
console.log(result.canceled)
console.log(result.filePaths)
}).catch(err => {
console.log(err)
})
dialog.showSaveDialogSync([browserWindow, ]options)
browserWindow
BrowserWindow (optional)options
Objecttitle
String (optional)defaultPath
String (optional) - Absolute directory path, absolute file path, or file name to use by default.buttonLabel
String (optional) - Custom label for the confirmation button, when left empty the default label will be used.filters
FileFilter[] (optional)message
String (optional) macOS - Message to display above text fields.nameFieldLabel
String (optional) macOS - Custom label for the text displayed in front of the filename text field.showsTagField
Boolean (optional) macOS - Show the tags input box, defaults totrue
.properties
String[] (optional)showHiddenFiles
- Show hidden files in dialog.createDirectory
macOS - Allow creating new directories from dialog.treatPackageAsDirectory
macOS - Treat packages, such as.app
folders, as a directory instead of a file.showOverwriteConfirmation
Linux - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.dontAddToRecent
Windows - Do not add the item being saved to the recent documents list.
securityScopedBookmarks
Boolean (optional) macOS mas - Create a security scoped bookmark when packaged for the Mac App Store. If this option is enabled and the file doesn't already exist a blank file will be created at the chosen path.
Returns String | undefined
, the path of the file chosen by the user; if the dialog is cancelled it returns undefined
.
The browserWindow
argument allows the dialog to attach itself to a parent window, making it modal.
The filters
specifies an array of file types that can be displayed, see
dialog.showOpenDialog
for an example.
dialog.showSaveDialog([browserWindow, ]options)
browserWindow
BrowserWindow (optional)options
Objecttitle
String (optional)defaultPath
String (optional) - Absolute directory path, absolute file path, or file name to use by default.buttonLabel
String (optional) - Custom label for the confirmation button, when left empty the default label will be used.filters
FileFilter[] (optional)message
String (optional) macOS - Message to display above text fields.nameFieldLabel
String (optional) macOS - Custom label for the text displayed in front of the filename text field.showsTagField
Boolean (optional) macOS - Show the tags input box, defaults totrue
.properties
String[] (optional)showHiddenFiles
- Show hidden files in dialog.createDirectory
macOS - Allow creating new directories from dialog.treatPackageAsDirectory
macOS - Treat packages, such as.app
folders, as a directory instead of a file.showOverwriteConfirmation
Linux - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.dontAddToRecent
Windows - Do not add the item being saved to the recent documents list.
securityScopedBookmarks
Boolean (optional) macOS mas - Create a security scoped bookmark when packaged for the Mac App Store. If this option is enabled and the file doesn't already exist a blank file will be created at the chosen path.
Returns Promise<Object>
- Resolve with an object containing the following:
canceled
Boolean - whether or not the dialog was canceled.filePath
String (optional) - If the dialog is canceled, this will beundefined
.bookmark
String (optional) macOS mas - Base64 encoded string which contains the security scoped bookmark data for the saved file.securityScopedBookmarks
must be enabled for this to be present. (For return values, see table here.)
The browserWindow
argument allows the dialog to attach itself to a parent window, making it modal.
The filters
specifies an array of file types that can be displayed, see
dialog.showOpenDialog
for an example.
Note: On macOS, using the asynchronous version is recommended to avoid issues when expanding and collapsing the dialog.
dialog.showMessageBoxSync([browserWindow, ]options)
browserWindow
BrowserWindow (optional)options
Objecttype
String (optional) - Can be"none"
,"info"
,"error"
,"question"
or"warning"
. On Windows,"question"
displays the same icon as"info"
, unless you set an icon using the"icon"
option. On macOS, both"warning"
and"error"
display the same warning icon.buttons
String[] (optional) - Array of texts for buttons. On Windows, an empty array will result in one button labeled "OK".defaultId
Integer (optional) - Index of the button in the buttons array which will be selected by default when the message box opens.title
String (optional) - Title of the message box, some platforms will not show it.message
String - Content of the message box.detail
String (optional) - Extra information of the message.checkboxLabel
String (optional) - If provided, the message box will include a checkbox with the given label.checkboxChecked
Boolean (optional) - Initial checked state of the checkbox.false
by default.icon
(NativeImage | String) (optional)cancelId
Integer (optional) - The index of the button to be used to cancel the dialog, via theEsc
key. By default this is assigned to the first button with "cancel" or "no" as the label. If no such labeled buttons exist and this option is not set,0
will be used as the return value.noLink
Boolean (optional) - On Windows Electron will try to figure out which one of thebuttons
are common buttons (like "Cancel" or "Yes"), and show the others as command links in the dialog. This can make the dialog appear in the style of modern Windows apps. If you don't like this behavior, you can setnoLink
totrue
.normalizeAccessKeys
Boolean (optional) - Normalize the keyboard access keys across platforms. Default isfalse
. Enabling this assumes&
is used in the button labels for the placement of the keyboard shortcut access key and labels will be converted so they work correctly on each platform,&
characters are removed on macOS, converted to_
on Linux, and left untouched on Windows. For example, a button label ofVie&w
will be converted toVie_w
on Linux andView
on macOS and can be selected viaAlt-W
on Windows and Linux.
Returns Integer
- the index of the clicked button.
Shows a message box, it will block the process until the message box is closed. It returns the index of the clicked button.
The browserWindow
argument allows the dialog to attach itself to a parent window, making it modal.
If browserWindow
is not shown dialog will not be attached to it. In such case it will be displayed as an independent window.
dialog.showMessageBox([browserWindow, ]options)
browserWindow
BrowserWindow (optional)options
Objecttype
String (optional) - Can be"none"
,"info"
,"error"
,"question"
or"warning"
. On Windows,"question"
displays the same icon as"info"
, unless you set an icon using the"icon"
option. On macOS, both"warning"
and"error"
display the same warning icon.buttons
String[] (optional) - Array of texts for buttons. On Windows, an empty array will result in one button labeled "OK".defaultId
Integer (optional) - Index of the button in the buttons array which will be selected by default when the message box opens.title
String (optional) - Title of the message box, some platforms will not show it.message
String - Content of the message box.detail
String (optional) - Extra information of the message.checkboxLabel
String (optional) - If provided, the message box will include a checkbox with the given label.checkboxChecked
Boolean (optional) - Initial checked state of the checkbox.false
by default.icon
NativeImage (optional)cancelId
Integer (optional) - The index of the button to be used to cancel the dialog, via theEsc
key. By default this is assigned to the first button with "cancel" or "no" as the label. If no such labeled buttons exist and this option is not set,0
will be used as the return value.noLink
Boolean (optional) - On Windows Electron will try to figure out which one of thebuttons
are common buttons (like "Cancel" or "Yes"), and show the others as command links in the dialog. This can make the dialog appear in the style of modern Windows apps. If you don't like this behavior, you can setnoLink
totrue
.normalizeAccessKeys
Boolean (optional) - Normalize the keyboard access keys across platforms. Default isfalse
. Enabling this assumes&
is used in the button labels for the placement of the keyboard shortcut access key and labels will be converted so they work correctly on each platform,&
characters are removed on macOS, converted to_
on Linux, and left untouched on Windows. For example, a button label ofVie&w
will be converted toVie_w
on Linux andView
on macOS and can be selected viaAlt-W
on Windows and Linux.
Returns Promise<Object>
- resolves with a promise containing the following properties:
response
Number - The index of the clicked button.checkboxChecked
Boolean - The checked state of the checkbox ifcheckboxLabel
was set. Otherwisefalse
.
Shows a message box, it will block the process until the message box is closed.
The browserWindow
argument allows the dialog to attach itself to a parent window, making it modal.
dialog.showErrorBox(title, content)
title
String - The title to display in the error box.content
String - The text content to display in the error box.
Displays a modal dialog that shows an error message.
This API can be called safely before the ready
event the app
module emits,
it is usually used to report errors in early stage of startup. If called
before the app ready
event on Linux, the message will be emitted to stderr,
and no GUI dialog will appear.
dialog.showCertificateTrustDialog([browserWindow, ]options)
macOS Windows
browserWindow
BrowserWindow (optional)options
Objectcertificate
Certificate - The certificate to trust/import.message
String - The message to display to the user.
Returns Promise<void>
- resolves when the certificate trust dialog is shown.
On macOS, this displays a modal dialog that shows a message and certificate
information, and gives the user the option of trusting/importing the
certificate. If you provide a browserWindow
argument the dialog will be
attached to the parent window, making it modal.
On Windows the options are more limited, due to the Win32 APIs used:
- The
message
argument is not used, as the OS provides its own confirmation dialog. - The
browserWindow
argument is ignored since it is not possible to make this confirmation dialog modal.
Bookmarks array
showOpenDialog
, showOpenDialogSync
, showSaveDialog
, and showSaveDialogSync
will return a bookmarks
array.
Build Type | securityScopedBookmarks boolean | Return Type | Return Value |
---|---|---|---|
macOS mas | True | Success | ['LONGBOOKMARKSTRING'] |
macOS mas | True | Error | [''] (array of empty string) |
macOS mas | False | NA | [] (empty array) |
non mas | any | NA | [] (empty array) |
Sheets
On macOS, dialogs are presented as sheets attached to a window if you provide
a BrowserWindow
reference in the browserWindow
parameter, or modals if no
window is provided.
You can call BrowserWindow.getCurrentWindow().setSheetOffset(offset)
to change
the offset from the window frame where sheets are attached.
Display Object
id
Number - Unique identifier associated with the display.rotation
Number - Can be 0, 90, 180, 270, represents screen rotation in clock-wise degrees.scaleFactor
Number - Output device's pixel scale factor.touchSupport
String - Can beavailable
,unavailable
,unknown
.monochrome
Boolean - Whether or not the display is a monochrome display.accelerometerSupport
String - Can beavailable
,unavailable
,unknown
.colorSpace
String - represent a color space (three-dimensional object which contains all realizable color combinations) for the purpose of color conversionscolorDepth
Number - The number of bits per pixel.depthPerComponent
Number - The number of bits per color component.bounds
Rectanglesize
SizeworkArea
RectangleworkAreaSize
Sizeinternal
Boolean -true
for an internal display andfalse
for an external display
The Display
object represents a physical display connected to the system. A
fake Display
may exist on a headless system, or a Display
may correspond to
a remote, virtual display.
Class: Dock
Control your app in the macOS dock
Process: Main
The following example shows how to bounce your icon on the dock.
const { app } = require('electron')
app.dock.bounce()
dock.bounce([type])
macOS
type
String (optional) - Can becritical
orinformational
. The default isinformational
Returns Integer
- an ID representing the request.
When critical
is passed, the dock icon will bounce until either the
application becomes active or the request is canceled.
When informational
is passed, the dock icon will bounce for one second.
However, the request remains active until either the application becomes active
or the request is canceled.
Nota Bene: This method can only be used while the app is not focused; when the app is focused it will return -1.
dock.downloadFinished(filePath)
macOS
filePath
String
Bounces the Downloads stack if the filePath is inside the Downloads folder.
dock.getBadge()
macOS
Returns String
- The badge string of the dock.
dock.hide()
macOS
Hides the dock icon.
dock.show()
macOS
Returns Promise<void>
- Resolves when the dock icon is shown.
dock.isVisible()
macOS
Returns Boolean
- Whether the dock icon is visible.
dock.getMenu()
macOS
Returns Menu | null
- The application's [dock menu][dock-menu].
dock.setIcon(image)
macOS
image
(NativeImage | String)
Sets the image
associated with this dock icon.
Class: DownloadItem
Control file downloads from remote sources.
Process: Main
DownloadItem
is an EventEmitter that represents a download item in Electron.
It is used in will-download
event of Session
class, and allows users to
control the download item.
// In the main process.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.webContents.session.on('will-download', (event, item, webContents) => {
// Set the save path, making Electron not to prompt a save dialog.
item.setSavePath('/tmp/save.pdf')
item.on('updated', (event, state) => {
if (state === 'interrupted') {
console.log('Download is interrupted but can be resumed')
} else if (state === 'progressing') {
if (item.isPaused()) {
console.log('Download is paused')
} else {
console.log(`Received bytes: ${item.getReceivedBytes()}`)
}
}
})
item.once('done', (event, state) => {
if (state === 'completed') {
console.log('Download successfully')
} else {
console.log(`Download failed: ${state}`)
}
})
})
Event: 'updated'
Returns:
event
Eventstate
String - Can beprogressing
orinterrupted
.
Emitted when the download has been updated and is not done.
The state
can be one of following:
progressing
- The download is in-progress.interrupted
- The download has interrupted and can be resumed.
Event: 'done'
Returns:
event
Eventstate
String - Can becompleted
,cancelled
orinterrupted
.
Emitted when the download is in a terminal state. This includes a completed
download, a cancelled download (via downloadItem.cancel()
), and interrupted
download that can't be resumed.
The state
can be one of following:
completed
- The download completed successfully.cancelled
- The download has been cancelled.interrupted
- The download has interrupted and can not resume.
Instance Methods
The downloadItem
object has the following methods:
downloadItem.setSavePath(path)
path
String - Set the save file path of the download item.
The API is only available in session's will-download
callback function.
If user doesn't set the save path via the API, Electron will use the original
routine to determine the save path; this usually prompts a save dialog.
downloadItem.getSavePath()
Returns String
- The save path of the download item. This will be either the path
set via downloadItem.setSavePath(path)
or the path selected from the shown
save dialog.
downloadItem.setSaveDialogOptions(options)
options
SaveDialogOptions - Set the save file dialog options. This object has the same properties as theoptions
parameter ofdialog.showSaveDialog()
.
This API allows the user to set custom options for the save dialog that opens
for the download item by default.
The API is only available in session's will-download
callback function.
downloadItem.getSaveDialogOptions()
Returns SaveDialogOptions
- Returns the object previously set by downloadItem.setSaveDialogOptions(options)
.
downloadItem.pause()
Pauses the download.
downloadItem.isPaused()
Returns Boolean
- Whether the download is paused.
downloadItem.resume()
Resumes the download that has been paused.
Note: To enable resumable downloads the server you are downloading from must support range requests and provide both Last-Modified
and ETag
header values. Otherwise resume()
will dismiss previously received bytes and restart the download from the beginning.
downloadItem.canResume()
Returns Boolean
- Whether the download can resume.
downloadItem.cancel()
Cancels the download operation.
downloadItem.getURL()
Returns String
- The origin URL where the item is downloaded from.
downloadItem.getMimeType()
Returns String
- The files mime type.
downloadItem.hasUserGesture()
Returns Boolean
- Whether the download has user gesture.
downloadItem.getFilename()
Returns String
- The file name of the download item.
Note: The file name is not always the same as the actual one saved in local disk. If user changes the file name in a prompted download saving dialog, the actual name of saved file will be different.
downloadItem.getTotalBytes()
Returns Integer
- The total size in bytes of the download item.
If the size is unknown, it returns 0.
downloadItem.getReceivedBytes()
Returns Integer
- The received bytes of the download item.
downloadItem.getContentDisposition()
Returns String
- The Content-Disposition field from the response
header.
downloadItem.getState()
Returns String
- The current state. Can be progressing
, completed
, cancelled
or interrupted
.
Note: The following methods are useful specifically to resume a
cancelled
item when session is restarted.
downloadItem.getURLChain()
Returns String[]
- The complete URL chain of the item including any redirects.
downloadItem.getLastModifiedTime()
Returns String
- Last-Modified header value.
downloadItem.getETag()
Returns String
- ETag header value.
downloadItem.getStartTime()
Returns Double
- Number of seconds since the UNIX epoch when the download was
started.
downloadItem.savePath
A String
property that determines the save file path of the download item.
The property is only available in session's will-download
callback function.
If user doesn't set the save path via the property, Electron will use the original
routine to determine the save path; this usually prompts a save dialog.
Electron Release Timelines
- The
-beta.1
andstable
dates are our solid release dates. - We strive for weekly beta releases, however we often release more betas than scheduled.
- All dates are our goals but there may be reasons for adjusting the stable deadline, such as security bugs.
- Take a look at the 5.0.0 Timeline blog post for info about publicizing our release dates.
- Since Electron 6.0, we've been targeting every other Chromium version and releasing our stable on the same day as Chrome stable. You can reference Chromium's release schedule here. See Electron's new release cadence blog post for more details on our release schedule.
Version | -beta.1 | Stable | Chrome | Node |
---|---|---|---|---|
2.0.0 | 2018-02-21 | 2018-05-01 | M61 | v8.9 |
3.0.0 | 2018-06-21 | 2018-09-18 | M66 | v10.2 |
4.0.0 | 2018-10-11 | 2018-12-20 | M69 | v10.11 |
5.0.0 | 2019-01-22 | 2019-04-24 | M73 | v12.0 |
6.0.0 | 2019-05-01 | 2019-07-30 | M76 | v12.4 |
7.0.0 | 2019-08-01 | 2019-10-22 | M78 | v12.8 |
8.0.0 | 2019-10-24 | 2020-02-04 | M80 | v12.13 |
9.0.0 | 2020-02-06 | 2020-05-19 | M83 | v12.14 |
10.0.0 | 2020-05-21 | 2020-08-25 | M85 | v12.16 |
11.0.0 | 2020-08-27 | 2020-11-17 | M87 | v12.18 |
12.0.0 | 2020-11-19 | 2021-03-02 | M89 | v14.x |
Electron Versioning
A detailed look at our versioning policy and implementation.
As of version 2.0.0, Electron follows semver. The following command will install the most recent stable build of Electron:
npm install --save-dev electron
To update an existing project to use the latest stable version:
npm install --save-dev electron@latest
Version 1.x
Electron versions < 2.0 did not conform to the semver spec: major versions corresponded to end-user API changes, minor versions corresponded to Chromium major releases, and patch versions corresponded to new features and bug fixes. While convenient for developers merging features, it creates problems for developers of client-facing applications. The QA testing cycles of major apps like Slack, Stride, Teams, Skype, VS Code, Atom, and Desktop can be lengthy and stability is a highly desired outcome. There is a high risk in adopting new features while trying to absorb bug fixes.
Here is an example of the 1.x strategy:
An app developed with 1.8.1
cannot take the 1.8.3
bug fix without either absorbing the 1.8.2
feature, or by backporting the fix and maintaining a new release line.
Version 2.0 and Beyond
There are several major changes from our 1.x strategy outlined below. Each change is intended to satisfy the needs and priorities of developers/maintainers and app developers.
- Strict use of semver
- Introduction of semver-compliant
-beta
tags - Introduction of conventional commit messages
- Well-defined stabilization branches
- The
master
branch is versionless; only stabilization branches contain version information
We will cover in detail how git branching works, how npm tagging works, what developers should expect to see, and how one can backport changes.
semver
From 2.0 onward, Electron will follow semver.
Below is a table explicitly mapping types of changes to their corresponding category of semver (e.g. Major, Minor, Patch).
Major Version Increments | Minor Version Increments | Patch Version Increments |
---|---|---|
Electron breaking API changes | Electron non-breaking API changes | Electron bug fixes |
Node.js major version updates | Node.js minor version updates | Node.js patch version updates |
Chromium version updates | fix-related chromium patches |
Note that most Chromium updates will be considered breaking. Fixes that can be backported will likely be cherry-picked as patches.
Stabilization Branches
Stabilization branches are branches that run parallel to master, taking in only cherry-picked commits that are related to security or stability. These branches are never merged back to master.
Since Electron 8, stabilization branches are always major version lines, and named against the following template $MAJOR-x-y
e.g. 8-x-y
. Prior to that we used minor version lines and named them as $MAJOR-$MINOR-x
e.g. 2-0-x
We allow for multiple stabilization branches to exist simultaneously, and intend to support at least two in parallel at all times, backporting security fixes as necessary.
Older lines will not be supported by GitHub, but other groups can take ownership and backport stability and security fixes on their own. We discourage this, but recognize that it makes life easier for many app developers.
Beta Releases and Bug Fixes
Developers want to know which releases are safe to use. Even seemingly innocent features can introduce regressions in complex applications. At the same time, locking to a fixed version is dangerous because you’re ignoring security patches and bug fixes that may have come out since your version. Our goal is to allow the following standard semver ranges in package.json
:
- Use
~2.0.0
to admit only stability or security related fixes to your2.0.0
release. - Use
^2.0.0
to admit non-breaking reasonably stable feature work as well as security and bug fixes.
What’s important about the second point is that apps using ^
should still be able to expect a reasonable level of stability. To accomplish this, semver allows for a pre-release identifier to indicate a particular version is not yet safe or stable.
Whatever you choose, you will periodically have to bump the version in your package.json
as breaking changes are a fact of Chromium life.
The process is as follows:
- All new major and minor releases lines begin with a beta series indicated by semver prerelease tags of
beta.N
, e.g.2.0.0-beta.1
. After the first beta, subsequent beta releases must meet all of the following conditions:- The change is backwards API-compatible (deprecations are allowed)
- The risk to meeting our stability timeline must be low.
- If allowed changes need to be made once a release is beta, they are applied and the prerelease tag is incremented, e.g.
2.0.0-beta.2
. - If a particular beta release is generally regarded as stable, it will be re-released as a stable build, changing only the version information. e.g.
2.0.0
. After the first stable, all changes must be backwards-compatible bug or security fixes. - If future bug fixes or security patches need to be made once a release is stable, they are applied and the patch version is incremented
e.g.
2.0.1
.
Specifically, the above means:
- Admitting non-breaking-API changes before Week 3 in the beta cycle is okay, even if those changes have the potential to cause moderate side-effects
- Admitting feature-flagged changes, that do not otherwise alter existing code paths, at most points in the beta cycle is okay. Users can explicitly enable those flags in their apps.
- Admitting features of any sort after Week 3 in the beta cycle is 👎 without a very good reason.
For each major and minor bump, you should expect to see something like the following:
2.0.0-beta.1
2.0.0-beta.2
2.0.0-beta.3
2.0.0
2.0.1
2.0.2
An example lifecycle in pictures:
- A new release branch is created that includes the latest set of features. It is published as
2.0.0-beta.1
. - A bug fix comes into master that can be backported to the release branch. The patch is applied, and a new beta is published as
2.0.0-beta.2
. - The beta is considered generally stable and it is published again as a non-beta under
2.0.0
. - Later, a zero-day exploit is revealed and a fix is applied to master. We backport the fix to the
2-0-x
line and release2.0.1
.
A few examples of how various semver ranges will pick up new releases:
Missing Features: Alphas
Our strategy has a few tradeoffs, which for now we feel are appropriate. Most importantly that new features in master may take a while before reaching a stable release line. If you want to try a new feature immediately, you will have to build Electron yourself.
As a future consideration, we may introduce one or both of the following:
- alpha releases that have looser stability constraints to betas; for example it would be allowable to admit new features while a stability channel is in alpha
Feature Flags
Feature flags are a common practice in Chromium, and are well-established in the web-development ecosystem. In the context of Electron, a feature flag or soft branch must have the following properties:
- it is enabled/disabled either at runtime, or build-time; we do not support the concept of a request-scoped feature flag
- it completely segments new and old code paths; refactoring old code to support a new feature violates the feature-flag contract
- feature flags are eventually removed after the feature is released
Semantic Commits
We seek to increase clarity at all levels of the update and releases process. Starting with 2.0.0
we will require pull requests adhere to the Conventional Commits spec, which can be summarized as follows:
-
Commits that would result in a semver major bump must start their body with
BREAKING CHANGE:
. -
Commits that would result in a semver minor bump must start with
feat:
. -
Commits that would result in a semver patch bump must start with
fix:
. -
We allow squashing of commits, provided that the squashed message adheres to the above message format.
-
It is acceptable for some commits in a pull request to not include a semantic prefix, as long as the pull request title contains a meaningful encompassing semantic message.
Versioned master
- The
master
branch will always contain the next major versionX.0.0-nightly.DATE
in itspackage.json
- Release branches are never merged back to master
- Release branches do contain the correct version in their
package.json
- As soon as a release branch is cut for a major, master must be bumped to the next major. I.e.
master
is always versioned as the next theoretical release branch
Technical Differences Between Electron and NW.js
Like NW.js, Electron provides a platform to write desktop applications with web technologies. Both platforms enable developers to utilize HTML, JavaScript, and Node.js. On the surface, they seem very similar.
There are however fundamental differences between the two projects that make Electron a completely separate product from NW.js.
1) Entry of Application
In NW.js, the main entry point of an application can be an HTML web page. In that case, NW.js will open the given entry point in a browser window.
In Electron, the entry point is always a JavaScript script. Instead of providing a URL directly, you manually create a browser window and load an HTML file using the API. You also need to listen to window events to decide when to quit the application.
Electron works more like the Node.js runtime. Electron's APIs are lower level so you can use it for browser testing in place of PhantomJS.
2) Node Integration
In NW.js, the Node integration in web pages requires patching Chromium to work,
while in Electron we chose a different way to integrate the libuv
loop with
each platform's message loop to avoid hacking Chromium. See the
node_bindings
code for how that was done.
3) JavaScript Contexts
If you are an experienced NW.js user, you should be familiar with the concept of Node context and web context. These concepts were invented because of how NW.js was implemented.
By using the multi-context feature of Node, Electron doesn't introduce a new JavaScript context in web pages.
Note: NW.js has optionally supported multi-context since 0.13.
4) Legacy Support
NW.js still offers a "legacy release" that supports Windows XP. It doesn't receive security updates.
Given that hardware manufacturers, Microsoft, Chromium, and Node.js haven't released even critical security updates for that system, we have to warn you that using Windows XP is wildly insecure and outright irresponsible.
However, we understand that requirements outside our wildest imagination may exist, so if you're looking for something like Electron that runs on Windows XP, the NW.js legacy release might be the right fit for you.
5) Features
There are numerous differences in the amount of supported features. Electron has a bigger community, more production apps using it, and a large amount of userland modules available on npm.
As an example, Electron has built-in support for automatic updates and countless
tools that make the creation of installers easier. As an example in favor of
NW.js, NW.js supports more Chrome.*
APIs for the development of Chrome Apps.
Naturally, we believe that Electron is the better platform for polished production applications built with web technologies (like Visual Studio Code, Slack, or Facebook Messenger); however, we want to be fair to our web technology friends. If you have feature needs that Electron does not meet, you might want to try NW.js.
Environment Variables
Control application configuration and behavior without changing code.
Certain Electron behaviors are controlled by environment variables because they are initialized earlier than the command line flags and the app's code.
POSIX shell example:
$ export ELECTRON_ENABLE_LOGGING=true
$ electron
Windows console example:
> set ELECTRON_ENABLE_LOGGING=true
> electron
Production Variables
The following environment variables are intended primarily for use at runtime in packaged Electron applications.
NODE_OPTIONS
Electron includes support for a subset of Node's NODE_OPTIONS
. The majority are supported with the exception of those which conflict with Chromium's use of BoringSSL.
Example:
export NODE_OPTIONS="--no-warnings --max-old-space-size=2048"
Unsupported options are:
--use-bundled-ca
--force-fips
--enable-fips
--openssl-config
--use-openssl-ca
NODE_OPTIONS
are explicitly disallowed in packaged apps, except for the following:
--max-http-header-size
--http-parser
GOOGLE_API_KEY
Geolocation support in Electron requires the use of Google Cloud Platform's geolocation webservice. To enable this feature, acquire a Google API key and place the following code in your main process file, before opening any browser windows that will make geolocation requests:
process.env.GOOGLE_API_KEY = 'YOUR_KEY_HERE'
By default, a newly generated Google API key may not be allowed to make geolocation requests. To enable the geolocation webservice for your project, enable it through the API library.
N.B. You will need to add a Billing Account to the project associated to the API key for the geolocation webservice to work.
ELECTRON_NO_ASAR
Disables ASAR support. This variable is only supported in forked child processes
and spawned child processes that set ELECTRON_RUN_AS_NODE
.
ELECTRON_RUN_AS_NODE
Starts the process as a normal Node.js process.
In this mode, you will be able to pass cli options to Node.js as you would when running the normal Node.js executable, with the exception of the following flags:
- "--openssl-config"
- "--use-bundled-ca"
- "--use-openssl-ca",
- "--force-fips"
- "--enable-fips"
These flags are disabled owing to the fact that Electron uses BoringSSL instead of OpenSSL when building Node.js'
crypto
module, and so will not work as designed.
ELECTRON_NO_ATTACH_CONSOLE
Windows
Don't attach to the current console session.
ELECTRON_FORCE_WINDOW_MENU_BAR
Linux
Don't use the global menu bar on Linux.
ELECTRON_TRASH
Linux
Set the trash implementation on Linux. Default is gio
.
Options:
gvfs-trash
trash-cli
kioclient5
kioclient
Development Variables
The following environment variables are intended primarily for development and debugging purposes.
ELECTRON_ENABLE_LOGGING
Prints Chrome's internal logging to the console.
ELECTRON_LOG_ASAR_READS
When Electron reads from an ASAR file, log the read offset and file path to
the system tmpdir
. The resulting file can be provided to the ASAR module
to optimize file ordering.
ELECTRON_ENABLE_STACK_DUMPING
Prints the stack trace to the console when Electron crashes.
This environment variable will not work if the crashReporter
is started.
ELECTRON_DEFAULT_ERROR_MODE
Windows
Shows the Windows's crash dialog when Electron crashes.
This environment variable will not work if the crashReporter
is started.
ELECTRON_OVERRIDE_DIST_PATH
When running from the electron
package, this variable tells
the electron
command to use the specified build of Electron instead of
the one downloaded by npm install
. Usage:
export ELECTRON_OVERRIDE_DIST_PATH=/Users/username/projects/electron/out/Testing
Set By Electron
Electron sets some variables in your environment at runtime.
ORIGINAL_XDG_CURRENT_DESKTOP
This variable is set to the value of XDG_CURRENT_DESKTOP
that your application
originally launched with. Electron sometimes modifies the value of XDG_CURRENT_DESKTOP
to affect other logic within Chromium so if you want access to the original value
you should look up this environment variable instead.
Event Object extends GlobalEvent
preventDefault
VoidFunction
Experimental APIs
Some of Electrons APIs are tagged with _Experimental_
in the documentation.
This tag indicates that the API may not be considered stable and the API may
be removed or modified more frequently than other APIs with less warning.
Conditions for an API to be tagged as Experimental
Anyone can request an API be tagged as experimental in a feature PR, disagreements on the experimental nature of a feature can be discussed in the API WG if they can't be resolved in the PR.
Process for removing the Experimental tag
Once an API has been stable and in at least two major stable release lines it can be nominated to have its experimental tag removed. This discussion should happen at an API WG meeting. Things to consider when discussing / nominating:
- The above "two major stables release lines" condition must have been met
- During that time no major bugs / issues should have been caused by the adoption of this feature
- The API is stable enough and hasn't been heavily impacted by Chromium upgrades
- Is anyone using the API?
- Is the API fulfilling the original proposed usecases, does it have any gaps?
Extension Object
id
Stringmanifest
any - Copy of the extension's manifest data.name
Stringpath
String - The extension's file path.version
Stringurl
String - The extension'schrome-extension://
URL.
ExtensionInfo Object
name
Stringversion
String
Chrome Extension Support
Electron supports a subset of the Chrome Extensions API, primarily to support DevTools extensions and Chromium-internal extensions, but it also happens to support some other extension capabilities.
Note: Electron does not support arbitrary Chrome extensions from the store, and it is a non-goal of the Electron project to be perfectly compatible with Chrome's implementation of Extensions.
Loading extensions
Electron only supports loading unpacked extensions (i.e., .crx
files do not
work). Extensions are installed per-session
. To load an extension, call
ses.loadExtension
:
const { session } = require('electron')
session.loadExtension('path/to/unpacked/extension').then(({ id }) => {
// ...
})
Loaded extensions will not be automatically remembered across exits; if you do
not call loadExtension
when the app runs, the extension will not be loaded.
Note that loading extensions is only supported in persistent sessions. Attempting to load an extension into an in-memory session will throw an error.
See the session
documentation for more information about
loading, unloading, and querying active extensions.
Supported Extensions APIs
We support the following extensions APIs, with some caveats. Other APIs may additionally be supported, but support for any APIs not listed here is provisional and may be removed.
chrome.devtools.inspectedWindow
All features of this API are supported.
chrome.devtools.network
All features of this API are supported.
chrome.devtools.panels
All features of this API are supported.
chrome.extension
The following properties of chrome.extension
are supported:
chrome.extension.lastError
The following methods of chrome.extension
are supported:
chrome.extension.getURL
chrome.extension.getBackgroundPage
chrome.runtime
The following properties of chrome.runtime
are supported:
chrome.runtime.lastError
chrome.runtime.id
The following methods of chrome.runtime
are supported:
chrome.runtime.getBackgroundPage
chrome.runtime.getManifest
chrome.runtime.getURL
chrome.runtime.connect
chrome.runtime.sendMessage
The following events of chrome.runtime
are supported:
chrome.runtime.onStartup
chrome.runtime.onInstalled
chrome.runtime.onSuspend
chrome.runtime.onSuspendCanceled
chrome.runtime.onConnect
chrome.runtime.onMessage
chrome.storage
Only chrome.storage.local
is supported; chrome.storage.sync
and
chrome.storage.managed
are not.
chrome.tabs
The following methods of chrome.tabs
are supported:
chrome.tabs.sendMessage
chrome.tabs.executeScript
Note: In Chrome, passing
-1
as a tab ID signifies the "currently active tab". Since Electron has no such concept, passing-1
as a tab ID is not supported and will raise an error.
chrome.management
The following methods of chrome.management
are supported:
chrome.management.getAll
chrome.management.get
chrome.management.getSelf
chrome.management.getPermissionWarningsById
chrome.management.getPermissionWarningsByManifest
chrome.management.onEnabled
chrome.management.onDisabled
chrome.webRequest
All features of this API are supported.
NOTE: Electron's
webRequest
module takes precedence overchrome.webRequest
if there are conflicting handlers.
Why am I having trouble installing Electron?
When running npm install electron
, some users occasionally encounter
installation errors.
In almost all cases, these errors are the result of network problems and not
actual issues with the electron
npm package. Errors like ELIFECYCLE
,
EAI_AGAIN
, ECONNRESET
, and ETIMEDOUT
are all indications of such
network problems. The best resolution is to try switching networks, or
wait a bit and try installing again.
You can also attempt to download Electron directly from
electron/electron/releases
if installing via npm
is failing.
When will Electron upgrade to latest Chrome?
The Chrome version of Electron is usually bumped within one or two weeks after a new stable Chrome version gets released. This estimate is not guaranteed and depends on the amount of work involved with upgrading.
Only the stable channel of Chrome is used. If an important fix is in beta or dev channel, we will back-port it.
For more information, please see the security introduction.
When will Electron upgrade to latest Node.js?
When a new version of Node.js gets released, we usually wait for about a month before upgrading the one in Electron. So we can avoid getting affected by bugs introduced in new Node.js versions, which happens very often.
New features of Node.js are usually brought by V8 upgrades, since Electron is using the V8 shipped by Chrome browser, the shiny new JavaScript feature of a new Node.js version is usually already in Electron.
How to share data between web pages?
To share data between web pages (the renderer processes) the simplest way is to
use HTML5 APIs which are already available in browsers. Good candidates are
Storage API, localStorage
,
sessionStorage
, and IndexedDB.
Alternatively, you can use the IPC primitives that are provided by Electron. To
share data between the main and renderer processes, you can use the
ipcMain
and ipcRenderer
modules.
To communicate directly between web pages, you can send a
MessagePort
from one to the other, possibly via the main process
using ipcRenderer.postMessage()
.
Subsequent communication over message ports is direct and does not detour through
the main process.
My app's tray disappeared after a few minutes.
This happens when the variable which is used to store the tray gets garbage collected.
If you encounter this problem, the following articles may prove helpful:
If you want a quick fix, you can make the variables global by changing your code from this:
const { app, Tray } = require('electron')
app.whenReady().then(() => {
const tray = new Tray('/path/to/icon.png')
tray.setTitle('hello world')
})
to this:
const { app, Tray } = require('electron')
let tray = null
app.whenReady().then(() => {
tray = new Tray('/path/to/icon.png')
tray.setTitle('hello world')
})
I can not use jQuery/RequireJS/Meteor/AngularJS in Electron.
Due to the Node.js integration of Electron, there are some extra symbols
inserted into the DOM like module
, exports
, require
. This causes problems
for some libraries since they want to insert the symbols with the same names.
To solve this, you can turn off node integration in Electron:
// In the main process.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
webPreferences: {
nodeIntegration: false
}
})
win.show()
But if you want to keep the abilities of using Node.js and Electron APIs, you have to rename the symbols in the page before including other libraries:
<head>
<script>
window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;
</script>
<script type="text/javascript" src="jquery.js"></script>
</head>
require('electron').xxx
is undefined.
When using Electron's built-in module you might encounter an error like this:
> require('electron').webFrame.setZoomFactor(1.0)
Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined
It is very likely you are using the module in the wrong process. For example
electron.app
can only be used in the main process, while electron.webFrame
is only available in renderer processes.
The font looks blurry, what is this and what can I do?
If sub-pixel anti-aliasing is deactivated, then fonts on LCD screens can look blurry. Example:
Sub-pixel anti-aliasing needs a non-transparent background of the layer containing the font glyphs. (See this issue for more info).
To achieve this goal, set the background in the constructor for BrowserWindow:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
backgroundColor: '#fff'
})
The effect is visible only on (some?) LCD screens. Even if you don't see a difference, some of your users may. It is best to always set the background this way, unless you have reasons not to do so.
Notice that just setting the background in the CSS does not have the desired effect.
FileFilter Object
name
Stringextensions
String[]
File
Object
Use the HTML5
File
API to work natively with files on the filesystem.
The DOM's File interface provides abstraction around native files in order to
let users work on native files directly with the HTML5 file API. Electron has
added a path
attribute to the File
interface which exposes the file's real
path on filesystem.
Example of getting a real path from a dragged-onto-the-app file:
<div id="holder">
Drag your file here
</div>
<script>
document.addEventListener('drop', (e) => {
e.preventDefault();
e.stopPropagation();
for (const f of e.dataTransfer.files) {
console.log('File(s) you dragged here: ', f.path)
}
});
document.addEventListener('dragover', (e) => {
e.preventDefault();
e.stopPropagation();
});
</script>
FilePathWithHeaders Object
path
String - The path to the file to send.headers
Record<string, string> (optional) - Additional headers to be sent.
Frameless Window
Open a window without toolbars, borders, or other graphical "chrome".
A frameless window is a window that has no
chrome, the parts of
the window, like toolbars, that are not a part of the web page. These are
options on the BrowserWindow
class.
Create a frameless window
To create a frameless window, you need to set frame
to false
in
BrowserWindow's options
:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600, frame: false })
win.show()
Alternatives on macOS
There's an alternative way to specify a chromeless window.
Instead of setting frame
to false
which disables both the titlebar and window controls,
you may want to have the title bar hidden and your content extend to the full window size,
yet still preserve the window controls ("traffic lights") for standard window actions.
You can do so by specifying the titleBarStyle
option:
hidden
Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls (“traffic lights”) in the top left.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hidden' })
win.show()
hiddenInset
Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
win.show()
customButtonsOnHover
Uses custom drawn close, and miniaturize buttons that display when hovering in the top left of the window. The fullscreen button is not available due to restrictions of frameless windows as they interface with Apple's macOS window masks. These custom buttons prevent issues with mouse events that occur with the standard window toolbar buttons. This option is only applicable for frameless windows.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: false })
win.show()
Transparent window
By setting the transparent
option to true
, you can also make the frameless
window transparent:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ transparent: true, frame: false })
win.show()
Limitations
- You can not click through the transparent area. We are going to introduce an API to set window shape to solve this, see our issue for details.
- Transparent windows are not resizable. Setting
resizable
totrue
may make a transparent window stop working on some platforms. - The
blur
filter only applies to the web page, so there is no way to apply blur effect to the content below the window (i.e. other applications open on the user's system). - On Windows operating systems, transparent windows will not work when DWM is disabled.
- On Linux, users have to put
--enable-transparent-visuals --disable-gpu
in the command line to disable GPU and allow ARGB to make transparent window, this is caused by an upstream bug that alpha channel doesn't work on some NVidia drivers on Linux. - On Mac, the native window shadow will not be shown on a transparent window.
Click-through window
To create a click-through window, i.e. making the window ignore all mouse events, you can call the win.setIgnoreMouseEvents(ignore) API:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.setIgnoreMouseEvents(true)
Forwarding
Ignoring mouse messages makes the web page oblivious to mouse movement, meaning
that mouse movement events will not be emitted. On Windows operating systems an
optional parameter can be used to forward mouse move messages to the web page,
allowing events such as mouseleave
to be emitted:
const win = require('electron').remote.getCurrentWindow()
const el = document.getElementById('clickThroughElement')
el.addEventListener('mouseenter', () => {
win.setIgnoreMouseEvents(true, { forward: true })
})
el.addEventListener('mouseleave', () => {
win.setIgnoreMouseEvents(false)
})
This makes the web page click-through when over el
, and returns to normal
outside it.
Draggable region
By default, the frameless window is non-draggable. Apps need to specify
-webkit-app-region: drag
in CSS to tell Electron which regions are draggable
(like the OS's standard titlebar), and apps can also use
-webkit-app-region: no-drag
to exclude the non-draggable area from the
draggable region. Note that only rectangular shapes are currently supported.
Note: -webkit-app-region: drag
is known to have problems while the developer tools are open. See this GitHub issue for more information including a workaround.
To make the whole window draggable, you can add -webkit-app-region: drag
as
body
's style:
<body style="-webkit-app-region: drag">
</body>
And note that if you have made the whole window draggable, you must also mark buttons as non-draggable, otherwise it would be impossible for users to click on them:
button {
-webkit-app-region: no-drag;
}
If you're only setting a custom titlebar as draggable, you also need to make all buttons in titlebar non-draggable.
Text selection
In a frameless window the dragging behavior may conflict with selecting text. For example, when you drag the titlebar you may accidentally select the text on the titlebar. To prevent this, you need to disable text selection within a draggable area like this:
.titlebar {
-webkit-user-select: none;
-webkit-app-region: drag;
}
Context menu
On some platforms, the draggable area will be treated as a non-client frame, so when you right click on it a system menu will pop up. To make the context menu behave correctly on all platforms you should never use a custom context menu on draggable areas.
Electron Fuses
Package time feature toggles
What are fuses?
For a subset of Electron functionality it makes sense to disable certain features for an entire application. For example, 99% of apps don't make use of ELECTRON_RUN_AS_NODE
, these applications want to be able to ship a binary that is incapable of using that feature. We also don't want Electron consumers building Electron from source as that is both a massive technical challenge and has a high cost of both time and money.
Fuses are the solution to this problem, at a high level they are "magic bits" in the Electron binary that can be flipped when packaging your Electron app to enable / disable certain features / restrictions. Because they are flipped at package time before you code sign your app the OS becomes responsible for ensuring those bits aren't flipped back via OS level code signing validation (Gatekeeper / App Locker).
The easy way
We've made a handy module @electron/fuses
to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases.
require('@electron/fuses').flipFuses(
// Path to electron
require('electron'),
// Fuses to flip
{
runAsNode: false
}
)
Quick Glossary
- Fuse Wire: A sequence of bytes in the Electron binary used to control the fuses
- Sentinel: A static known sequence of bytes you can use to locate the fuse wire
- Fuse Schema: The format / allowed values for the fuse wire
Manually flipping fuses requires editing the Electron binary and modifying the fuse wire to be the sequence of bytes that represent the state of the fuses you want.
Somewhere in the Electron binary there will be a sequence of bytes that look like this:
| ...binary | sentinel_bytes | fuse_version | fuse_wire_length | fuse_wire | ...binary |
sentinel_bytes
is always this exact stringdL7pKGdnNz796PbbjQWNKmHXBZaB9tsX
fuse_version
is a single byte whose unsigned integer value represents the version of the fuse schemafuse_wire_length
is a single byte whose unsigned integer value represents the number of fuses in the following fuse wirefuse_wire
is a sequence of N bytes, each byte represents a single fuse and its state.- "0" (0x30) indicates the fuse is disabled
- "1" (0x31) indicates the fuse is enabled
- "r" (0x72) indicates the fuse has been removed and changing the byte to either 1 or 0 will have no effect.
To flip a fuse you find its position in the fuse wire and change it to "0" or "1" depending on the state you'd like.
You can view the current schema here.
globalShortcut
Detect keyboard events when the application does not have keyboard focus.
Process: Main
The globalShortcut
module can register/unregister a global keyboard shortcut
with the operating system so that you can customize the operations for various
shortcuts.
Note: The shortcut is global; it will work even if the app does
not have the keyboard focus. This module cannot be used before the ready
event of the app module is emitted.
const { app, globalShortcut } = require('electron')
app.whenReady().then(() => {
// Register a 'CommandOrControl+X' shortcut listener.
const ret = globalShortcut.register('CommandOrControl+X', () => {
console.log('CommandOrControl+X is pressed')
})
if (!ret) {
console.log('registration failed')
}
// Check whether a shortcut is registered.
console.log(globalShortcut.isRegistered('CommandOrControl+X'))
})
app.on('will-quit', () => {
// Unregister a shortcut.
globalShortcut.unregister('CommandOrControl+X')
// Unregister all shortcuts.
globalShortcut.unregisterAll()
})
Methods
The globalShortcut
module has the following methods:
globalShortcut.register(accelerator, callback)
accelerator
Acceleratorcallback
Function
Returns Boolean
- Whether or not the shortcut was registered successfully.
Registers a global shortcut of accelerator
. The callback
is called when
the registered shortcut is pressed by the user.
When the accelerator is already taken by other applications, this call will silently fail. This behavior is intended by operating systems, since they don't want applications to fight for global shortcuts.
The following accelerators will not be registered successfully on macOS 10.14 Mojave unless the app has been authorized as a trusted accessibility client:
- "Media Play/Pause"
- "Media Next Track"
- "Media Previous Track"
- "Media Stop"
globalShortcut.registerAll(accelerators, callback)
accelerators
String[] - an array of Accelerators.callback
Function
Registers a global shortcut of all accelerator
items in accelerators
. The callback
is called when any of the registered shortcuts are pressed by the user.
When a given accelerator is already taken by other applications, this call will silently fail. This behavior is intended by operating systems, since they don't want applications to fight for global shortcuts.
The following accelerators will not be registered successfully on macOS 10.14 Mojave unless the app has been authorized as a trusted accessibility client:
- "Media Play/Pause"
- "Media Next Track"
- "Media Previous Track"
- "Media Stop"
globalShortcut.isRegistered(accelerator)
accelerator
Accelerator
Returns Boolean
- Whether this application has registered accelerator
.
When the accelerator is already taken by other applications, this call will
still return false
. This behavior is intended by operating systems, since they
don't want applications to fight for global shortcuts.
globalShortcut.unregister(accelerator)
accelerator
Accelerator
Unregisters the global shortcut of accelerator
.
globalShortcut.unregisterAll()
Unregisters all of the global shortcuts.
Glossary
This page defines some terminology that is commonly used in Electron development.
ASAR
ASAR stands for Atom Shell Archive Format. An asar archive is a simple
tar
-like format that concatenates files into a single file. Electron can read
arbitrary files from it without unpacking the whole file.
The ASAR format was created primarily to improve performance on Windows... TODO
CRT
The C Run-time Library (CRT) is the part of the C++ Standard Library that incorporates the ISO C99 standard library. The Visual C++ libraries that implement the CRT support native code development, and both mixed native and managed code, and pure managed code for .NET development.
DMG
An Apple Disk Image is a packaging format used by macOS. DMG files are
commonly used for distributing application "installers". electron-builder
supports dmg
as a build target.
IME
Input Method Editor. A program that allows users to enter characters and symbols not found on their keyboard. For example, this allows users of Latin keyboards to input Chinese, Japanese, Korean and Indic characters.
IDL
Interface description language. Write function signatures and data types in a format that can be used to generate interfaces in Java, C++, JavaScript, etc.
IPC
IPC stands for Inter-Process Communication. Electron uses IPC to send serialized JSON messages between the main and renderer processes.
libchromiumcontent
A shared library that includes the Chromium Content module and all its dependencies (e.g., Blink, V8, etc.). Also referred to as "libcc".
main process
The main process, commonly a file named main.js
, is the entry point to every
Electron app. It controls the life of the app, from open to close. It also
manages native elements such as the Menu, Menu Bar, Dock, Tray, etc. The
main process is responsible for creating each new renderer process in the app.
The full Node API is built in.
Every app's main process file is specified in the main
property in
package.json
. This is how electron .
knows what file to execute at startup.
In Chromium, this process is referred to as the "browser process". It is renamed in Electron to avoid confusion with renderer processes.
See also: process, renderer process
MAS
Acronym for Apple's Mac App Store. For details on submitting your app to the MAS, see the Mac App Store Submission Guide.
Mojo
An IPC system for communicating intra- or inter-process, and that's important because Chrome is keen on being able to split its work into separate processes or not, depending on memory pressures etc.
See https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md
native modules
Native modules (also called addons in Node.js) are modules written in C or C++ that can be loaded into Node.js or Electron using the require() function, and used as if they were an ordinary Node.js module. They are used primarily to provide an interface between JavaScript running in Node.js and C/C++ libraries.
Native Node modules are supported by Electron, but since Electron is very likely to use a different V8 version from the Node binary installed in your system, you have to manually specify the location of Electron’s headers when building native modules.
See also Using Native Node Modules.
NSIS
Nullsoft Scriptable Install System is a script-driven Installer authoring tool for Microsoft Windows. It is released under a combination of free software licenses, and is a widely-used alternative to commercial proprietary products like InstallShield. electron-builder supports NSIS as a build target.
OSR
OSR (Off-screen rendering) can be used for loading heavy page in background and then displaying it after (it will be much faster). It allows you to render page without showing it on screen.
process
A process is an instance of a computer program that is being executed. Electron apps that make use of the main and one or many renderer process are actually running several programs simultaneously.
In Node.js and Electron, each running process has a process
object. This
object is a global that provides information about, and control over, the
current process. As a global, it is always available to applications without
using require().
See also: main process, renderer process
renderer process
The renderer process is a browser window in your app. Unlike the main process, there can be multiple of these and each is run in a separate process. They can also be hidden.
In normal browsers, web pages usually run in a sandboxed environment and are not allowed access to native resources. Electron users, however, have the power to use Node.js APIs in web pages allowing lower level operating system interactions.
See also: process, main process
Squirrel
Squirrel is an open-source framework that enables Electron apps to update automatically as new versions are released. See the autoUpdater API for info about getting started with Squirrel.
userland
This term originated in the Unix community, where "userland" or "userspace" referred to programs that run outside of the operating system kernel. More recently, the term has been popularized in the Node and npm community to distinguish between the features available in "Node core" versus packages published to the npm registry by the much larger "user" community.
Like Node, Electron is focused on having a small set of APIs that provide all the necessary primitives for developing multi-platform desktop applications. This design philosophy allows Electron to remain a flexible tool without being overly prescriptive about how it should be used. Userland enables users to create and share tools that provide additional functionality on top of what is available in "core".
V8
V8 is Google's open source JavaScript engine. It is written in C++ and is used in Google Chrome. V8 can run standalone, or can be embedded into any C++ application.
Electron builds V8 as part of Chromium and then points Node to that V8 when building it.
V8's version numbers always correspond to those of Google Chrome. Chrome 59 includes V8 5.9, Chrome 58 includes V8 5.8, etc.
webview
webview
tags are used to embed 'guest' content (such as external web pages) in
your Electron app. They are similar to iframe
s, but differ in that each
webview runs in a separate process. It doesn't have the same
permissions as your web page and all interactions between your app and
embedded content will be asynchronous. This keeps your app safe from the
embedded content.
Goma
Goma is a distributed compiler service for open-source projects such as Chromium and Android.
Electron has a deployment of a custom Goma Backend that we make available to
all Electron Maintainers. See the Access section below for details
on authentication. There is also a cache-only
Goma endpoint that will be
used by default if you do not have credentials. Requests to the cache-only
Goma will not hit our cluster, but will read from our cache and should result
in significantly faster build times.
Enabling Goma
Currently the only supported way to use Goma is to use our Build Tools.
Goma configuration is automatically included when you set up build-tools
.
If you are a maintainer and have access to our cluster, please ensure that you run
e init
with --goma=cluster
in order to configure build-tools
to use
the Goma cluster. If you have an existing config, you can just set "goma": "cluster"
in your config file.
Building with Goma
When you are using Goma you can run ninja
with a substantially higher j
value than would normally be supported by your machine.
Please do not set a value higher than 200 on Windows or Linux and 50 on macOS. We monitor Goma system usage, and users found to be abusing it with unreasonable concurrency will be de-activated.
ninja -C out/Testing electron -j 200
If you're using build-tools
, appropriate -j
values will automatically
be used for you.
Monitoring Goma
If you access http://localhost:8088 on your local machine you can monitor compile jobs as they flow through the goma system.
Access
For security and cost reasons, access to Electron's Goma cluster is currently restricted
to Electron Maintainers. If you want access please head to #access-requests
in
Slack and ping @goma-squad
to ask for access. Please be aware that being a
maintainer does not automatically grant access and access is determined on a
case by case basis.
Uptime / Support
We have automated monitoring of our Goma cluster and cache at https://status.notgoma.com
We do not provide support for usage of Goma and any issues raised asking for help / having issues will probably be closed without much reason, we do not have the capacity to handle that kind of support.
GPUFeatureStatus Object
2d_canvas
String - Canvas.flash_3d
String - Flash.flash_stage3d
String - Flash Stage3D.flash_stage3d_baseline
String - Flash Stage3D Baseline profile.gpu_compositing
String - Compositing.multiple_raster_threads
String - Multiple Raster Threads.native_gpu_memory_buffers
String - Native GpuMemoryBuffers.rasterization
String - Rasterization.video_decode
String - Video Decode.video_encode
String - Video Encode.vpx_decode
String - VPx Video Decode.webgl
String - WebGL.webgl2
String - WebGL2.
Possible values:
disabled_software
- Software only. Hardware acceleration disabled (yellow)disabled_off
- Disabled (red)disabled_off_ok
- Disabled (yellow)unavailable_software
- Software only, hardware acceleration unavailable (yellow)unavailable_off
- Unavailable (red)unavailable_off_ok
- Unavailable (yellow)enabled_readback
- Hardware accelerated but at reduced performance (yellow)enabled_force
- Hardware accelerated on all pages (green)enabled
- Hardware accelerated (green)enabled_on
- Enabled (green)enabled_force_on
- Force enabled (green)
Events
The inAppPurchase
module emits the following events:
Event: 'transactions-updated'
Emitted when one or more transactions have been updated.
Returns:
event
Eventtransactions
Transaction[] - Array ofTransaction
objects.
Methods
The inAppPurchase
module has the following methods:
inAppPurchase.purchaseProduct(productID[, quantity])
productID
String - The identifiers of the product to purchase. (The identifier ofcom.example.app.product1
isproduct1
).quantity
Integer (optional) - The number of items the user wants to purchase.
Returns Promise<Boolean>
- Returns true
if the product is valid and added to the payment queue.
You should listen for the transactions-updated
event as soon as possible and certainly before you call purchaseProduct
.
inAppPurchase.getProducts(productIDs)
productIDs
String[] - The identifiers of the products to get.
Returns Promise<Product[]>
- Resolves with an array of Product
objects.
Retrieves the product descriptions.
inAppPurchase.canMakePayments()
Returns Boolean
- whether a user can make a payment.
inAppPurchase.restoreCompletedTransactions()
Restores finished transactions. This method can be called either to install purchases on additional devices, or to restore purchases for an application that the user deleted and reinstalled.
The payment queue delivers a new transaction for each previously completed transaction that can be restored. Each transaction includes a copy of the original transaction.
inAppPurchase.getReceiptURL()
Returns String
- the path to the receipt.
inAppPurchase.finishAllTransactions()
Completes all pending transactions.
inAppPurchase.finishTransactionByDate(date)
date
String - The ISO formatted date of the transaction to finish.
Completes the pending transactions corresponding to the date.
Paid Applications Agreement
If you haven't already, you’ll need to sign the Paid Applications Agreement and set up your banking and tax information in iTunes Connect.
iTunes Connect Developer Help: Agreements, tax, and banking overview
Create Your In-App Purchases
Then, you'll need to configure your in-app purchases in iTunes Connect, and include details such as name, pricing, and description that highlights the features and functionality of your in-app purchase.
Change the CFBundleIdentifier
To test In-App Purchase in development with Electron you'll have to change the CFBundleIdentifier
in node_modules/electron/dist/Electron.app/Contents/Info.plist
. You have to replace com.github.electron
by the bundle identifier of the application you created with iTunes Connect.
<key>CFBundleIdentifier</key>
<string>com.example.app</string>
Code example
Here is an example that shows how to use In-App Purchases in Electron. You'll have to replace the product ids by the identifiers of the products created with iTunes Connect (the identifier of com.example.app.product1
is product1
). Note that you have to listen to the transactions-updated
event as soon as possible in your app.
// Main process
const { inAppPurchase } = require('electron')
const PRODUCT_IDS = ['id1', 'id2']
// Listen for transactions as soon as possible.
inAppPurchase.on('transactions-updated', (event, transactions) => {
if (!Array.isArray(transactions)) {
return
}
// Check each transaction.
transactions.forEach(function (transaction) {
const payment = transaction.payment
switch (transaction.transactionState) {
case 'purchasing':
console.log(`Purchasing ${payment.productIdentifier}...`)
break
case 'purchased': {
console.log(`${payment.productIdentifier} purchased.`)
// Get the receipt url.
const receiptURL = inAppPurchase.getReceiptURL()
console.log(`Receipt URL: ${receiptURL}`)
// Submit the receipt file to the server and check if it is valid.
// @see https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html
// ...
// If the receipt is valid, the product is purchased
// ...
// Finish the transaction.
inAppPurchase.finishTransactionByDate(transaction.transactionDate)
break
}
case 'failed':
console.log(`Failed to purchase ${payment.productIdentifier}.`)
// Finish the transaction.
inAppPurchase.finishTransactionByDate(transaction.transactionDate)
break
case 'restored':
console.log(`The purchase of ${payment.productIdentifier} has been restored.`)
break
case 'deferred':
console.log(`The purchase of ${payment.productIdentifier} has been deferred.`)
break
default:
break
}
})
})
// Check if the user is allowed to make in-app purchase.
if (!inAppPurchase.canMakePayments()) {
console.log('The user is not allowed to make in-app purchase.')
}
// Retrieve and display the product descriptions.
inAppPurchase.getProducts(PRODUCT_IDS).then(products => {
// Check the parameters.
if (!Array.isArray(products) || products.length <= 0) {
console.log('Unable to retrieve the product informations.')
return
}
// Display the name and price of each product.
products.forEach(product => {
console.log(`The price of ${product.localizedTitle} is ${product.formattedPrice}.`)
})
// Ask the user which product he/she wants to purchase.
const selectedProduct = products[0]
const selectedQuantity = 1
// Purchase the selected product.
inAppPurchase.purchaseProduct(selectedProduct.productIdentifier, selectedQuantity).then(isProductValid => {
if (!isProductValid) {
console.log('The product is not valid.')
return
}
console.log('The payment has been added to the payment queue.')
})
})
Class: IncomingMessage
Handle responses to HTTP/HTTPS requests.
Process: Main
IncomingMessage
implements the Readable Stream
interface and is therefore an EventEmitter.
Event: 'data'
Returns:
chunk
Buffer - A chunk of response body's data.
The data
event is the usual method of transferring response data into
applicative code.
Event: 'end'
Indicates that response body has ended.
Event: 'aborted'
Emitted when a request has been canceled during an ongoing HTTP transaction.
Event: 'error'
Returns:
error
Error - Typically holds an error string identifying failure root cause.
Emitted when an error was encountered while streaming response data events. For
instance, if the server closes the underlying while the response is still
streaming, an error
event will be emitted on the response object and a close
event will subsequently follow on the request object.
Instance Properties
An IncomingMessage
instance has the following readable properties:
response.statusCode
An Integer
indicating the HTTP response status code.
response.statusMessage
A String
representing the HTTP status message.
response.headers
A Record<string, string | string[]>
representing the HTTP response headers. The headers
object is
formatted as follows:
- All header names are lowercased.
- Duplicates of
age
,authorization
,content-length
,content-type
,etag
,expires
,from
,host
,if-modified-since
,if-unmodified-since
,last-modified
,location
,max-forwards
,proxy-authorization
,referer
,retry-after
,server
, oruser-agent
are discarded. set-cookie
is always an array. Duplicates are added to the array.- For duplicate
cookie
headers, the values are joined together with '; '. - For all other headers, the values are joined together with ', '.
response.httpVersion
A String
indicating the HTTP protocol version number. Typical values are '1.0'
or '1.1'. Additionally httpVersionMajor
and httpVersionMinor
are two
Integer-valued readable properties that return respectively the HTTP major and
minor version numbers.
response.httpVersionMajor
An Integer
indicating the HTTP protocol major version number.
response.httpVersionMinor
An Integer
indicating the HTTP protocol minor version number.
InputEvent Object
modifiers
String[] (optional) - An array of modifiers of the event, can beshift
,control
,ctrl
,alt
,meta
,command
,cmd
,isKeypad
,isAutoRepeat
,leftButtonDown
,middleButtonDown
,rightButtonDown
,capsLock
,numLock
,left
,right
.
Installation
To install prebuilt Electron binaries, use npm
.
The preferred method is to install Electron as a development dependency in your
app:
npm install electron --save-dev
See the Electron versioning doc for info on how to manage Electron versions in your apps.
Global Installation
You can also install the electron
command globally in your $PATH
:
npm install electron -g
Customization
If you want to change the architecture that is downloaded (e.g., ia32
on an
x64
machine), you can use the --arch
flag with npm install or set the
npm_config_arch
environment variable:
npm install --arch=ia32 electron
In addition to changing the architecture, you can also specify the platform
(e.g., win32
, linux
, etc.) using the --platform
flag:
npm install --platform=win32 electron
Proxies
If you need to use an HTTP proxy, you need to set the ELECTRON_GET_USE_PROXY
variable to any
value, plus additional environment variables depending on your host system's Node version:
Custom Mirrors and Caches
During installation, the electron
module will call out to
@electron/get
to download prebuilt binaries of
Electron for your platform. It will do so by contacting GitHub's
release download page (https://github.com/electron/electron/releases/tag/v$VERSION
,
where $VERSION
is the exact version of Electron).
If you are unable to access GitHub or you need to provide a custom build, you can do so by either providing a mirror or an existing cache directory.
Mirror
You can use environment variables to override the base URL, the path at which to
look for Electron binaries, and the binary filename. The URL used by @electron/get
is composed as follows:
url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
For instance, to use the China CDN mirror:
ELECTRON_MIRROR="https://cdn.npm.taobao.org/dist/electron/"
By default, ELECTRON_CUSTOM_DIR
is set to v$VERSION
. To change the format,
use the {{ version }}
placeholder. For example, version-{{ version }}
resolves to version-5.0.0
, {{ version }}
resolves to 5.0.0
, and
v{{ version }}
is equivalent to the default. As a more concrete example, to
use the China non-CDN mirror:
ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/"
ELECTRON_CUSTOM_DIR="{{ version }}"
The above configuration will download from URLs such as
https://npm.taobao.org/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip
.
Cache
Alternatively, you can override the local cache. @electron/get
will cache
downloaded binaries in a local directory to not stress your network. You can use
that cache folder to provide custom builds of Electron or to avoid making contact
with the network at all.
- Linux:
$XDG_CACHE_HOME
or~/.cache/electron/
- macOS:
~/Library/Caches/electron/
- Windows:
$LOCALAPPDATA/electron/Cache
or~/AppData/Local/electron/Cache/
On environments that have been using older versions of Electron, you might find the
cache also in ~/.electron
.
You can also override the local cache location by providing a electron_config_cache
environment variable.
The cache contains the version's official zip file as well as a checksum, stored as a text file. A typical cache might look like this:
├── httpsgithub.comelectronelectronreleasesdownloadv1.7.9electron-v1.7.9-darwin-x64.zip
│ └── electron-v1.7.9-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.7.9SHASUMS256.txt
│ └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.1electron-v1.8.1-darwin-x64.zip
│ └── electron-v1.8.1-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.1SHASUMS256.txt
│ └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.1electron-v1.8.2-beta.1-darwin-x64.zip
│ └── electron-v1.8.2-beta.1-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.1SHASUMS256.txt
│ └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.2electron-v1.8.2-beta.2-darwin-x64.zip
│ └── electron-v1.8.2-beta.2-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.2SHASUMS256.txt
│ └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.3electron-v1.8.2-beta.3-darwin-x64.zip
│ └── electron-v1.8.2-beta.3-darwin-x64.zip
└── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.3SHASUMS256.txt
└── SHASUMS256.txt
Skip binary download
When installing the electron
NPM package, it automatically downloads the electron binary.
This can sometimes be unnecessary, e.g. in a CI environment, when testing another component.
To prevent the binary from being downloaded when you install all npm dependencies you can set the environment variable ELECTRON_SKIP_BINARY_DOWNLOAD
.
E.g.:
ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install
Troubleshooting
When running npm install electron
, some users occasionally encounter
installation errors.
In almost all cases, these errors are the result of network problems and not
actual issues with the electron
npm package. Errors like ELIFECYCLE
,
EAI_AGAIN
, ECONNRESET
, and ETIMEDOUT
are all indications of such
network problems. The best resolution is to try switching networks, or
wait a bit and try installing again.
You can also attempt to download Electron directly from
electron/electron/releases
if installing via npm
is failing.
If installation fails with an EACCESS
error you may need to
fix your npm permissions.
If the above error persists, the unsafe-perm flag may need to be set to true:
sudo npm install electron --unsafe-perm=true
On slower networks, it may be advisable to use the --verbose
flag in order to
show download progress:
npm install --verbose electron
If you need to force a re-download of the asset and the SHASUM file set the
force_no_cache
environment variable to true
.
IOCounters Object
readOperationCount
Number - The number of I/O read operations.writeOperationCount
Number - The number of I/O write operations.otherOperationCount
Number - Then number of I/O other operations.readTransferCount
Number - The number of I/O read transfers.writeTransferCount
Number - The number of I/O write transfers.otherTransferCount
Number - Then number of I/O other transfers.
ipcMain
Communicate asynchronously from the main process to renderer processes.
Process: Main
The ipcMain
module is an Event Emitter. When used in the main
process, it handles asynchronous and synchronous messages sent from a renderer
process (web page). Messages sent from a renderer will be emitted to this
module.
Sending Messages
It is also possible to send messages from the main process to the renderer process, see webContents.send for more information.
- When sending a message, the event name is the
channel
. - To reply to a synchronous message, you need to set
event.returnValue
. - To send an asynchronous message back to the sender, you can use
event.reply(...)
. This helper method will automatically handle messages coming from frames that aren't the main frame (e.g. iframes) whereasevent.sender.send(...)
will always send to the main frame.
An example of sending and handling messages between the render and main processes:
// In main process.
const { ipcMain } = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.reply('asynchronous-reply', 'pong')
})
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.returnValue = 'pong'
})
// In renderer process (web page).
const { ipcRenderer } = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"
ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')
Methods
The ipcMain
module has the following method to listen for events:
ipcMain.on(channel, listener)
channel
Stringlistener
Functionevent
IpcMainEvent...args
any[]
Listens to channel
, when a new message arrives listener
would be called with
listener(event, args...)
.
ipcMain.once(channel, listener)
channel
Stringlistener
Functionevent
IpcMainEvent...args
any[]
Adds a one time listener
function for the event. This listener
is invoked
only the next time a message is sent to channel
, after which it is removed.
ipcMain.removeListener(channel, listener)
channel
Stringlistener
Function...args
any[]
Removes the specified listener
from the listener array for the specified
channel
.
ipcMain.removeAllListeners([channel])
channel
String (optional)
Removes listeners of the specified channel
.
ipcMain.handle(channel, listener)
channel
Stringlistener
Function<Promise\| any> event
IpcMainInvokeEvent...args
any[]
Adds a handler for an invoke
able IPC. This handler will be called whenever a
renderer calls ipcRenderer.invoke(channel, ...args)
.
If listener
returns a Promise, the eventual result of the promise will be
returned as a reply to the remote caller. Otherwise, the return value of the
listener will be used as the value of the reply.
// Main process
ipcMain.handle('my-invokable-ipc', async (event, ...args) => {
const result = await somePromise(...args)
return result
})
// Renderer process
async () => {
const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2)
// ...
}
The event
that is passed as the first argument to the handler is the same as
that passed to a regular event listener. It includes information about which
WebContents is the source of the invoke request.
ipcMain.handleOnce(channel, listener)
channel
Stringlistener
Function<Promise\| any> event
IpcMainInvokeEvent...args
any[]
Handles a single invoke
able IPC message, then removes the listener. See
ipcMain.handle(channel, listener)
.
IpcMainEvent object
The documentation for the event
object passed to the callback
can be found
in the ipc-main-event
structure docs.
IpcMainInvokeEvent object
The documentation for the event
object passed to handle
callbacks can be
found in the ipc-main-invoke-event
structure docs.
IpcMainEvent Object extends Event
processId
Integer - The internal ID of the renderer process that sent this messageframeId
Integer - The ID of the renderer frame that sent this messagereturnValue
any - Set this to the value to be returned in a synchronous messagesender
WebContents - Returns thewebContents
that sent the messageports
MessagePortMain[] - A list of MessagePorts that were transferred with this messagereply
Function - A function that will send an IPC message to the renderer frame that sent the original message that you are currently handling. You should use this method to "reply" to the sent message in order to guarantee the reply will go to the correct process and frame.channel
String...args
any[]
IpcMainInvokeEvent Object extends Event
processId
Integer - The internal ID of the renderer process that sent this messageframeId
Integer - The ID of the renderer frame that sent this messagesender
WebContents - Returns thewebContents
that sent the message
ipcRenderer
Communicate asynchronously from a renderer process to the main process.
Process: Renderer
The ipcRenderer
module is an EventEmitter. It provides a few
methods so you can send synchronous and asynchronous messages from the render
process (web page) to the main process. You can also receive replies from the
main process.
See ipcMain for code examples.
Methods
The ipcRenderer
module has the following method to listen for events and send messages:
ipcRenderer.on(channel, listener)
channel
Stringlistener
Functionevent
IpcRendererEvent...args
any[]
Listens to channel
, when a new message arrives listener
would be called with
listener(event, args...)
.
ipcRenderer.once(channel, listener)
channel
Stringlistener
Functionevent
IpcRendererEvent...args
any[]
Adds a one time listener
function for the event. This listener
is invoked
only the next time a message is sent to channel
, after which it is removed.
ipcRenderer.removeListener(channel, listener)
channel
Stringlistener
Function...args
any[]
Removes the specified listener
from the listener array for the specified
channel
.
ipcRenderer.removeAllListeners(channel)
channel
String
Removes all listeners, or those of the specified channel
.
ipcRenderer.send(channel, ...args)
channel
String...args
any[]
Send an asynchronous message to the main process via channel
, along with
arguments. Arguments will be serialized with the Structured Clone
Algorithm, just like window.postMessage
, so prototype chains will not be
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
throw an exception.
NOTE: Sending non-standard JavaScript types such as DOM objects or special Electron objects is deprecated, and will begin throwing an exception starting with Electron 9.
The main process handles it by listening for channel
with the
ipcMain
module.
If you need to transfer a MessagePort
to the main process, use ipcRenderer.postMessage
.
If you want to receive a single response from the main process, like the result of a method call, consider using ipcRenderer.invoke
.
ipcRenderer.invoke(channel, ...args)
channel
String...args
any[]
Returns Promise<any>
- Resolves with the response from the main process.
Send a message to the main process via channel
and expect a result
asynchronously. Arguments will be serialized with the Structured Clone
Algorithm, just like window.postMessage
, so prototype chains will not be
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
throw an exception.
NOTE: Sending non-standard JavaScript types such as DOM objects or special Electron objects is deprecated, and will begin throwing an exception starting with Electron 9.
The main process should listen for channel
with
ipcMain.handle()
.
For example:
// Renderer process
ipcRenderer.invoke('some-name', someArgument).then((result) => {
// ...
})
// Main process
ipcMain.handle('some-name', async (event, someArgument) => {
const result = await doSomeWork(someArgument)
return result
})
If you need to transfer a MessagePort
to the main process, use ipcRenderer.postMessage
.
If you do not need a response to the message, consider using ipcRenderer.send
.
ipcRenderer.sendSync(channel, ...args)
channel
String...args
any[]
Returns any
- The value sent back by the ipcMain
handler.
Send a message to the main process via channel
and expect a result
synchronously. Arguments will be serialized with the Structured Clone
Algorithm, just like window.postMessage
, so prototype chains will not be
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
throw an exception.
NOTE: Sending non-standard JavaScript types such as DOM objects or special Electron objects is deprecated, and will begin throwing an exception starting with Electron 9.
The main process handles it by listening for channel
with ipcMain
module,
and replies by setting event.returnValue
.
⚠️ WARNING: Sending a synchronous message will block the whole renderer process until the reply is received, so use this method only as a last resort. It's much better to use the asynchronous version,
invoke()
.
ipcRenderer.postMessage(channel, message, [transfer])
channel
Stringmessage
anytransfer
MessagePort[] (optional)
Send a message to the main process, optionally transferring ownership of zero
or more MessagePort
objects.
The transferred MessagePort
objects will be available in the main process as
MessagePortMain
objects by accessing the ports
property of the emitted event.
For example:
// Renderer process
const { port1, port2 } = new MessageChannel()
ipcRenderer.postMessage('port', { message: 'hello' }, [port1])
// Main process
ipcMain.on('port', (e, msg) => {
const [port] = e.ports
// ...
})
For more information on using MessagePort
and MessageChannel
, see the MDN
documentation.
ipcRenderer.sendTo(webContentsId, channel, ...args)
webContentsId
Numberchannel
String...args
any[]
Sends a message to a window with webContentsId
via channel
.
ipcRenderer.sendToHost(channel, ...args)
channel
String...args
any[]
Like ipcRenderer.send
but the event will be sent to the <webview>
element in
the host page instead of the main process.
Event object
The documentation for the event
object passed to the callback
can be found
in the ipc-renderer-event
structure docs.
IpcRendererEvent Object extends Event
sender
IpcRenderer - TheIpcRenderer
instance that emitted the event originallysenderId
Integer - ThewebContents.id
that sent the message, you can callevent.sender.sendTo(event.senderId, ...)
to reply to the message, see ipcRenderer.sendTo for more information. This only applies to messages sent from a different renderer. Messages sent directly from the main process setevent.senderId
to0
.ports
MessagePort[] - A list of MessagePorts that were transferred with this message
How to Contribute to Issues
For any issue, there are fundamentally three ways an individual can contribute:
- By opening the issue for discussion: If you believe that you have found
a new bug in Electron, you should report it by creating a new issue in
the
electron/electron
issue tracker. - By helping to triage the issue: You can do this either by providing assistive details (a reproducible test case that demonstrates a bug) or by providing suggestions to address the issue.
- By helping to resolve the issue: This can be done by demonstrating
that the issue is not a bug or is fixed; but more often, by opening
a pull request that changes the source in
electron/electron
in a concrete and reviewable manner.
Asking for General Help
"Finding Support" has a list of resources for getting programming help, reporting security issues, contributing, and more. Please use the issue tracker for bugs only!
Submitting a Bug Report
To submit a bug report:
When opening a new issue in the electron/electron
issue tracker, users
will be presented with a template
that should be filled in.
If you believe that you have found a bug in Electron, please fill out the template to the best of your ability.
The two most important pieces of information needed to evaluate the report are a description of the bug and a simple test case to recreate it. It is easier to fix a bug if it can be reproduced.
See How to create a Minimal, Complete, and Verifiable example.
Triaging a Bug Report
It's common for open issues to involve discussion. Some contributors may have differing opinions, including whether the behavior is a bug or feature. This discussion is part of the process and should be kept focused, helpful, and professional.
Terse responses that provide neither additional context nor supporting detail are not helpful or professional. To many, such responses are annoying and unfriendly.
Contributors are encouraged to solve issues collaboratively and help one another make progress. If you encounter an issue that you feel is invalid, or which contains incorrect information, explain why you feel that way with additional supporting context, and be willing to be convinced that you may be wrong. By doing so, we can often reach the correct outcome faster.
Resolving a Bug Report
Most issues are resolved by opening a pull request. The process for opening and reviewing a pull request is similar to that of opening and triaging issues, but carries with it a necessary review and approval workflow that ensures that the proposed changes meet the minimal quality and functional guidelines of the Electron project.
JumpListCategory Object
type
String (optional) - One of the following:tasks
- Items in this category will be placed into the standardTasks
category. There can be only one such category, and it will always be displayed at the bottom of the Jump List.frequent
- Displays a list of files frequently opened by the app, the name of the category and its items are set by Windows.recent
- Displays a list of files recently opened by the app, the name of the category and its items are set by Windows. Items may be added to this category indirectly usingapp.addRecentDocument(path)
.custom
- Displays tasks or file links,name
must be set by the app.
name
String (optional) - Must be set iftype
iscustom
, otherwise it should be omitted.items
JumpListItem[] (optional) - Array ofJumpListItem
objects iftype
istasks
orcustom
, otherwise it should be omitted.
Note: If a JumpListCategory
object has neither the type
nor the name
property set then its type
is assumed to be tasks
. If the name
property
is set but the type
property is omitted then the type
is assumed to be
custom
.
JumpListItem Object
type
String (optional) - One of the following:task
- A task will launch an app with specific arguments.separator
- Can be used to separate items in the standardTasks
category.file
- A file link will open a file using the app that created the Jump List, for this to work the app must be registered as a handler for the file type (though it doesn't have to be the default handler).
path
String (optional) - Path of the file to open, should only be set iftype
isfile
.program
String (optional) - Path of the program to execute, usually you should specifyprocess.execPath
which opens the current program. Should only be set iftype
istask
.args
String (optional) - The command line arguments whenprogram
is executed. Should only be set iftype
istask
.title
String (optional) - The text to be displayed for the item in the Jump List. Should only be set iftype
istask
.description
String (optional) - Description of the task (displayed in a tooltip). Should only be set iftype
istask
.iconPath
String (optional) - The absolute path to an icon to be displayed in a Jump List, which can be an arbitrary resource file that contains an icon (e.g..ico
,.exe
,.dll
). You can usually specifyprocess.execPath
to show the program icon.iconIndex
Number (optional) - The index of the icon in the resource file. If a resource file contains multiple icons this value can be used to specify the zero-based index of the icon that should be displayed for this task. If a resource file contains only one icon, this property should be set to zero.workingDirectory
String (optional) - The working directory. Default is empty.
KeyboardEvent Object
ctrlKey
Boolean (optional) - whether the Control key was used in an accelerator to trigger the EventmetaKey
Boolean (optional) - whether a meta key was used in an accelerator to trigger the EventshiftKey
Boolean (optional) - whether a Shift key was used in an accelerator to trigger the EventaltKey
Boolean (optional) - whether an Alt key was used in an accelerator to trigger the EventtriggeredByAccelerator
Boolean (optional) - whether an accelerator was used to trigger the event as opposed to another user gesture like mouse click
KeyboardInputEvent Object extends InputEvent
type
String - The type of the event, can bekeyDown
,keyUp
orchar
.keyCode
String - The character that will be sent as the keyboard event. Should only use the valid key codes in Accelerator.
Overview
This feature allows you to configure local and global keyboard shortcuts for your Electron application.
Local Shortcuts
Local keyboard shortcuts are triggered only when the application is focused.
To configure a local keyboard shortcut, you need to specify an accelerator
property when creating a MenuItem within the Menu module.
Starting with a working application from the
Quick Start Guide, update the main.js
file with the
following lines:
const { Menu, MenuItem } = require('electron')
const menu = new Menu()
menu.append(new MenuItem({
label: 'Electron',
submenu: [{
role: 'help',
accelerator: process.platform === 'darwin' ? 'Alt+Cmd+I' : 'Alt+Shift+I',
click: () => { console.log('Electron rocks!') }
}]
}))
Menu.setApplicationMenu(menu)
NOTE: In the code above, you can see that the accelerator differs based on the user's operating system. For MacOS, it is
Alt+Cmd+I
, whereas for Linux and Windows, it isAlt+Shift+I
.
After launching the Electron application, you should see the application menu along with the local shortcut you just defined:
If you click Help
or press the defined accelerator and then open the terminal
that you ran your Electron application from, you will see the message that was
generated after triggering the click
event: "Electron rocks!".
Global Shortcuts
To configure a global keyboard shortcut, you need to use the globalShortcut module to detect keyboard events even when the application does not have keyboard focus.
Starting with a working application from the
Quick Start Guide, update the main.js
file with the
following lines:
const { app, globalShortcut } = require('electron')
app.whenReady().then(() => {
globalShortcut.register('Alt+CommandOrControl+I', () => {
console.log('Electron loves global shortcuts!')
})
}).then(createWindow)
NOTE: In the code above, the
CommandOrControl
combination usesCommand
on macOS andControl
on Windows/Linux.
After launching the Electron application, if you press the defined key combination then open the terminal that you ran your Electron application from, you will see that Electron loves global shortcuts!
Using web APIs
If you want to handle keyboard shortcuts within a BrowserWindow, you can
listen for the keyup
and keydown
DOM events inside the
renderer process using the addEventListener() API.
window.addEventListener('keyup', doSomething, true)
Note the third parameter true
indicates that the listener will always receive
key presses before other listeners so they can't have stopPropagation()
called on them.
Intercepting events in the main process
The before-input-event
event
is emitted before dispatching keydown
and keyup
events in the page. It can
be used to catch and handle custom shortcuts that are not visible in the menu.
Example
Starting with a working application from the
Quick Start Guide, update the main.js
file with the
following lines:
const { app, BrowserWindow } = require('electron')
app.whenReady().then(() => {
const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } })
win.loadFile('index.html')
win.webContents.on('before-input-event', (event, input) => {
if (input.control && input.key.toLowerCase() === 'i') {
console.log('Pressed Control+I')
event.preventDefault()
}
})
})
After launching the Electron application, if you open the terminal that you ran
your Electron application from and press Ctrl+I
key combination, you will
see that this key combination was successfully intercepted.
Using third-party libraries
If you don't want to do manual shortcut parsing, there are libraries that do
advanced key detection, such as mousetrap. Below are examples of usage of the
mousetrap
running in the Renderer process:
Mousetrap.bind('4', () => { console.log('4') })
Mousetrap.bind('?', () => { console.log('show shortcuts!') })
Mousetrap.bind('esc', () => { console.log('escape') }, 'keyup')
// combinations
Mousetrap.bind('command+shift+k', () => { console.log('command shift k') })
// map multiple combinations to the same callback
Mousetrap.bind(['command+k', 'ctrl+k'], () => {
console.log('command k or control k')
// return false to prevent default behavior and stop event from bubbling
return false
})
// gmail style sequences
Mousetrap.bind('g i', () => { console.log('go to inbox') })
Mousetrap.bind('* a', () => { console.log('select all') })
// konami code!
Mousetrap.bind('up up down down left right left right b a enter', () => {
console.log('konami code')
})
Overview
On many Linux environments, you can add custom entries to the system launcher
by modifying the .desktop
file. For Canonical's Unity documentation, see
Adding Shortcuts to a Launcher. For details on a more generic
implementation, see the freedesktop.org Specification.
NOTE: The screenshot above is an example of launcher shortcuts in Audacious audio player
To create a shortcut, you need to provide Name
and Exec
properties for the
entry you want to add to the shortcut menu. Unity will execute the command
defined in the Exec
field after the user clicked the shortcut menu item.
An example of the .desktop
file may look as follows:
Actions=PlayPause;Next;Previous
[Desktop Action PlayPause]
Name=Play-Pause
Exec=audacious -t
OnlyShowIn=Unity;
[Desktop Action Next]
Name=Next
Exec=audacious -f
OnlyShowIn=Unity;
[Desktop Action Previous]
Name=Previous
Exec=audacious -r
OnlyShowIn=Unity;
The preferred way for Unity to instruct your application on what to do is using
parameters. You can find them in your application in the global variable
process.argv
.
Locales
Locale values returned by
app.getLocale()
.
Electron uses Chromium's l10n_util
library to fetch the locale. Possible
values are listed below:
Language Code | Language Name |
---|---|
af | Afrikaans |
am | Amharic |
ar | Arabic |
az | Azerbaijani |
be | Belarusian |
bg | Bulgarian |
bh | Bihari |
bn | Bengali |
br | Breton |
bs | Bosnian |
ca | Catalan |
co | Corsican |
cs | Czech |
cy | Welsh |
da | Danish |
de | German |
de-AT | German (Austria) |
de-CH | German (Switzerland) |
de-DE | German (Germany) |
el | Greek |
en | English |
en-AU | English (Australia) |
en-CA | English (Canada) |
en-GB | English (UK) |
en-NZ | English (New Zealand) |
en-US | English (US) |
en-ZA | English (South Africa) |
eo | Esperanto |
es | Spanish |
es-419 | Spanish (Latin America) |
et | Estonian |
eu | Basque |
fa | Persian |
fi | Finnish |
fil | Filipino |
fo | Faroese |
fr | French |
fr-CA | French (Canada) |
fr-CH | French (Switzerland) |
fr-FR | French (France) |
fy | Frisian |
ga | Irish |
gd | Scots Gaelic |
gl | Galician |
gn | Guarani |
gu | Gujarati |
ha | Hausa |
haw | Hawaiian |
he | Hebrew |
hi | Hindi |
hr | Croatian |
hu | Hungarian |
hy | Armenian |
ia | Interlingua |
id | Indonesian |
is | Icelandic |
it | Italian |
it-CH | Italian (Switzerland) |
it-IT | Italian (Italy) |
ja | Japanese |
jw | Javanese |
ka | Georgian |
kk | Kazakh |
km | Cambodian |
kn | Kannada |
ko | Korean |
ku | Kurdish |
ky | Kyrgyz |
la | Latin |
ln | Lingala |
lo | Laothian |
lt | Lithuanian |
lv | Latvian |
mk | Macedonian |
ml | Malayalam |
mn | Mongolian |
mo | Moldavian |
mr | Marathi |
ms | Malay |
mt | Maltese |
nb | Norwegian (Bokmal) |
ne | Nepali |
nl | Dutch |
nn | Norwegian (Nynorsk) |
no | Norwegian |
oc | Occitan |
om | Oromo |
or | Oriya |
pa | Punjabi |
pl | Polish |
ps | Pashto |
pt | Portuguese |
pt-BR | Portuguese (Brazil) |
pt-PT | Portuguese (Portugal) |
qu | Quechua |
rm | Romansh |
ro | Romanian |
ru | Russian |
sd | Sindhi |
sh | Serbo-Croatian |
si | Sinhalese |
sk | Slovak |
sl | Slovenian |
sn | Shona |
so | Somali |
sq | Albanian |
sr | Serbian |
st | Sesotho |
su | Sundanese |
sv | Swedish |
sw | Swahili |
ta | Tamil |
te | Telugu |
tg | Tajik |
th | Thai |
ti | Tigrinya |
tk | Turkmen |
to | Tonga |
tr | Turkish |
tt | Tatar |
tw | Twi |
ug | Uighur |
uk | Ukrainian |
ur | Urdu |
uz | Uzbek |
vi | Vietnamese |
xh | Xhosa |
yi | Yiddish |
yo | Yoruba |
zh | Chinese |
zh-CN | Chinese (Simplified) |
zh-TW | Chinese (Traditional) |
zu | Zulu |
Mac App Store Submission Guide
Since v0.34.0, Electron allows submitting packaged apps to the Mac App Store (MAS). This guide provides information on: how to submit your app and the limitations of the MAS build.
Note: Submitting an app to Mac App Store requires enrolling in the Apple Developer Program, which costs money.
How to Submit Your App
The following steps introduce a simple way to submit your app to Mac App Store. However, these steps do not ensure your app will be approved by Apple; you still need to read Apple's Submitting Your App guide on how to meet the Mac App Store requirements.
Get Certificate
To submit your app to the Mac App Store, you first must get a certificate from Apple. You can follow these existing guides on web.
Get Team ID
Before signing your app, you need to know the Team ID of your account. To locate your Team ID, Sign in to Apple Developer Center, and click Membership in the sidebar. Your Team ID appears in the Membership Information section under the team name.
Sign Your App
After finishing the preparation work, you can package your app by following Application Distribution, and then proceed to signing your app.
First, you have to add a ElectronTeamID
key to your app's Info.plist
, which
has your Team ID as its value:
<plist version="1.0">
<dict>
...
<key>ElectronTeamID</key>
<string>TEAM_ID</string>
</dict>
</plist>
Then, you need to prepare three entitlements files.
child.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
</dict>
</plist>
parent.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>TEAM_ID.your.bundle.id</string>
</array>
</dict>
</plist>
loginhelper.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
You have to replace TEAM_ID
with your Team ID, and replace your.bundle.id
with the Bundle ID of your app.
And then sign your app with the following script:
#!/bin/bash
# Name of your app.
APP="YourApp"
# The path of your app to sign.
APP_PATH="/path/to/YourApp.app"
# The path to the location you want to put the signed package.
RESULT_PATH="~/Desktop/$APP.pkg"
# The name of certificates you requested.
APP_KEY="3rd Party Mac Developer Application: Company Name (APPIDENTITY)"
INSTALLER_KEY="3rd Party Mac Developer Installer: Company Name (APPIDENTITY)"
# The path of your plist files.
CHILD_PLIST="/path/to/child.plist"
PARENT_PLIST="/path/to/parent.plist"
LOGINHELPER_PLIST="/path/to/loginhelper.plist"
FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libnode.dylib"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/"
codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/Contents/MacOS/$APP Login Helper"
codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP"
codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH"
productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH"
If you are new to app sandboxing under macOS, you should also read through Apple's Enabling App Sandbox to have a basic idea, then add keys for the permissions needed by your app to the entitlements files.
Apart from manually signing your app, you can also choose to use the electron-osx-sign module to do the job.
Sign Native Modules
Native modules used in your app also need to be signed. If using electron-osx-sign, be sure to include the path to the built binaries in the argument list:
electron-osx-sign YourApp.app YourApp.app/Contents/Resources/app/node_modules/nativemodule/build/release/nativemodule
Also note that native modules may have intermediate files produced which should
not be included (as they would also need to be signed). If you use
electron-packager before version 8.1.0, add
--ignore=.+\.o$
to your build step to ignore these files. Versions 8.1.0 and
later ignore those files by default.
Upload Your App
After signing your app, you can use Application Loader to upload it to iTunes Connect for processing, making sure you have created a record before uploading.
Submit Your App for Review
After these steps, you can submit your app for review.
Limitations of MAS Build
In order to satisfy all requirements for app sandboxing, the following modules have been disabled in the MAS build:
crashReporter
autoUpdater
and the following behaviors have been changed:
- Video capture may not work for some machines.
- Certain accessibility features may not work.
- Apps will not be aware of DNS changes.
Also, due to the usage of app sandboxing, the resources which can be accessed by the app are strictly limited; you can read App Sandboxing for more information.
Additional Entitlements
Depending on which Electron APIs your app uses, you may need to add additional
entitlements to your parent.plist
file to be able to use these APIs from your
app's Mac App Store build.
Network Access
Enable outgoing network connections to allow your app to connect to a server:
<key>com.apple.security.network.client</key>
<true/>
Enable incoming network connections to allow your app to open a network listening socket:
<key>com.apple.security.network.server</key>
<true/>
See the Enabling Network Access documentation for more details.
dialog.showOpenDialog
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
See the Enabling User-Selected File Access documentation for more details.
dialog.showSaveDialog
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
See the Enabling User-Selected File Access documentation for more details.
Cryptographic Algorithms Used by Electron
Depending on the countries in which you are releasing your app, you may be required to provide information on the cryptographic algorithms used in your software. See the encryption export compliance docs for more information.
Electron uses following cryptographic algorithms:
- AES - NIST SP 800-38A, NIST SP 800-38D, RFC 3394
- HMAC - FIPS 198-1
- ECDSA - ANS X9.62–2005
- ECDH - ANS X9.63–2001
- HKDF - NIST SP 800-56C
- PBKDF2 - RFC 2898
- RSA - RFC 3447
- SHA - FIPS 180-4
- Blowfish - https://www.schneier.com/cryptography/blowfish/
- CAST - RFC 2144, RFC 2612
- DES - FIPS 46-3
- DH - RFC 2631
- DSA - ANSI X9.30
- EC - SEC 1
- IDEA - "On the Design and Security of Block Ciphers" book by X. Lai
- MD2 - RFC 1319
- MD4 - RFC 6150
- MD5 - RFC 1321
- MDC2 - ISO/IEC 10118-2
- RC2 - RFC 2268
- RC4 - RFC 4345
- RC5 - https://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf
- RIPEMD - ISO/IEC 10118-3
Overview
Electron has APIs to configure the app's icon in the macOS Dock. A macOS-only API exists to create a custom dock menu, but Electron also uses the app dock icon as the entry point for cross-platform features like recent documents and application progress.
The custom dock is commonly used to add shortcuts to tasks the user wouldn't want to open the whole app window for.
Dock menu of Terminal.app:
To set your custom dock menu, you need to use the
app.dock.setMenu
API,
which is only available on macOS.
Example
Starting with a working application from the
Quick Start Guide, update the main.js
file with the
following lines:
const { app, Menu } = require('electron')
const dockMenu = Menu.buildFromTemplate([
{
label: 'New Window',
click () { console.log('New Window') }
}, {
label: 'New Window with Settings',
submenu: [
{ label: 'Basic' },
{ label: 'Pro' }
]
},
{ label: 'New Command...' }
])
app.whenReady().then(() => {
app.dock.setMenu(dockMenu)
})
After launching the Electron application, right click the application icon. You should see the custom menu you just defined:
MemoryInfo Object
workingSetSize
Integer - The amount of memory currently pinned to actual physical RAM.peakWorkingSetSize
Integer - The maximum amount of memory that has ever been pinned to actual physical RAM.privateBytes
Integer (optional) Windows - The amount of memory not shared by other processes, such as JS heap or HTML content.
Note that all statistics are reported in Kilobytes.
MemoryUsageDetails Object
count
Numbersize
NumberliveSize
Number
new Menu()
Creates a new menu.
Static Methods
The Menu
class has the following static methods:
Menu.setApplicationMenu(menu)
menu
Menu | null
Sets menu
as the application menu on macOS. On Windows and Linux, the
menu
will be set as each window's top menu.
Also on Windows and Linux, you can use a &
in the top-level item name to
indicate which letter should get a generated accelerator. For example, using
&File
for the file menu would result in a generated Alt-F
accelerator that
opens the associated menu. The indicated character in the button label gets an
underline. The &
character is not displayed on the button label.
Passing null
will suppress the default menu. On Windows and Linux,
this has the additional effect of removing the menu bar from the window.
Note: The default menu will be created automatically if the app does not set one.
It contains standard items such as File
, Edit
, View
, Window
and Help
.
Menu.getApplicationMenu()
Returns Menu | null
- The application menu, if set, or null
, if not set.
Note: The returned Menu
instance doesn't support dynamic addition or
removal of menu items. Instance properties can still
be dynamically modified.
Menu.sendActionToFirstResponder(action)
macOS
action
String
Sends the action
to the first responder of application. This is used for
emulating default macOS menu behaviors. Usually you would use the
role
property of a MenuItem
.
See the macOS Cocoa Event Handling Guide for more information on macOS' native actions.
Menu.buildFromTemplate(template)
template
(MenuItemConstructorOptions | MenuItem)[]
Returns Menu
Generally, the template
is an array of options
for constructing a
MenuItem. The usage can be referenced above.
You can also attach other fields to the element of the template
and they will become properties of the constructed menu items.
Instance Methods
The menu
object has the following instance methods:
menu.popup([options])
options
Object (optional)window
BrowserWindow (optional) - Default is the focused window.x
Number (optional) - Default is the current mouse cursor position. Must be declared ify
is declared.y
Number (optional) - Default is the current mouse cursor position. Must be declared ifx
is declared.positioningItem
Number (optional) macOS - The index of the menu item to be positioned under the mouse cursor at the specified coordinates. Default is -1.callback
Function (optional) - Called when menu is closed.
Pops up this menu as a context menu in the BrowserWindow
.
menu.closePopup([browserWindow])
browserWindow
BrowserWindow (optional) - Default is the focused window.
Closes the context menu in the browserWindow
.
menu.insert(pos, menuItem)
pos
IntegermenuItem
MenuItem
Inserts the menuItem
to the pos
position of the menu.
Instance Events
Objects created with new Menu
or returned by Menu.buildFromTemplate
emit the following events:
Note: Some events are only available on specific operating systems and are labeled as such.
Event: 'menu-will-close'
Returns:
event
Event
Emitted when a popup is closed either manually or with menu.closePopup()
.
Instance Properties
menu
objects also have the following properties:
menu.items
A MenuItem[]
array containing the menu's items.
Each Menu
consists of multiple MenuItem
s and each MenuItem
can have a submenu.
Examples
The Menu
class is only available in the main process, but you can also use it
in the render process via the remote
module.
Main process
An example of creating the application menu in the main process with the simple template API:
const { app, Menu } = require('electron')
const isMac = process.platform === 'darwin'
const template = [
// { role: 'appMenu' }
...(isMac ? [{
label: app.name,
submenu: [
{ role: 'about' },
{ type: 'separator' },
{ role: 'services' },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideothers' },
{ role: 'unhide' },
{ type: 'separator' },
{ role: 'quit' }
]
}] : []),
// { role: 'fileMenu' }
{
label: 'File',
submenu: [
isMac ? { role: 'close' } : { role: 'quit' }
]
},
// { role: 'editMenu' }
{
label: 'Edit',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
...(isMac ? [
{ role: 'pasteAndMatchStyle' },
{ role: 'delete' },
{ role: 'selectAll' },
{ type: 'separator' },
{
label: 'Speech',
submenu: [
{ role: 'startSpeaking' },
{ role: 'stopSpeaking' }
]
}
] : [
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
])
]
},
// { role: 'viewMenu' }
{
label: 'View',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]
},
// { role: 'windowMenu' }
{
label: 'Window',
submenu: [
{ role: 'minimize' },
{ role: 'zoom' },
...(isMac ? [
{ type: 'separator' },
{ role: 'front' },
{ type: 'separator' },
{ role: 'window' }
] : [
{ role: 'close' }
])
]
},
{
role: 'help',
submenu: [
{
label: 'Learn More',
click: async () => {
const { shell } = require('electron')
await shell.openExternal('https://electronjs.org')
}
}
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
Render process
Below is an example of creating a menu dynamically in a web page
(render process) by using the remote
module, and showing it when
the user right clicks the page:
<!-- index.html -->
<script>
const { remote } = require('electron')
const { Menu, MenuItem } = remote
const menu = new Menu()
menu.append(new MenuItem({ label: 'MenuItem1', click() { console.log('item 1 clicked') } }))
menu.append(new MenuItem({ type: 'separator' }))
menu.append(new MenuItem({ label: 'MenuItem2', type: 'checkbox', checked: true }))
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
menu.popup({ window: remote.getCurrentWindow() })
}, false)
</script>
Notes on macOS Application Menu
macOS has a completely different style of application menu from Windows and Linux. Here are some notes on making your app's menu more native-like.
Standard Menus
On macOS there are many system-defined standard menus, like the Services
and
Windows
menus. To make your menu a standard menu, you should set your menu's
role
to one of the following and Electron will recognize them and make them
become standard menus:
window
help
services
Standard Menu Item Actions
macOS has provided standard actions for some menu items, like About xxx
,
Hide xxx
, and Hide Others
. To set the action of a menu item to a standard
action, you should set the role
attribute of the menu item.
Main Menu's Name
On macOS the label of the application menu's first item is always your app's
name, no matter what label you set. To change it, modify your app bundle's
Info.plist
file. See
About Information Property List Files
for more information.
Setting Menu for Specific Browser Window (Linux Windows)
The setMenu
method of browser windows can set the menu of certain
browser windows.
Menu Item Position
You can make use of before
, after
, beforeGroupContaining
, afterGroupContaining
and id
to control how the item will be placed when building a menu with Menu.buildFromTemplate
.
before
- Inserts this item before the item with the specified label. If the referenced item doesn't exist the item will be inserted at the end of the menu. Also implies that the menu item in question should be placed in the same “group” as the item.after
- Inserts this item after the item with the specified label. If the referenced item doesn't exist the item will be inserted at the end of the menu. Also implies that the menu item in question should be placed in the same “group” as the item.beforeGroupContaining
- Provides a means for a single context menu to declare the placement of their containing group before the containing group of the item with the specified label.afterGroupContaining
- Provides a means for a single context menu to declare the placement of their containing group after the containing group of the item with the specified label.
By default, items will be inserted in the order they exist in the template unless one of the specified positioning keywords is used.
Examples
Template:
[
{ id: '1', label: 'one' },
{ id: '2', label: 'two' },
{ id: '3', label: 'three' },
{ id: '4', label: 'four' }
]
Menu:
- 1
- 2
- 3
- 4
Template:
[
{ id: '1', label: 'one' },
{ type: 'separator' },
{ id: '3', label: 'three', beforeGroupContaining: ['1'] },
{ id: '4', label: 'four', afterGroupContaining: ['2'] },
{ type: 'separator' },
{ id: '2', label: 'two' }
]
Menu:
- 3
- 4
- ---
- 1
- ---
- 2
Template:
[
{ id: '1', label: 'one', after: ['3'] },
{ id: '2', label: 'two', before: ['1'] },
{ id: '3', label: 'three' }
]
Menu:
- ---
- 3
- 2
- 1
Class: MenuItem
Add items to native application menus and context menus.
Process: Main
See Menu
for examples.
new MenuItem(options)
options
Objectclick
Function (optional) - Will be called withclick(menuItem, browserWindow, event)
when the menu item is clicked.menuItem
MenuItembrowserWindow
BrowserWindow | undefined - This will not be defined if no window is open.event
KeyboardEvent
role
String (optional) - Can beundo
,redo
,cut
,copy
,paste
,pasteAndMatchStyle
,delete
,selectAll
,reload
,forceReload
,toggleDevTools
,resetZoom
,zoomIn
,zoomOut
,togglefullscreen
,window
,minimize
,close
,help
,about
,services
,hide
,hideOthers
,unhide
,quit
,startSpeaking
,stopSpeaking
,zoom
,front
,appMenu
,fileMenu
,editMenu
,viewMenu
,recentDocuments
,toggleTabBar
,selectNextTab
,selectPreviousTab
,mergeAllWindows
,clearRecentDocuments
,moveTabToNewWindow
orwindowMenu
- Define the action of the menu item, when specified theclick
property will be ignored. See roles.type
String (optional) - Can benormal
,separator
,submenu
,checkbox
orradio
.label
String (optional)sublabel
String (optional)toolTip
String (optional) macOS - Hover text for this menu item.accelerator
Accelerator (optional)icon
(NativeImage | String) (optional)enabled
Boolean (optional) - If false, the menu item will be greyed out and unclickable.acceleratorWorksWhenHidden
Boolean (optional) macOS - default istrue
, and whenfalse
will prevent the accelerator from triggering the item if the item is not visible`.visible
Boolean (optional) - If false, the menu item will be entirely hidden.checked
Boolean (optional) - Should only be specified forcheckbox
orradio
type menu items.registerAccelerator
Boolean (optional) Linux Windows - If false, the accelerator won't be registered with the system, but it will still be displayed. Defaults to true.submenu
(MenuItemConstructorOptions[] | Menu) (optional) - Should be specified forsubmenu
type menu items. Ifsubmenu
is specified, thetype: 'submenu'
can be omitted. If the value is not aMenu
then it will be automatically converted to one usingMenu.buildFromTemplate
.id
String (optional) - Unique within a single menu. If defined then it can be used as a reference to this item by the position attribute.before
String[] (optional) - Inserts this item before the item with the specified label. If the referenced item doesn't exist the item will be inserted at the end of the menu. Also implies that the menu item in question should be placed in the same “group” as the item.after
String[] (optional) - Inserts this item after the item with the specified label. If the referenced item doesn't exist the item will be inserted at the end of the menu.beforeGroupContaining
String[] (optional) - Provides a means for a single context menu to declare the placement of their containing group before the containing group of the item with the specified label.afterGroupContaining
String[] (optional) - Provides a means for a single context menu to declare the placement of their containing group after the containing group of the item with the specified label.
Note: acceleratorWorksWhenHidden
is specified as being macOS-only because accelerators always work when items are hidden on Windows and Linux. The option is exposed to users to give them the option to turn it off, as this is possible in native macOS development. This property is only usable on macOS High Sierra 10.13 or newer.
Roles
Roles allow menu items to have predefined behaviors.
It is best to specify role
for any menu item that matches a standard role,
rather than trying to manually implement the behavior in a click
function.
The built-in role
behavior will give the best native experience.
The label
and accelerator
values are optional when using a role
and will
default to appropriate values for each platform.
Every menu item must have either a role
, label
, or in the case of a separator
a type
.
The role
property can have following values:
undo
about
- Trigger a native about panel (custom message box on Window, which does not provide its own).redo
cut
copy
paste
pasteAndMatchStyle
selectAll
delete
minimize
- Minimize current window.close
- Close current window.quit
- Quit the application.reload
- Reload the current window.forceReload
- Reload the current window ignoring the cache.toggleDevTools
- Toggle developer tools in the current window.togglefullscreen
- Toggle full screen mode on the current window.resetZoom
- Reset the focused page's zoom level to the original size.zoomIn
- Zoom in the focused page by 10%.zoomOut
- Zoom out the focused page by 10%.fileMenu
- Whole default "File" menu (Close / Quit)editMenu
- Whole default "Edit" menu (Undo, Copy, etc.).viewMenu
- Whole default "View" menu (Reload, Toggle Developer Tools, etc.)windowMenu
- Whole default "Window" menu (Minimize, Zoom, etc.).
The following additional roles are available on macOS:
appMenu
- Whole default "App" menu (About, Services, etc.)hide
- Map to thehide
action.hideOthers
- Map to thehideOtherApplications
action.unhide
- Map to theunhideAllApplications
action.startSpeaking
- Map to thestartSpeaking
action.stopSpeaking
- Map to thestopSpeaking
action.front
- Map to thearrangeInFront
action.zoom
- Map to theperformZoom
action.toggleTabBar
- Map to thetoggleTabBar
action.selectNextTab
- Map to theselectNextTab
action.selectPreviousTab
- Map to theselectPreviousTab
action.mergeAllWindows
- Map to themergeAllWindows
action.moveTabToNewWindow
- Map to themoveTabToNewWindow
action.window
- The submenu is a "Window" menu.help
- The submenu is a "Help" menu.services
- The submenu is a "Services" menu. This is only intended for use in the Application Menu and is not the same as the "Services" submenu used in context menus in macOS apps, which is not implemented in Electron.recentDocuments
- The submenu is an "Open Recent" menu.clearRecentDocuments
- Map to theclearRecentDocuments
action.
When specifying a role
on macOS, label
and accelerator
are the only
options that will affect the menu item. All other options will be ignored.
Lowercase role
, e.g. toggledevtools
, is still supported.
Nota Bene: The enabled
and visibility
properties are not available for top-level menu items in the tray on macOS.
Instance Properties
The following properties are available on instances of MenuItem
:
menuItem.id
A String
indicating the item's unique id, this property can be
dynamically changed.
menuItem.label
A String
indicating the item's visible label.
menuItem.click
A Function
that is fired when the MenuItem receives a click event.
It can be called with menuItem.click(event, focusedWindow, focusedWebContents)
.
event
KeyboardEventfocusedWindow
BrowserWindowfocusedWebContents
WebContents
menuItem.submenu
A Menu
(optional) containing the menu
item's submenu, if present.
menuItem.type
A String
indicating the type of the item. Can be normal
, separator
, submenu
, checkbox
or radio
.
menuItem.role
A String
(optional) indicating the item's role, if set. Can be undo
, redo
, cut
, copy
, paste
, pasteAndMatchStyle
, delete
, selectAll
, reload
, forceReload
, toggleDevTools
, resetZoom
, zoomIn
, zoomOut
, togglefullscreen
, window
, minimize
, close
, help
, about
, services
, hide
, hideOthers
, unhide
, quit
, startSpeaking
, stopSpeaking
, zoom
, front
, appMenu
, fileMenu
, editMenu
, viewMenu
, recentDocuments
, toggleTabBar
, selectNextTab
, selectPreviousTab
, mergeAllWindows
, clearRecentDocuments
, moveTabToNewWindow
or windowMenu
menuItem.accelerator
A Accelerator
(optional) indicating the item's accelerator, if set.
menuItem.icon
A NativeImage | String
(optional) indicating the
item's icon, if set.
menuItem.sublabel
A String
indicating the item's sublabel.
menuItem.toolTip
macOS
A String
indicating the item's hover text.
menuItem.enabled
A Boolean
indicating whether the item is enabled, this property can be
dynamically changed.
menuItem.visible
A Boolean
indicating whether the item is visible, this property can be
dynamically changed.
menuItem.checked
A Boolean
indicating whether the item is checked, this property can be
dynamically changed.
A checkbox
menu item will toggle the checked
property on and off when
selected.
A radio
menu item will turn on its checked
property when clicked, and
will turn off that property for all adjacent items in the same menu.
You can add a click
function for additional behavior.
menuItem.registerAccelerator
A Boolean
indicating if the accelerator should be registered with the
system or just displayed.
This property can be dynamically changed.
menuItem.commandId
A Number
indicating an item's sequential unique id.
menuItem.menu
A Menu
that the item is a part of.
MessageChannelMain
MessageChannelMain
is the main-process-side equivalent of the DOM
MessageChannel
object. Its singular function is to create a pair of
connected MessagePortMain
objects.
See the Channel Messaging API documentation for more information on using channel messaging.
Class: MessageChannelMain
Process: Main
Example:
const { port1, port2 } = new MessageChannelMain()
w.webContents.postMessage('port', null, [port2])
port1.postMessage({ some: 'message' })
channel.port1
A MessagePortMain
property.
channel.port2
A MessagePortMain
property.
MessagePortMain
MessagePortMain
is the main-process-side equivalent of the DOM
MessagePort
object. It behaves similarly to the DOM version, with the
exception that it uses the Node.js EventEmitter
event system, instead of the
DOM EventTarget
system. This means you should use port.on('message', ...)
to listen for events, instead of port.onmessage = ...
or
port.addEventListener('message', ...)
See the Channel Messaging API documentation for more information on using channel messaging.
MessagePortMain
is an [EventEmitter][event-emitter].
Class: MessagePortMain
Process: Main
port.postMessage(message, [transfer])
message
anytransfer
MessagePortMain[] (optional)
Sends a message from the port, and optionally, transfers ownership of objects to other browsing contexts.
port.start()
Starts the sending of messages queued on the port. Messages will be queued until this method is called.
port.close()
Disconnects the port, so it is no longer active.
Event: 'message'
Returns:
messageEvent
Objectdata
anyports
MessagePortMain[]
Emitted when a MessagePortMain object receives a message.
Event: 'close'
Emitted when the remote end of a MessagePortMain object becomes disconnected.
MimeTypedBuffer Object
mimeType
String (optional) - MIME type of the buffer.charset
String (optional) - Charset of the buffer.data
Buffer - The actual Buffer content.
MouseInputEvent Object extends InputEvent
type
String - The type of the event, can bemouseDown
,mouseUp
,mouseEnter
,mouseLeave
,contextMenu
,mouseWheel
ormouseMove
.x
Integery
Integerbutton
String (optional) - The button pressed, can beleft
,middle
,right
.globalX
Integer (optional)globalY
Integer (optional)movementX
Integer (optional)movementY
Integer (optional)clickCount
Integer (optional)
MouseWheelInputEvent Object extends MouseInputEvent
type
String - The type of the event, can bemouseWheel
.deltaX
Integer (optional)deltaY
Integer (optional)wheelTicksX
Integer (optional)wheelTicksY
Integer (optional)accelerationRatioX
Integer (optional)accelerationRatioY
Integer (optional)hasPreciseScrollingDeltas
Boolean (optional)canScroll
Boolean (optional)
Multithreading
With Web Workers, it is possible to run JavaScript in OS-level threads.
Multi-threaded Node.js
It is possible to use Node.js features in Electron's Web Workers, to do
so the nodeIntegrationInWorker
option should be set to true
in
webPreferences
.
const win = new BrowserWindow({
webPreferences: {
nodeIntegrationInWorker: true
}
})
The nodeIntegrationInWorker
can be used independent of nodeIntegration
, but
sandbox
must not be set to true
.
Available APIs
All built-in modules of Node.js are supported in Web Workers, and asar
archives can still be read with Node.js APIs. However none of Electron's
built-in modules can be used in a multi-threaded environment.
Native Node.js modules
Any native Node.js module can be loaded directly in Web Workers, but it is strongly recommended not to do so. Most existing native modules have been written assuming single-threaded environment, using them in Web Workers will lead to crashes and memory corruptions.
Note that even if a native Node.js module is thread-safe it's still not safe to
load it in a Web Worker because the process.dlopen
function is not thread
safe.
The only way to load a native module safely for now, is to make sure the app loads no native modules after the Web Workers get started.
process.dlopen = () => {
throw new Error('Load native module is not safe')
}
const worker = new Worker('script.js')
Overview
Certain kinds of applications that manipulate files might want to support the operating system's native file drag & drop feature. Dragging files into web content is common and supported by many websites. Electron additionally supports dragging files and content out from web content into the operating system's world.
To implement this feature in your app, you need to call the
webContents.startDrag(item)
API in response to the ondragstart
event.
Example
Starting with a working application from the
Quick Start Guide, add the following lines to the
index.html
file:
<a href="#" id="drag">Drag me</a>
<script src="renderer.js"></script>
and add the following lines to the renderer.js
file:
const { ipcRenderer } = require('electron')
document.getElementById('drag').ondragstart = (event) => {
event.preventDefault()
ipcRenderer.send('ondragstart', '/absolute/path/to/the/item')
}
The code above instructs the Renderer process to handle the ondragstart
event
and forward the information to the Main process.
In the Main process(main.js
file), expand the received event with a path to the file that is
being dragged and an icon:
const { ipcMain } = require('electron')
ipcMain.on('ondragstart', (event, filePath) => {
event.sender.startDrag({
file: filePath,
icon: '/path/to/icon.png'
})
})
After launching the Electron application, try dragging and dropping the item from the BroswerWindow onto your desktop. In this guide, the item is a Markdown file located in the root of the project:
nativeImage
Create tray, dock, and application icons using PNG or JPG files.
In Electron, for the APIs that take images, you can pass either file paths or
NativeImage
instances. An empty image will be used when null
is passed.
For example, when creating a tray or setting a window's icon, you can pass an
image file path as a String
:
const { BrowserWindow, Tray } = require('electron')
const appIcon = new Tray('/Users/somebody/images/icon.png')
const win = new BrowserWindow({ icon: '/Users/somebody/images/window.png' })
console.log(appIcon, win)
Or read the image from the clipboard, which returns a NativeImage
:
const { clipboard, Tray } = require('electron')
const image = clipboard.readImage()
const appIcon = new Tray(image)
console.log(appIcon)
Supported Formats
Currently PNG
and JPEG
image formats are supported. PNG
is recommended
because of its support for transparency and lossless compression.
On Windows, you can also load ICO
icons from file paths. For best visual
quality, it is recommended to include at least the following sizes in the:
- Small icon
- 16x16 (100% DPI scale)
- 20x20 (125% DPI scale)
- 24x24 (150% DPI scale)
- 32x32 (200% DPI scale)
- Large icon
- 32x32 (100% DPI scale)
- 40x40 (125% DPI scale)
- 48x48 (150% DPI scale)
- 64x64 (200% DPI scale)
- 256x256
Check the Size requirements section in this article.
High Resolution Image
On platforms that have high-DPI support such as Apple Retina displays, you can
append @2x
after image's base filename to mark it as a high resolution image.
For example, if icon.png
is a normal image that has standard resolution, then
icon@2x.png
will be treated as a high resolution image that has double DPI
density.
If you want to support displays with different DPI densities at the same time, you can put images with different sizes in the same folder and use the filename without DPI suffixes. For example:
images/
├── icon.png
├── icon@2x.png
└── icon@3x.png
const { Tray } = require('electron')
const appIcon = new Tray('/Users/somebody/images/icon.png')
console.log(appIcon)
The following suffixes for DPI are also supported:
@1x
@1.25x
@1.33x
@1.4x
@1.5x
@1.8x
@2x
@2.5x
@3x
@4x
@5x
Template Image
Template images consist of black and an alpha channel. Template images are not intended to be used as standalone images and are usually mixed with other content to create the desired final appearance.
The most common case is to use template images for a menu bar icon, so it can adapt to both light and dark menu bars.
Note: Template image is only supported on macOS.
To mark an image as a template image, its filename should end with the word
Template
. For example:
xxxTemplate.png
xxxTemplate@2x.png
Methods
The nativeImage
module has the following methods, all of which return
an instance of the NativeImage
class:
nativeImage.createThumbnailFromPath(path, maxSize)
macOS Windows
path
String - path to a file that we intend to construct a thumbnail out of.maxSize
Size - the maximum width and height (positive numbers) the thumbnail returned can be. The Windows implementation will ignoremaxSize.height
and scale the height according tomaxSize.width
.
Returns Promise<NativeImage>
- fulfilled with the file's thumbnail preview image, which is a NativeImage.
nativeImage.createFromPath(path)
path
String
Returns NativeImage
Creates a new NativeImage
instance from a file located at path
. This method
returns an empty image if the path
does not exist, cannot be read, or is not
a valid image.
const nativeImage = require('electron').nativeImage
const image = nativeImage.createFromPath('/Users/somebody/images/icon.png')
console.log(image)
nativeImage.createFromBitmap(buffer, options)
buffer
Bufferoptions
Objectwidth
Integerheight
IntegerscaleFactor
Double (optional) - Defaults to 1.0.
Returns NativeImage
Creates a new NativeImage
instance from buffer
that contains the raw bitmap
pixel data returned by toBitmap()
. The specific format is platform-dependent.
nativeImage.createFromBuffer(buffer[, options])
buffer
Bufferoptions
Object (optional)width
Integer (optional) - Required for bitmap buffers.height
Integer (optional) - Required for bitmap buffers.scaleFactor
Double (optional) - Defaults to 1.0.
Returns NativeImage
Creates a new NativeImage
instance from buffer
. Tries to decode as PNG or JPEG first.
nativeImage.createFromDataURL(dataURL)
dataURL
String
Returns NativeImage
Creates a new NativeImage
instance from dataURL
.
nativeImage.createFromNamedImage(imageName[, hslShift])
macOS
imageName
StringhslShift
Number[] (optional)
Returns NativeImage
Creates a new NativeImage
instance from the NSImage that maps to the
given image name. See System Icons
for a list of possible values.
The hslShift
is applied to the image with the following rules:
hsl_shift[0]
(hue): The absolute hue value for the image - 0 and 1 map to 0 and 360 on the hue color wheel (red).hsl_shift[1]
(saturation): A saturation shift for the image, with the following key values: 0 = remove all color. 0.5 = leave unchanged. 1 = fully saturate the image.hsl_shift[2]
(lightness): A lightness shift for the image, with the following key values: 0 = remove all lightness (make all pixels black). 0.5 = leave unchanged. 1 = full lightness (make all pixels white).
This means that [-1, 0, 1]
will make the image completely white and
[-1, 1, 0]
will make the image completely black.
In some cases, the NSImageName
doesn't match its string representation; one example of this is NSFolderImageName
, whose string representation would actually be NSFolder
. Therefore, you'll need to determine the correct string representation for your image before passing it in. This can be done with the following:
echo -e '#import <Cocoa/Cocoa.h>\nint main() { NSLog(@"%@", SYSTEM_IMAGE_NAME); }' | clang -otest -x objective-c -framework Cocoa - && ./test
where SYSTEM_IMAGE_NAME
should be replaced with any value from this list.
Class: NativeImage
Natively wrap images such as tray, dock, and application icons.
Instance Methods
The following methods are available on instances of the NativeImage
class:
image.toPNG([options])
options
Object (optional)scaleFactor
Double (optional) - Defaults to 1.0.
Returns Buffer
- A Buffer that contains the image's PNG
encoded data.
image.toJPEG(quality)
quality
Integer - Between 0 - 100.
Returns Buffer
- A Buffer that contains the image's JPEG
encoded data.
image.toBitmap([options])
options
Object (optional)scaleFactor
Double (optional) - Defaults to 1.0.
Returns Buffer
- A Buffer that contains a copy of the image's raw bitmap pixel
data.
image.toDataURL([options])
options
Object (optional)scaleFactor
Double (optional) - Defaults to 1.0.
Returns String
- The data URL of the image.
image.getBitmap([options])
options
Object (optional)scaleFactor
Double (optional) - Defaults to 1.0.
Returns Buffer
- A Buffer that contains the image's raw bitmap pixel data.
The difference between getBitmap()
and toBitmap()
is that getBitmap()
does not
copy the bitmap data, so you have to use the returned Buffer immediately in
current event loop tick; otherwise the data might be changed or destroyed.
image.getNativeHandle()
macOS
Returns Buffer
- A Buffer that stores C pointer to underlying native handle of
the image. On macOS, a pointer to NSImage
instance would be returned.
Notice that the returned pointer is a weak pointer to the underlying native
image instead of a copy, so you must ensure that the associated
nativeImage
instance is kept around.
image.isEmpty()
Returns Boolean
- Whether the image is empty.
image.getSize([scaleFactor])
scaleFactor
Double (optional) - Defaults to 1.0.
Returns Size
.
If scaleFactor
is passed, this will return the size corresponding to the image representation most closely matching the passed value.
image.isTemplateImage()
Returns Boolean
- Whether the image is a template image.
image.crop(rect)
rect
Rectangle - The area of the image to crop.
Returns NativeImage
- The cropped image.
image.resize(options)
options
Objectwidth
Integer (optional) - Defaults to the image's width.height
Integer (optional) - Defaults to the image's height.quality
String (optional) - The desired quality of the resize image. Possible values aregood
,better
, orbest
. The default isbest
. These values express a desired quality/speed tradeoff. They are translated into an algorithm-specific method that depends on the capabilities (CPU, GPU) of the underlying platform. It is possible for all three methods to be mapped to the same algorithm on a given platform.
Returns NativeImage
- The resized image.
If only the height
or the width
are specified then the current aspect ratio
will be preserved in the resized image.
image.getAspectRatio([scaleFactor])
scaleFactor
Double (optional) - Defaults to 1.0.
Returns Float
- The image's aspect ratio.
If scaleFactor
is passed, this will return the aspect ratio corresponding to the image representation most closely matching the passed value.
image.getScaleFactors()
Returns Float[]
- An array of all scale factors corresponding to representations for a given nativeImage.
image.addRepresentation(options)
options
ObjectscaleFactor
Double - The scale factor to add the image representation for.width
Integer (optional) - Defaults to 0. Required if a bitmap buffer is specified asbuffer
.height
Integer (optional) - Defaults to 0. Required if a bitmap buffer is specified asbuffer
.buffer
Buffer (optional) - The buffer containing the raw image data.dataURL
String (optional) - The data URL containing either a base 64 encoded PNG or JPEG image.
Add an image representation for a specific scale factor. This can be used to explicitly add different scale factor representations to an image. This can be called on empty images.
nativeImage.isMacTemplateImage
macOS
A Boolean
property that determines whether the image is considered a template image.
Please note that this property only has an effect on macOS.
Events
The nativeTheme
module emits the following events:
Event: 'updated'
Emitted when something in the underlying NativeTheme has changed. This normally
means that either the value of shouldUseDarkColors
,
shouldUseHighContrastColors
or shouldUseInvertedColorScheme
has changed.
You will have to check them to determine which one has changed.
Properties
The nativeTheme
module has the following properties:
nativeTheme.shouldUseDarkColors
Readonly
A Boolean
for if the OS / Chromium currently has a dark mode enabled or is
being instructed to show a dark-style UI. If you want to modify this value you
should use themeSource
below.
nativeTheme.themeSource
A String
property that can be system
, light
or dark
. It is used to override and supersede
the value that Chromium has chosen to use internally.
Setting this property to system
will remove the override and
everything will be reset to the OS default. By default themeSource
is system
.
Settings this property to dark
will have the following effects:
nativeTheme.shouldUseDarkColors
will betrue
when accessed- Any UI Electron renders on Linux and Windows including context menus, devtools, etc. will use the dark UI.
- Any UI the OS renders on macOS including menus, window frames, etc. will use the dark UI.
- The
prefers-color-scheme
CSS query will matchdark
mode. - The
updated
event will be emitted
Settings this property to light
will have the following effects:
nativeTheme.shouldUseDarkColors
will befalse
when accessed- Any UI Electron renders on Linux and Windows including context menus, devtools, etc. will use the light UI.
- Any UI the OS renders on macOS including menus, window frames, etc. will use the light UI.
- The
prefers-color-scheme
CSS query will matchlight
mode. - The
updated
event will be emitted
The usage of this property should align with a classic "dark mode" state machine in your application where the user has three options.
Follow OS
-->themeSource = 'system'
Dark Mode
-->themeSource = 'dark'
Light Mode
-->themeSource = 'light'
Your application should then always use shouldUseDarkColors
to determine what CSS to apply.
nativeTheme.shouldUseHighContrastColors
macOS Windows Readonly
A Boolean
for if the OS / Chromium currently has high-contrast mode enabled
or is being instructed to show a high-contrast UI.
nativeTheme.shouldUseInvertedColorScheme
macOS Windows Readonly
A Boolean
for if the OS / Chromium currently has an inverted color scheme
or is being instructed to use an inverted color scheme.
net
Issue HTTP/HTTPS requests using Chromium's native networking library
Process: Main
The net
module is a client-side API for issuing HTTP(S) requests. It is
similar to the HTTP and
HTTPS modules of Node.js but uses
Chromium's native networking library instead of the Node.js implementation,
offering better support for web proxies.
The following is a non-exhaustive list of why you may consider using the net
module instead of the native Node.js modules:
- Automatic management of system proxy configuration, support of the wpad protocol and proxy pac configuration files.
- Automatic tunneling of HTTPS requests.
- Support for authenticating proxies using basic, digest, NTLM, Kerberos or negotiate authentication schemes.
- Support for traffic monitoring proxies: Fiddler-like proxies used for access control and monitoring.
The API components (including classes, methods, properties and event names) are similar to those used in Node.js.
Example usage:
const { app } = require('electron')
app.whenReady().then(() => {
const { net } = require('electron')
const request = net.request('https://github.com')
request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`)
console.log(`HEADERS: ${JSON.stringify(response.headers)}`)
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`)
})
response.on('end', () => {
console.log('No more data in response.')
})
})
request.end()
})
The net
API can be used only after the application emits the ready
event.
Trying to use the module before the ready
event will throw an error.
Methods
The net
module has the following methods:
net.request(options)
options
(ClientRequestConstructorOptions | String) - TheClientRequest
constructor options.
Returns ClientRequest
Creates a ClientRequest
instance using the provided
options
which are directly forwarded to the ClientRequest
constructor.
The net.request
method would be used to issue both secure and insecure HTTP
requests according to the specified protocol scheme in the options
object.
netLog
Logging network events for a session.
Process: Main
const { netLog } = require('electron')
app.whenReady().then(async () => {
await netLog.startLogging('/path/to/net-log')
// After some network events
const path = await netLog.stopLogging()
console.log('Net-logs written to', path)
})
See --log-net-log
to log network events throughout the app's lifecycle.
Note: All methods unless specified can only be used after the ready
event
of the app
module gets emitted.
netLog.startLogging(path[, options])
path
String - File path to record network logs.options
Object (optional)captureMode
String (optional) - What kinds of data should be captured. By default, only metadata about requests will be captured. Setting this toincludeSensitive
will include cookies and authentication data. Setting it toeverything
will include all bytes transferred on sockets. Can bedefault
,includeSensitive
oreverything
.maxFileSize
Number (optional) - When the log grows beyond this size, logging will automatically stop. Defaults to unlimited.
Returns Promise<void>
- resolves when the net log has begun recording.
Starts recording network events to path
.
netLog.stopLogging()
Returns Promise<void>
- resolves when the net log has been flushed to disk.
Stops recording network events. If not called, net logging will automatically end when app quits.
netLog.currentlyLogging
Readonly
A Boolean
property that indicates whether network logs are currently being recorded.
NewWindowWebContentsEvent Object extends Event
newGuest
BrowserWindow (optional)
Using in the renderer process
If you want to show Notifications from a renderer process you should use the HTML5 Notification API
Class: Notification
Create OS desktop notifications
Process: Main
Notification
is an EventEmitter.
It creates a new Notification
with native properties as set by the options
.
Static Methods
The Notification
class has the following static methods:
Notification.isSupported()
Returns Boolean
- Whether or not desktop notifications are supported on the current system
new Notification([options])
options
Object (optional)title
String - A title for the notification, which will be shown at the top of the notification window when it is shown.subtitle
String (optional) macOS - A subtitle for the notification, which will be displayed below the title.body
String - The body text of the notification, which will be displayed below the title or subtitle.silent
Boolean (optional) - Whether or not to emit an OS notification noise when showing the notification.icon
(String | NativeImage) (optional) - An icon to use in the notification.hasReply
Boolean (optional) macOS - Whether or not to add an inline reply option to the notification.timeoutType
String (optional) Linux Windows - The timeout duration of the notification. Can be 'default' or 'never'.replyPlaceholder
String (optional) macOS - The placeholder to write in the inline reply input field.sound
String (optional) macOS - The name of the sound file to play when the notification is shown.urgency
String (optional) Linux - The urgency level of the notification. Can be 'normal', 'critical', or 'low'.actions
NotificationAction[] (optional) macOS - Actions to add to the notification. Please read the available actions and limitations in theNotificationAction
documentation.closeButtonText
String (optional) macOS - A custom title for the close button of an alert. An empty string will cause the default localized text to be used.
Instance Events
Objects created with new Notification
emit the following events:
Note: Some events are only available on specific operating systems and are labeled as such.
Event: 'show'
Returns:
event
Event
Emitted when the notification is shown to the user, note this could be fired
multiple times as a notification can be shown multiple times through the
show()
method.
Event: 'close'
Returns:
event
Event
Emitted when the notification is closed by manual intervention from the user.
This event is not guaranteed to be emitted in all cases where the notification is closed.
Event: 'reply' macOS
Returns:
event
Eventreply
String - The string the user entered into the inline reply field.
Emitted when the user clicks the "Reply" button on a notification with hasReply: true
.
Event: 'action' macOS
Returns:
event
Eventindex
Number - The index of the action that was activated.
Instance Methods
Objects created with new Notification
have the following instance methods:
notification.show()
Immediately shows the notification to the user, please note this means unlike the
HTML5 Notification implementation, instantiating a new Notification
does
not immediately show it to the user, you need to call this method before the OS
will display it.
If the notification has been shown before, this method will dismiss the previously shown notification and create a new one with identical properties.
notification.close()
Dismisses the notification.
notification.title
A String
property representing the title of the notification.
notification.subtitle
A String
property representing the subtitle of the notification.
notification.body
A String
property representing the body of the notification.
notification.replyPlaceholder
A String
property representing the reply placeholder of the notification.
notification.sound
A String
property representing the sound of the notification.
notification.closeButtonText
A String
property representing the close button text of the notification.
notification.silent
A Boolean
property representing whether the notification is silent.
notification.hasReply
A Boolean
property representing whether the notification has a reply action.
notification.urgency
Linux
A String
property representing the urgency level of the notification. Can be 'normal', 'critical', or 'low'.
Default is 'low' - see NotifyUrgency for more information.
notification.timeoutType
Linux Windows
A String
property representing the type of timeout duration for the notification. Can be 'default' or 'never'.
If timeoutType
is set to 'never', the notification never expires. It stays open until closed by the calling API or the user.
notification.actions
A NotificationAction[]
property representing the actions of the notification.
Playing Sounds
On macOS, you can specify the name of the sound you'd like to play when the
notification is shown. Any of the default sounds (under System Preferences >
Sound) can be used, in addition to custom sound files. Be sure that the sound
file is copied under the app bundle (e.g., YourApp.app/Contents/Resources
),
or one of the following locations:
~/Library/Sounds
/Library/Sounds
/Network/Library/Sounds
/System/Library/Sounds
See the NSSound
docs for more information.
NotificationAction Object
type
String - The type of action, can bebutton
.text
String (optional) - The label for the given action.
Platform / Action Support
Action Type | Platform Support | Usage of text | Default text | Limitations |
---|---|---|---|---|
button | macOS | Used as the label for the button | "Show" (or a localized string by system default if first of such button , otherwise empty) | Only the first one is used. If multiple are provided, those beyond the first will be listed as additional actions (displayed when mouse active over the action button). Any such action also is incompatible with hasReply and will be ignored if hasReply is true . |
Button support on macOS
In order for extra notification buttons to work on macOS your app must meet the following criteria.
- App is signed
- App has it's
NSUserNotificationAlertStyle
set toalert
in theInfo.plist
.
If either of these requirements are not met the button won't appear.
Overview
All three operating systems provide means for applications to send notifications to the user. The technique of showing notifications is different for the Main and Renderer processes.
For the Renderer process, Electron conveniently allows developers to send notifications with the HTML5 Notification API, using the currently running operating system's native notification APIs to display it.
To show notifications in the Main process, you need to use the Notification module.
Show notifications in the Renderer process
Assuming you have a working Electron application from the
Quick Start Guide, add the following line to the
index.html
file before the closing </body>
tag:
<script src="renderer.js"></script>
and add the renderer.js
file:
const myNotification = new Notification('Title', {
body: 'Notification from the Renderer process'
})
myNotification.onclick = () => {
console.log('Notification clicked')
}
After launching the Electron application, you should see the notification:
If you open the Console and then click the notification, you will see the
message that was generated after triggering the onclick
event:
Show notifications in the Main process
Starting with a working application from the
Quick Start Guide, update the main.js
file with the following lines:
const { Notification } = require('electron')
function showNotification () {
const notification = {
title: 'Basic Notification',
body: 'Notification from the Main process'
}
new Notification(notification).show()
}
app.whenReady().then(createWindow).then(showNotification)
After launching the Electron application, you should see the notification:
Additional information
While code and user experience across operating systems are similar, there are subtle differences.
Windows
- On Windows 10, a shortcut to your app with an
Application User Model ID must be installed to the
Start Menu. This can be overkill during development, so adding
node_modules\electron\dist\electron.exe
to your Start Menu also does the trick. Navigate to the file in Explorer, right-click and 'Pin to Start Menu'. You will then need to add the lineapp.setAppUserModelId(process.execPath)
to your main process to see notifications. - On Windows 8.1 and Windows 8, a shortcut to your app with an Application User Model ID must be installed to the Start screen. Note, however, that it does not need to be pinned to the Start screen.
- On Windows 7, notifications work via a custom implementation which visually resembles the native one on newer systems.
Electron attempts to automate the work around the Application User Model ID. When
Electron is used together with the installation and update framework Squirrel,
shortcuts will automatically be set correctly. Furthermore,
Electron will detect that Squirrel was used and will automatically call
app.setAppUserModelId()
with the correct value. During development, you may have
to call app.setAppUserModelId()
yourself.
Furthermore, in Windows 8, the maximum length for the notification body is 250 characters, with the Windows team recommending that notifications should be kept to 200 characters. That said, that limitation has been removed in Windows 10, with the Windows team asking developers to be reasonable. Attempting to send gigantic amounts of text to the API (thousands of characters) might result in instability.
Advanced Notifications
Later versions of Windows allow for advanced notifications, with custom templates,
images, and other flexible elements. To send those notifications (from either the
main process or the renderer process), use the userland module
electron-windows-notifications,
which uses native Node addons to send ToastNotification
and TileNotification
objects.
While notifications including buttons work with electron-windows-notifications
,
handling replies requires the use of
electron-windows-interactive-notifications
,
which helps with registering the required COM components and calling your
Electron app with the entered user data.
Quiet Hours / Presentation Mode
To detect whether or not you're allowed to send a notification, use the userland module electron-notification-state.
This allows you to determine ahead of time whether or not Windows will silently throw the notification away.
macOS
Notifications are straight-forward on macOS, but you should be aware of Apple's Human Interface guidelines regarding notifications.
Note that notifications are limited to 256 bytes in size and will be truncated if you exceed that limit.
Advanced Notifications
Later versions of macOS allow for notifications with an input field, allowing the user to quickly reply to a notification. In order to send notifications with an input field, use the userland module node-mac-notifier.
Do not disturb / Session State
To detect whether or not you're allowed to send a notification, use the userland module electron-notification-state.
This will allow you to detect ahead of time whether or not the notification will be displayed.
Linux
Notifications are sent using libnotify
which can show notifications on any
desktop environment that follows Desktop Notifications
Specification, including Cinnamon, Enlightenment, Unity,
GNOME, KDE.
Overview
Offscreen rendering lets you obtain the content of a BrowserWindow
in a
bitmap, so it can be rendered anywhere, for example, on texture in a 3D scene.
The offscreen rendering in Electron uses a similar approach to that of the
Chromium Embedded Framework
project.
Notes:
- There are two rendering modes that can be used (see the section below) and only
the dirty area is passed to the
paint
event to be more efficient. - You can stop/continue the rendering as well as set the frame rate.
- The maximum frame rate is 240 because greater values bring only performance losses with no benefits.
- When nothing is happening on a webpage, no frames are generated.
- An offscreen window is always created as a Frameless Window.
GPU accelerated
GPU accelerated rendering means that the GPU is used for composition. Because of that, the frame has to be copied from the GPU which requires more resources, thus this mode is slower than the Software output device. The benefit of this mode is that WebGL and 3D CSS animations are supported.
Software output device
This mode uses a software output device for rendering in the CPU, so the frame generation is much faster. As a result, this mode is preferred over the GPU accelerated one.
To enable this mode, GPU acceleration has to be disabled by calling the
app.disableHardwareAcceleration()
API.
Example
Starting with a working application from the
Quick Start Guide, add the following lines to the
main.js
file:
const { app, BrowserWindow } = require('electron')
const fs = require('fs')
app.disableHardwareAcceleration()
let win
app.whenReady().then(() => {
win = new BrowserWindow({ webPreferences: { offscreen: true } })
win.loadURL('https://github.com')
win.webContents.on('paint', (event, dirty, image) => {
fs.writeFileSync('ex.png', image.toPNG())
})
win.webContents.setFrameRate(60)
})
After launching the Electron application, navigate to your application's working folder.
Overview
Online and offline event
detection can be implemented in the Renderer process using the
navigator.onLine
attribute, part of standard HTML5 API.
The navigator.onLine
attribute returns:
false
if all network requests are guaranteed to fail (e.g. when disconnected from the network).true
in all other cases.
Since many cases return true
, you should treat with care situations of
getting false positives, as we cannot always assume that true
value means
that Electron can access the Internet. For example, in cases when the computer
is running a virtualization software that has virtual Ethernet adapters in "always
connected" state. Therefore, if you want to determine the Internet access
status of Electron, you should develop additional means for this check.
Event detection in the Renderer process
Starting with a working application from the
Quick Start Guide, update the main.js
file
with the following lines:
const { app, BrowserWindow } = require('electron')
let onlineStatusWindow
app.whenReady().then(() => {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false })
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
})
in the index.html
file, add the following line before the
closing </body>
tag:
<script src="renderer.js"></script>
and add the renderer.js
file:
const alertOnlineStatus = () => { window.alert(navigator.onLine ? 'online' : 'offline') }
window.addEventListener('online', alertOnlineStatus)
window.addEventListener('offline', alertOnlineStatus)
alertOnlineStatus()
After launching the Electron application, you should see the notification:
Event detection in the Main process
There may be situations when you want to respond to online/offline events in
the Main process as well. The Main process, however, does not have a
navigator
object and cannot detect these events directly. In this case, you
need to forward the events to the Main process using Electron's inter-process
communication (IPC) utilities.
Starting with a working application from the
Quick Start Guide, update the main.js
file
with the following lines:
const { app, BrowserWindow, ipcMain } = require('electron')
let onlineStatusWindow
app.whenReady().then(() => {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false, webPreferences: { nodeIntegration: true } })
onlineStatusWindow.loadURL(`file://${__dirname}/index.html`)
})
ipcMain.on('online-status-changed', (event, status) => {
console.log(status)
})
in the index.html
file, add the following line before the
closing </body>
tag:
<script src="renderer.js"></script>
and add the renderer.js
file:
const { ipcRenderer } = require('electron')
const updateOnlineStatus = () => { ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline') }
window.addEventListener('online', updateOnlineStatus)
window.addEventListener('offline', updateOnlineStatus)
updateOnlineStatus()
After launching the Electron application, you should see the notification in the Console:
npm start
> electron@1.0.0 start /electron
> electron .
online
Modernization
The Electron team is currently undergoing an initiative to modernize our API in a few concrete ways. These include: updating our modules to use idiomatic JS properties instead of separate getPropertyX
and setpropertyX
, converting callbacks to promises, and removing some other anti-patterns present in our APIs. The current status of the Promise initiative can be tracked in the promisification tracking file.
As we work to perform these updates, we seek to create the least disruptive amount of change at any given time, so as many changes as possible will be introduced in a backward compatible manner and deprecated after enough time has passed to give users a chance to upgrade their API calls.
This document and its child documents will be updated to reflect the latest status of our API changes.
Patches in Electron
Electron is built on two major upstream projects: Chromium and Node.js. Each of these projects has several of their own dependencies, too. We try our best to use these dependencies exactly as they are but sometimes we can't achieve our goals without patching those upstream dependencies to fit our use cases.
Patch justification
Every patch in Electron is a maintenance burden. When upstream code changes, patches can break—sometimes without even a patch conflict or a compilation error. It's an ongoing effort to keep our patch set up-to-date and effective. So we strive to keep our patch count at a minimum. To that end, every patch must describe its reason for existence in its commit message. That reason must be one of the following:
- The patch is temporary, and is intended to be (or has been) committed upstream or otherwise eventually removed. Include a link to an upstream PR or code review if available, or a procedure for verifying whether the patch is still needed at a later date.
- The patch allows the code to compile in the Electron environment, but cannot be upstreamed because it's Electron-specific (e.g. patching out references to Chrome's
Profile
). Include reasoning about why the change cannot be implemented without a patch (e.g. by subclassing or copying the code). - The patch makes Electron-specific changes in functionality which are fundamentally incompatible with upstream.
In general, all the upstream projects we work with are friendly folks and are often happy to accept refactorings that allow the code in question to be compatible with both Electron and the upstream project. (See e.g. this change in Chromium, which allowed us to remove a patch that did the same thing, or this change in Node, which was a no-op for Node but fixed a bug in Electron.) We should aim to upstream changes whenever we can, and avoid indefinite-lifetime patches.
Patch system
If you find yourself in the unfortunate position of having to make a change which can only be made through patching an upstream project, you'll need to know how to manage patches in Electron.
All patches to upstream projects in Electron are contained in the patches/
directory. Each subdirectory of patches/
contains several patch files, along with a .patches
file which lists the order in which the patches should be applied. Think of these files as making up a series of git commits that are applied on top of the upstream project after we check it out.
patches
├── config.json <-- this describes which patchset directory is applied to what project
├── chromium
│ ├── .patches
│ ├── accelerator.patch
│ ├── add_contentgpuclient_precreatemessageloop_callback.patch
│ ⋮
├── node
│ ├── .patches
│ ├── add_openssl_is_boringssl_guard_to_oaep_hash_check.patch
│ ├── build_add_gn_build_files.patch
│ ⋮
⋮
To help manage these patch sets, we provide two tools: git-import-patches
and git-export-patches
. git-import-patches
imports a set of patch files into a git repository by applying each patch in the correct order and creating a commit for each one. git-export-patches
does the reverse; it exports a series of git commits in a repository into a set of files in a directory and an accompanying .patches
file.
Side note: the reason we use a
.patches
file to maintain the order of applied patches, rather than prepending a number like001-
to each file, is because it reduces conflicts related to patch ordering. It prevents the situation where two PRs both add a patch at the end of the series with the same numbering and end up both getting merged resulting in a duplicate identifier, and it also reduces churn when a patch is added or deleted in the middle of the series.
Adding a new patch
$ cd src/third_party/electron_node
$ vim some/code/file.cc
$ git commit
$ ../../electron/script/git-export-patches -o ../../electron/patches/node
NOTE:
git-export-patches
ignores any uncommitted files, so you must create a commit if you want your changes to be exported. The subject line of the commit message will be used to derive the patch file name, and the body of the commit message should include the reason for the patch's existence.
Re-exporting patches will sometimes cause shasums in unrelated patches to change. This is generally harmless and can be ignored (but go ahead and add those changes to your PR, it'll stop them from showing up for other people).
Editing an existing patch
$ cd src/v8
$ vim some/code/file.cc
$ git log
# Find the commit sha of the patch you want to edit.
$ git commit --fixup [COMMIT_SHA]
$ git rebase --autosquash -i [COMMIT_SHA]^
$ ../electron/script/git-export-patches -o ../electron/patches/v8
Removing a patch
$ vim src/electron/patches/node/.patches
# Delete the line with the name of the patch you want to remove
$ cd src/third_party/electron_node
$ git reset --hard refs/patches/upstream-head
$ ../../electron/script/git-import-patches ../../electron/patches/node
$ ../../electron/script/git-export-patches -o ../../electron/patches/node
Note that git-import-patches
will mark the commit that was HEAD
when it was run as refs/patches/upstream-head
. This lets you keep track of which commits are from Electron patches (those that come after refs/patches/upstream-head
) and which commits are in upstream (those before refs/patches/upstream-head
).
Resolving conflicts
When updating an upstream dependency, patches may fail to apply cleanly. Often, the conflict can be resolved automatically by git with a 3-way merge. You can instruct git-import-patches
to use the 3-way merge algorithm by passing the -3
argument:
$ cd src/third_party/electron_node
# If the patch application failed midway through, you can reset it with:
$ git am --abort
# And then retry with 3-way merge:
$ ../../electron/script/git-import-patches -3 ../../electron/patches/node
If git-import-patches -3
encounters a merge conflict that it can't resolve automatically, it will pause and allow you to resolve the conflict manually. Once you have resolved the conflict, git add
the resolved files and continue to apply the rest of the patches by running git am --continue
.
Performance
Developers frequently ask about strategies to optimize the performance of Electron applications. Software engineers, consumers, and framework developers do not always agree on one single definition of what "performance" means. This document outlines some of the Electron maintainers' favorite ways to reduce the amount of memory, CPU, and disk resources being used while ensuring that your app is responsive to user input and completes operations as quickly as possible. Furthermore, we want all performance strategies to maintain a high standard for your app's security.
Wisdom and information about how to build performant websites with JavaScript generally applies to Electron apps, too. To a certain extent, resources discussing how to build performant Node.js applications also apply, but be careful to understand that the term "performance" means different things for a Node.js backend than it does for an application running on a client.
This list is provided for your convenience – and is, much like our security checklist – not meant to exhaustive. It is probably possible to build a slow Electron app that follows all the steps outlined below. Electron is a powerful development platform that enables you, the developer, to do more or less whatever you want. All that freedom means that performance is largely your responsibility.
Measure, Measure, Measure
The list below contains a number of steps that are fairly straightforward and easy to implement. However, building the most performant version of your app will require you to go beyond a number of steps. Instead, you will have to closely examine all the code running in your app by carefully profiling and measuring. Where are the bottlenecks? When the user clicks a button, what operations take up the brunt of the time? While the app is simply idling, which objects take up the most memory?
Time and time again, we have seen that the most successful strategy for building a performant Electron app is to profile the running code, find the most resource-hungry piece of it, and to optimize it. Repeating this seemingly laborious process over and over again will dramatically increase your app's performance. Experience from working with major apps like Visual Studio Code or Slack has shown that this practice is by far the most reliable strategy to improve performance.
To learn more about how to profile your app's code, familiarize yourself with the Chrome Developer Tools. For advanced analysis looking at multiple processes at once, consider the Chrome Tracing tool.
Checklist
Chances are that your app could be a little leaner, faster, and generally less resource-hungry if you attempt these steps.
1) Carelessly including modules
Before adding a Node.js module to your application, examine said module. How
many dependencies does that module include? What kind of resources does
it need to simply be called in a require()
statement? You might find
that the module with the most downloads on the NPM package registry or the most stars on GitHub
is not in fact the leanest or smallest one available.
Why?
The reasoning behind this recommendation is best illustrated with a real-world
example. During the early days of Electron, reliable detection of network
connectivity was a problem, resulting many apps to use a module that exposed a
simple isOnline()
method.
That module detected your network connectivity by attempting to reach out to a
number of well-known endpoints. For the list of those endpoints, it depended on
a different module, which also contained a list of well-known ports. This
dependency itself relied on a module containing information about ports, which
came in the form of a JSON file with more than 100,000 lines of content.
Whenever the module was loaded (usually in a require('module')
statement),
it would load all its dependencies and eventually read and parse this JSON
file. Parsing many thousands lines of JSON is a very expensive operation. On
a slow machine it can take up whole seconds of time.
In many server contexts, startup time is virtually irrelevant. A Node.js server that requires information about all ports is likely actually "more performant" if it loads all required information into memory whenever the server boots at the benefit of serving requests faster. The module discussed in this example is not a "bad" module. Electron apps, however, should not be loading, parsing, and storing in memory information that it does not actually need.
In short, a seemingly excellent module written primarily for Node.js servers running Linux might be bad news for your app's performance. In this particular example, the correct solution was to use no module at all, and to instead use connectivity checks included in later versions of Chromium.
How?
When considering a module, we recommend that you check:
- the size of dependencies included
- the resources required to load (
require()
) it - the resources required to perform the action you're interested in
Generating a CPU profile and a heap memory profile for loading a module can be done
with a single command on the command line. In the example below, we're looking at
the popular module request
.
node --cpu-prof --heap-prof -e "require('request')"
Executing this command results in a .cpuprofile
file and a .heapprofile
file in the directory you executed it in. Both files can be analyzed using
the Chrome Developer Tools, using the Performance
and Memory
tabs
respectively.
In this example, on the author's machine, we saw that loading request
took
almost half a second, whereas node-fetch
took dramatically less memory
and less than 50ms.
2) Loading and running code too soon
If you have expensive setup operations, consider deferring those. Inspect all the work being executed right after the application starts. Instead of firing off all operations right away, consider staggering them in a sequence more closely aligned with the user's journey.
In traditional Node.js development, we're used to putting all our require()
statements at the top. If you're currently writing your Electron application
using the same strategy and are using sizable modules that you do not
immediately need, apply the same strategy and defer loading to a more
opportune time.
Why?
Loading modules is a surprisingly expensive operation, especially on Windows. When your app starts, it should not make users wait for operations that are currently not necessary.
This might seem obvious, but many applications tend to do a large amount of work immediately after the app has launched - like checking for updates, downloading content used in a later flow, or performing heavy disk I/O operations.
Let's consider Visual Studio Code as an example. When you open a file, it will immediately display the file to you without any code highlighting, prioritizing your ability to interact with the text. Once it has done that work, it will move on to code highlighting.
How?
Let's consider an example and assume that your application is parsing files
in the fictitious .foo
format. In order to do that, it relies on the
equally fictitious foo-parser
module. In traditional Node.js development,
you might write code that eagerly loads dependencies:
const fs = require('fs')
const fooParser = require('foo-parser')
class Parser {
constructor () {
this.files = fs.readdirSync('.')
}
getParsedFiles () {
return fooParser.parse(this.files)
}
}
const parser = new Parser()
module.exports = { parser }
In the above example, we're doing a lot of work that's being executed as soon
as the file is loaded. Do we need to get parsed files right away? Could we
do this work a little later, when getParsedFiles()
is actually called?
// "fs" is likely already being loaded, so the `require()` call is cheap
const fs = require('fs')
class Parser {
async getFiles () {
// Touch the disk as soon as `getFiles` is called, not sooner.
// Also, ensure that we're not blocking other operations by using
// the asynchronous version.
this.files = this.files || await fs.readdir('.')
return this.files
}
async getParsedFiles () {
// Our fictitious foo-parser is a big and expensive module to load, so
// defer that work until we actually need to parse files.
// Since `require()` comes with a module cache, the `require()` call
// will only be expensive once - subsequent calls of `getParsedFiles()`
// will be faster.
const fooParser = require('foo-parser')
const files = await this.getFiles()
return fooParser.parse(files)
}
}
// This operation is now a lot cheaper than in our previous example
const parser = new Parser()
module.exports = { parser }
In short, allocate resources "just in time" rather than allocating them all when your app starts.
3) Blocking the main process
Electron's main process (sometimes called "browser process") is special: It is the parent process to all your app's other processes and the primary process the operating system interacts with. It handles windows, interactions, and the communication between various components inside your app. It also houses the UI thread.
Under no circumstances should you block this process and the UI thread with long-running operations. Blocking the UI thread means that your entire app will freeze until the main process is ready to continue processing.
Why?
The main process and its UI thread are essentially the control tower for major operations inside your app. When the operating system tells your app about a mouse click, it'll go through the main process before it reaches your window. If your window is rendering a buttery-smooth animation, it'll need to talk to the GPU process about that – once again going through the main process.
Electron and Chromium are careful to put heavy disk I/O and CPU-bound operations onto new threads to avoid blocking the UI thread. You should do the same.
How?
Electron's powerful multi-process architecture stands ready to assist you with your long-running tasks, but also includes a small number of performance traps.
1) For long running CPU-heavy tasks, make use of worker threads, consider moving them to the BrowserWindow, or (as a last resort) spawn a dedicated process.
2) Avoid using the synchronous IPC and the remote
module as much as possible.
While there are legitimate use cases, it is far too easy to unknowingly block
the UI thread using the remote
module.
3) Avoid using blocking I/O operations in the main process. In short, whenever
core Node.js modules (like fs
or child_process
) offer a synchronous or an
asynchronous version, you should prefer the asynchronous and non-blocking
variant.
4) Blocking the renderer process
Since Electron ships with a current version of Chrome, you can make use of the latest and greatest features the Web Platform offers to defer or offload heavy operations in a way that keeps your app smooth and responsive.
Why?
Your app probably has a lot of JavaScript to run in the renderer process. The trick is to execute operations as quickly as possible without taking away resources needed to keep scrolling smooth, respond to user input, or animations at 60fps.
Orchestrating the flow of operations in your renderer's code is particularly useful if users complain about your app sometimes "stuttering".
How?
Generally speaking, all advice for building performant web apps for modern
browsers apply to Electron's renderers, too. The two primary tools at your
disposal are currently requestIdleCallback()
for small operations and
Web Workers
for long-running operations.
requestIdleCallback()
allows developers to queue up a function to be
executed as soon as the process is entering an idle period. It enables you to
perform low-priority or background work wi