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+ACommandOrControl+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(orCmdfor short)Control(orCtrlfor short)CommandOrControl(orCmdOrCtrlfor short)AltOptionAltGrShiftSuper
Available key codes
0to9AtoZF1toF24- Punctuation like
~,!,@,#,$, etc. PlusSpaceTabCapslockNumlockScrolllockBackspaceDeleteInsertReturn(orEnteras alias)Up,Down,LeftandRightHomeandEndPageUpandPageDownEscape(orEscfor short)VolumeUp,VolumeDownandVolumeMuteMediaNextTrack,MediaPreviousTrack,MediaStopandMediaPlayPausePrintScreen- NumPad Keys
num0-num9numdec- 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:
launchInfounknown 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:
eventEvent
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:
eventEvent
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:
eventEventexitCodeInteger
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:
eventEventpathString
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:
eventEventurlString
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:
eventEventhasVisibleWindowsBoolean
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: 'continue-activity' macOS
Returns:
eventEventtypeString - A string identifying the activity. Maps toNSUserActivity.activityType.userInfounknown - 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:
eventEventtypeString - 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:
eventEventtypeString - A string identifying the activity. Maps toNSUserActivity.activityType.errorString - 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:
eventEventtypeString - A string identifying the activity. Maps toNSUserActivity.activityType.userInfounknown - 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:
eventEventtypeString - A string identifying the activity. Maps toNSUserActivity.activityType.userInfounknown - 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:
eventEvent
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:
eventEventwindowBrowserWindow
Emitted when a browserWindow gets blurred.
Event: 'browser-window-focus'
Returns:
eventEventwindowBrowserWindow
Emitted when a browserWindow gets focused.
Event: 'browser-window-created'
Returns:
eventEventwindowBrowserWindow
Emitted when a new browserWindow is created.
Event: 'web-contents-created'
Returns:
eventEventwebContentsWebContents
Emitted when a new webContents is created.
Event: 'certificate-error'
Returns:
eventEventwebContentsWebContentsurlStringerrorString - The error codecertificateCertificatecallbackFunctionisTrustedBoolean - 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:
eventEventwebContentsWebContentsurlURLcertificateListCertificate[]callbackFunctioncertificateCertificate (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:
eventEventwebContentsWebContentsauthenticationResponseDetailsObjecturlURL
authInfoObjectisProxyBooleanschemeStringhostStringportIntegerrealmString
callbackFunctionusernameString (optional)passwordString (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'
Returns:
eventEventkilledBoolean
Emitted when the GPU process crashes or is killed.
Event: 'renderer-process-crashed' Deprecated
Returns:
eventEventwebContentsWebContentskilledBoolean
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 dissapeared. 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:
eventEventwebContentsWebContentsdetailsObjectreasonString - 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 dissapears. This is normally because it was crashed or killed.
Event: 'accessibility-support-changed' macOS Windows
Returns:
eventEventaccessibilitySupportEnabledBoolean -truewhen Chrome's accessibility support is enabled,falseotherwise.
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:
sessionSession
Emitted when Electron has created a new session.
const { app } = require('electron')
app.on('session-created', (session) => {
console.log(session)
})
Event: 'second-instance'
Returns:
eventEventargvString[] - An array of the second instance's command line argumentsworkingDirectoryString - 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:
eventEventwebContentsWebContents
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:
eventEventwebContentsWebContentsmoduleNameString
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:
eventEventwebContentsWebContentsglobalNameString
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:
eventEventwebContentsWebContentsmoduleNameString
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:
eventEventwebContentsWebContents
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:
eventEventwebContentsWebContents
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])
exitCodeInteger (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])
optionsObject (optional)argsString[] (optional)execPathString (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])
optionsObject (optional)stealBoolean 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])
pathString (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)
nameString - You can request the following paths by the name:homeUser's home directory.appDataPer-user application data directory, which by default points to:%APPDATA%on Windows$XDG_CONFIG_HOMEor~/.configon Linux~/Library/Application Supporton macOS
userDataThe directory for storing your app's configuration files, which by default it is theappDatadirectory appended with your app's name.cachetempTemporary directory.exeThe current executable file.moduleThelibchromiumcontentlibrary.desktopThe current user's Desktop directory.documentsDirectory for a user's "My Documents".downloadsDirectory for a user's downloads.musicDirectory for a user's music.picturesDirectory for a user's pictures.videosDirectory for a user's videos.recentDirectory for the user's recent files (Windows only).logsDirectory for your app's log folder.pepperFlashSystemPluginFull path to the system version of the Pepper Flash plugin.crashDumpsDirectory 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])
pathStringoptionsObject (optional)sizeStringsmall- 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)
nameStringpathString
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)
nameString
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
pathString
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])
protocolString - The name of your protocol, without://. For example, if you want your app to handleelectron://links, call this method withelectronas the parameter.pathString (optional) Windows - The path to the Electron executable. Defaults toprocess.execPathargsString[] (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
protocolString - The name of your protocol, without://.pathString (optional) Windows - Defaults toprocess.execPathargsString[] (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])
protocolString - The name of your protocol, without://.pathString (optional) Windows - Defaults toprocess.execPathargsString[] (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)
urlString - 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.setUserTasks(tasks) Windows
tasksTask[] - Array ofTaskobjects
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:
minItemsInteger - 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).removedItemsJumpListItem[] - Array ofJumpListItemobjects 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
categoriesJumpListCategory[] |null- Array ofJumpListCategoryobjects.
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 standardTaskscategory.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(() => {
})
}
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
typeString - Uniquely identifies the activity. Maps toNSUserActivity.activityType.userInfoany - App-specific state to store for use by another device.webpageURLString (optional) - The webpage to load in a browser if no suitable app is installed on the resuming device. The scheme must behttporhttps.
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
typeString - Uniquely identifies the activity. Maps toNSUserActivity.activityType.userInfoany - 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
policyString - 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
optionsObjectcertificateString - Path for the pkcs12 file.passwordString - Passphrase for the certificate.
callbackFunctionresultInteger - 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)
infoTypeString - Can bebasicorcomplete.
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
countInteger
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
optionsObject (optional)pathString (optional) Windows - The executable path to compare against. Defaults toprocess.execPath.argsString[] (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:
openAtLoginBoolean -trueif the app is set to open at login.openAsHiddenBoolean macOS -trueif the app is set to open as hidden at login. This setting is not available on MAS builds.wasOpenedAtLoginBoolean macOS -trueif the app was opened at login automatically. This setting is not available on MAS builds.wasOpenedAsHiddenBoolean macOS -trueif 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.restoreStateBoolean macOS -trueif 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.
app.setLoginItemSettings(settings) macOS Windows
settingsObjectopenAtLoginBoolean (optional) -trueto open the app at login,falseto remove the app as a login item. Defaults tofalse.openAsHiddenBoolean (optional) macOS -trueto open the app as hidden. Defaults tofalse. The user can edit this setting from the System Preferences soapp.getLoginItemSettings().wasOpenedAsHiddenshould be checked when the app is opened to know the current value. This setting is not available on MAS builds.pathString (optional) Windows - The executable to launch at login. Defaults toprocess.execPath.argsString[] (optional) Windows - The command-line arguments to pass to the executable. Defaults to an empty array. Take care to wrap paths in quotes.
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
enabledBoolean - 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)
optionsObjectapplicationNameString (optional) - The app's name.applicationVersionString (optional) - The app's version.copyrightString (optional) - Copyright information.versionString (optional) macOS - The app's build version number.creditsString (optional) macOS Windows - Credit information.authorsString[] (optional) Linux - List of app authors.websiteString (optional) Linux - The app's website.iconPathString (optional) Linux Windows - Path to the app's icon. 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
bookmarkDataString - The base64 encoded security scoped bookmark data returned by thedialog.showOpenDialogordialog.showSaveDialogmethods.
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
optionsObject (optional)conflictHandlerFunction(optional) - A handler for potential conflict in move failure. conflictTypeString - The type of move conflict encountered by the handler; can beexistsorexistsAndRunning, whereexistsmeans that an app of the same name is present in the Applications directory andexistsAndRunningmeans 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 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
enabledBoolean - 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.
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.
Application Distribution
To distribute your app with Electron, you need to package and rebrand it. The easiest way to do this is to use one of the following third party packaging tools:
These tools will take care of all the steps you need to take to end up with a distributable Electron applications, such as packaging your application, rebranding the executable, setting the right icons and optionally creating installers.
Manual distribution
You can also choose to manually get your app ready for distribution. The steps needed to do this are outlined below.
To distribute your app with Electron, 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 that 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 (or electron on Linux, electron.exe on Windows),
and Electron will start as your app. The electron directory will then be
your distribution to deliver to final users.
Packaging Your App into a File
Apart from shipping your app by copying all of its source files, you can also package your app into an asar archive to avoid exposing your app's source code to users.
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
More details can be found in Application packaging.
Rebranding with Downloaded Binaries
After bundling your app into Electron, you will want to rebrand Electron before distributing it to users.
Windows
You can rename electron.exe to any name you like, and edit its icon and other
information with tools like rcedit.
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.plistElectron.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
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.
Creating a Custom Electron Fork
Creating a custom fork of Electron is almost certainly not something you will
need to do in order to build your app, even for "Production Level" applications.
Using a tool such as electron-packager or electron-forge will allow you to
"Rebrand" Electron without having to do these steps.
You need to fork Electron when you have custom C++ code that you have patched directly into Electron, that either cannot be upstreamed, or has been rejected from the official version. As maintainers of Electron, we very much would like to make your scenario work, so please try as hard as you can to get your changes into the official version of Electron, it will be much much easier on you, and we appreciate your help.
Creating a Custom Release with surf-build
-
Install Surf, via npm:
npm install -g surf-build@latest -
Create a new S3 bucket and create the following empty directory structure:
- electron/ - symbols/ - dist/ -
Set the following Environment Variables:
ELECTRON_GITHUB_TOKEN- a token that can create releases on GitHubELECTRON_S3_ACCESS_KEY,ELECTRON_S3_BUCKET,ELECTRON_S3_SECRET_KEY- the place where you'll upload Node.js headers as well as symbolsELECTRON_RELEASE- Set totrueand the upload part will run, leave unset andsurf-buildwill do CI-type checks, appropriate to run for every pull request.CI- Set totrueor else it will failGITHUB_TOKEN- set it to the same asELECTRON_GITHUB_TOKENSURF_TEMP- set toC:\Tempon Windows to prevent path too long issuesTARGET_ARCH- set toia32orx64
-
In
script/upload.py, you must setELECTRON_REPOto your fork (MYORG/electron), especially if you are a contributor to Electron proper. -
surf-build -r https://github.com/MYORG/electron -s YOUR_COMMIT -n 'surf-PLATFORM-ARCH' -
Wait a very, very long time for the build to complete.
Application Packaging
To mitigate issues around long
path names on Windows, slightly speed up require and conceal your source code
from cursory inspection, you can choose to package your app into an asar
archive with little changes to your source code.
Most users will get this feature for free, since it's supported out of the box
by electron-packager, electron-forge,
and electron-builder. If you are not using any of these
tools, read on.
Generating asar Archives
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.
Steps to package your app into an asar archive:
1. Install the asar Utility
$ npm install -g asar
2. Package with asar pack
$ asar pack your-app app.asar
Using asar Archives
In Electron there are two sets of APIs: Node APIs provided by Node.js and Web
APIs provided by Chromium. Both APIs support reading files from asar archives.
Node API
With special patches in Electron, Node APIs like fs.readFile and require
treat asar archives as virtual directories, and the files in it as normal
files in the filesystem.
For example, suppose we have an example.asar archive under /path/to:
$ asar list /path/to/example.asar
/app.js
/file.txt
/dir/module.js
/static/index.html
/static/main.css
/static/jquery.min.js
Read a file in the asar archive:
const fs = require('fs')
fs.readFileSync('/path/to/example.asar/file.txt')
List all files under the root of the archive:
const fs = require('fs')
fs.readdirSync('/path/to/example.asar')
Use a module from the archive:
require('./path/to/example.asar/dir/module.js')
You can also display a web page in an asar archive with BrowserWindow:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.loadURL('file:///path/to/example.asar/static/index.html')
Web API
In a web page, files in an archive can be requested with the file: protocol.
Like the Node API, asar archives are treated as directories.
For example, to get a file with $.get:
<script>
let $ = require('./jquery.min.js')
$.get('file:///path/to/example.asar/file.txt', (data) => {
console.log(data)
})
</script>
Treating an asar Archive as a Normal File
For some cases like verifying the asar archive's checksum, we need to read the
content of an asar archive as a file. For this purpose you can use the built-in
original-fs module which provides original fs APIs without asar support:
const originalFs = require('original-fs')
originalFs.readFileSync('/path/to/example.asar')
You can also set process.noAsar to true to disable the support for asar in
the fs module:
const fs = require('fs')
process.noAsar = true
fs.readFileSync('/path/to/example.asar')
Limitations of the Node API
Even though we tried hard to make asar archives in the Node API work like
directories as much as possible, there are still limitations due to the
low-level nature of the Node API.
Archives Are Read-only
The archives can not be modified so all Node APIs that can modify files will not
work with asar archives.
Working Directory Can Not Be Set to Directories in Archive
Though asar archives are treated as directories, there are no actual
directories in the filesystem, so you can never set the working directory to
directories in asar archives. Passing them as the cwd option of some APIs
will also cause errors.
Extra Unpacking on Some APIs
Most fs APIs can read a file or get a file's information from asar archives
without unpacking, but for some APIs that rely on passing the real file path to
underlying system calls, Electron will extract the needed file into a
temporary file and pass the path of the temporary file to the APIs to make them
work. This adds a little overhead for those APIs.
APIs that requires extra unpacking are:
child_process.execFilechild_process.execFileSyncfs.openfs.openSyncprocess.dlopen- Used byrequireon native modules
Fake Stat Information of fs.stat
The Stats object returned by fs.stat and its friends on files in asar
archives is generated by guessing, because those files do not exist on the
filesystem. So you should not trust the Stats object except for getting file
size and checking file type.
Executing Binaries Inside asar Archive
There are Node APIs that can execute binaries like child_process.exec,
child_process.spawn and child_process.execFile, but only execFile is
supported to execute binaries inside asar archive.
This is because exec and spawn accept command instead of file as input,
and commands are executed under shell. There is no reliable way to determine
whether a command uses a file in asar archive, and even if we do, we can not be
sure whether we can replace the path in command without side effects.
Adding Unpacked Files to asar Archives
As stated above, some Node APIs will unpack the file to the filesystem when called. Apart from the performance issues, various anti-virus scanners might be triggered by this behavior.
As a workaround, you can leave various files unpacked using the --unpack option.
In the following example, shared libraries of native Node.js modules will not be
packed:
$ asar pack app app.asar --unpack *.node
After running the command, you will notice that a folder named app.asar.unpacked
was created together with the app.asar file. It contains the unpacked files
and should be shipped together with the app.asar archive.
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:
eventEventreleaseNotesStringreleaseNameStringreleaseDateDateupdateURLString
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)
optionsObjecturlStringheadersRecord<String, String> (optional) macOS - HTTP request headers.serverTypeString (optional) macOS - Eitherjsonordefault, 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
appveyorlibccbuildsDisk Storage Account Name you'd look forappveyorlibccbuildsin 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
ps1file 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
Connectto connect to the VM.- Credentials for logging into the VM are found in LastPass under the
AppVeyor Enterprise master VMcredentials.
- 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
deviceNameStringdeviceIdString
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.
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: 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 methods in the renderer process
The following crashReporter methods are no longer available in the renderer
process:
crashReporter.startcrashReporter.getLastCrashReportcrashReporter.getUploadedReportscrashReporter.getUploadToServercrashReporter.setUploadToServercrashReporter.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(/* ... */)
Planned Breaking API Changes (11.0)
There are no breaking changes planned for 11.0.
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.startcrashReporter.getLastCrashReportcrashReporter.getUploadedReportscrashReporter.getUploadToServercrashReporter.setUploadToServercrashReporter.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.
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,Infinityand-Infinitywill 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,ErrorandRegExpvalues will be correctly serialized, instead of being converted to{}.BigIntvalues will be correctly serialized, instead of being converted tonull.- Sparse arrays will be serialized as such, instead of being converted to dense
arrays with
nulls. Dateobjects will be transferred asDateobjects, instead of being converted to their ISO string representation.- Typed Arrays (such as
Uint8Array,Uint16Array,Uint32Arrayand so on) will be transferred as such, instead of being converted to Node.jsBuffer. - Node.js
Bufferobjects will be transferred asUint8Arrays. You can convert aUint8Arrayback to a Node.jsBufferby 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: 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.electronandprocess.version.chromewill be made read-only properties for consistency with the otherprocess.versionsproperties 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
optionsObject (optional)webPreferencesObject (optional) - See BrowserWindow.
BrowserView.getAllViews()
Returns BrowserView[] - An array of all opened BrowserViews.
BrowserView.fromWebContents(webContents)
webContentsWebContents
Returns BrowserView | null - The BrowserView that owns the given webContents
or null if the contents are not owned by a BrowserView.
Instance Properties
Objects created with new BrowserView have the following properties:
view.webContents Experimental
A WebContents object owned by this view.
view.id Experimental
A Integer representing the unique ID of the view.
Instance Methods
Objects created with new BrowserView have the following instance methods:
view.destroy()
Force closing the view, the unload and beforeunload events won't be emitted
for the web page. After you're done with a view, call this function in order to
free memory and other resources as soon as possible.
view.isDestroyed()
Returns Boolean - Whether the view is destroyed.
view.setAutoResize(options) Experimental
optionsObjectwidthBoolean (optional) - Iftrue, the view's width will grow and shrink together with the window.falseby default.heightBoolean (optional) - Iftrue, the view's height will grow and shrink together with the window.falseby default.horizontalBoolean (optional) - Iftrue, the view's x position and width will grow and shrink proportionally with the window.falseby default.verticalBoolean (optional) - Iftrue, the view's y position and height will grow and shrink proportionally with the window.falseby default.
view.setBounds(bounds) Experimental
boundsRectangle
Resizes and moves the view to the supplied bounds relative to the window.
view.setBackgroundColor(color) Experimental
colorString - Color in#aarrggbbor#argbform. 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')
let 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')
let 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')
let top = new BrowserWindow()
let 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')
let 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 behiddenonly when the window is minimized or explicitly hidden withwin.hide(). - If a
BrowserWindowis created withshow: false, the initial visibility state will bevisibledespite the window actually being hidden. - If
backgroundThrottlingis disabled, the visibility state will remainvisibleeven 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])
optionsObject (optional)widthInteger (optional) - Window's width in pixels. Default is800.heightInteger (optional) - Window's height in pixels. Default is600.xInteger (optional) - (required if y is used) Window's left offset from screen. Default is to center the window.yInteger (optional) - (required if x is used) Window's top offset from screen. Default is to center the window.useContentSizeBoolean (optional) - Thewidthandheightwould 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.centerBoolean (optional) - Show window in the center of the screen.minWidthInteger (optional) - Window's minimum width. Default is0.minHeightInteger (optional) - Window's minimum height. Default is0.maxWidthInteger (optional) - Window's maximum width. Default is no limit.maxHeightInteger (optional) - Window's maximum height. Default is no limit.resizableBoolean (optional) - Whether window is resizable. Default istrue.movableBoolean (optional) - Whether window is movable. This is not implemented on Linux. Default istrue.minimizableBoolean (optional) - Whether window is minimizable. This is not implemented on Linux. Default istrue.maximizableBoolean (optional) - Whether window is maximizable. This is not implemented on Linux. Default istrue.closableBoolean (optional) - Whether window is closable. This is not implemented on Linux. Default istrue.focusableBoolean (optional) - Whether the window can be focused. Default istrue. On Windows settingfocusable: falsealso implies settingskipTaskbar: true. On Linux settingfocusable: falsemakes the window stop interacting with wm, so the window will always stay on top in all workspaces.alwaysOnTopBoolean (optional) - Whether the window should always stay on top of other windows. Default isfalse.fullscreenBoolean (optional) - Whether the window should show in fullscreen. When explicitly set tofalsethe fullscreen button will be hidden or disabled on macOS. Default isfalse.fullscreenableBoolean (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.simpleFullscreenBoolean (optional) - Use pre-Lion fullscreen on macOS. Default isfalse.skipTaskbarBoolean (optional) - Whether to show the window in taskbar. Default isfalse.kioskBoolean (optional) - Whether the window is in kiosk mode. Default isfalse.titleString (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 useICOicons to get best visual effects, you can also leave it undefined so the executable's icon will be used.showBoolean (optional) - Whether window should be shown when created. Default istrue.paintWhenInitiallyHiddenBoolean (optional) - Whether the renderer should be active whenshowisfalseand it has just been created. In order fordocument.visibilityStateto work correctly on first load withshow: falseyou should set this tofalse. Setting this tofalsewill cause theready-to-showevent to not fire. Default istrue.frameBoolean (optional) - Specifyfalseto create a Frameless Window. Default istrue.parentBrowserWindow (optional) - Specify parent window. Default isnull.modalBoolean (optional) - Whether this is a modal window. This only works when the window is a child window. Default isfalse.acceptFirstMouseBoolean (optional) - Whether the web view accepts a single mouse-down event that simultaneously activates the window. Default isfalse.disableAutoHideCursorBoolean (optional) - Whether to hide cursor when typing. Default isfalse.autoHideMenuBarBoolean (optional) - Auto hide the menu bar unless theAltkey is pressed. Default isfalse.enableLargerThanScreenBoolean (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.backgroundColorString (optional) - Window's background color as a hexadecimal value, like#66CD00or#FFFor#80FFFFFF(alpha in #AARRGGBB format is supported iftransparentis set totrue). Default is#FFF(white).hasShadowBoolean (optional) - Whether window should have a shadow. Default istrue.opacityNumber (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.darkThemeBoolean (optional) - Forces using dark theme for the window, only works on some GTK+3 desktop environments. Default isfalse.transparentBoolean (optional) - Makes the window transparent. Default isfalse. On Windows, does not work unless the window is frameless.typeString (optional) - The type of window, default is normal window. See more about this below.visualEffectStateString (optional) - Specify how the material appearance should reflect window activity state on macOS. Must be used with thevibrancyproperty. 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.
titleBarStyleString (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.customButtonsOnHoverBoolean (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.
trafficLightPositionPoint (optional) - Set a custom position for the traffic light buttons. Can only be used withtitleBarStyleset tohiddenfullscreenWindowTitleBoolean (optional) - Shows the title in the title bar in full screen mode on macOS for alltitleBarStyleoptions. Default isfalse.thickFrameBoolean (optional) - UseWS_THICKFRAMEstyle for frameless windows on Windows, which adds standard window frame. Setting it tofalsewill remove window shadow and window animations. Default istrue.vibrancyString (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: falsein combination with a vibrancy value requires that you use a non-defaulttitleBarStyleas well. Also note thatappearance-based,light,dark,medium-light, andultra-darkhave been deprecated and will be removed in an upcoming version of macOS.zoomToPageWidthBoolean (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,falsewill cause it to zoom to the width of the screen. This will also affect the behavior when callingmaximize()directly. Default isfalse.tabbingIdentifierString (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 yourappand window to receive thenew-window-for-tabevent.webPreferencesObject (optional) - Settings of web page's features.devToolsBoolean (optional) - Whether to enable DevTools. If it is set tofalse, can not useBrowserWindow.webContents.openDevTools()to open DevTools. Default istrue.nodeIntegrationBoolean (optional) - Whether node integration is enabled. Default isfalse.nodeIntegrationInWorkerBoolean (optional) - Whether node integration is enabled in web workers. Default isfalse. More about this can be found in Multithreading.nodeIntegrationInSubFramesBoolean (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.isMainFrameto determine if you are in the main frame or not.preloadString (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.sandboxBoolean (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 thenodeIntegrationoption and the APIs available to the preload script are more limited. Read more about the option here.enableRemoteModuleBoolean (optional) - Whether to enable theremotemodule. Default isfalse.sessionSession (optional) - Sets the session used by the page. Instead of passing the Session object directly, you can also choose to use thepartitionoption instead, which accepts a partition string. When bothsessionandpartitionare provided,sessionwill be preferred. Default is the default session.partitionString (optional) - Sets the session used by the page according to the session's partition string. Ifpartitionstarts 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.affinityString (optional) - When specified, web pages with the sameaffinitywill run in the same renderer process. Note that due to reusing the renderer process, certainwebPreferencesoptions will also be shared between the web pages even when you specified different values for them, including but not limited topreload,sandboxandnodeIntegration. So it is suggested to use exact samewebPreferencesfor web pages with the sameaffinity. DeprecatedzoomFactorNumber (optional) - The default zoom factor of the page,3.0represents300%. Default is1.0.javascriptBoolean (optional) - Enables JavaScript support. Default istrue.webSecurityBoolean (optional) - Whenfalse, it will disable the same-origin policy (usually using testing websites by people), and setallowRunningInsecureContenttotrueif this options has not been set by user. Default istrue.allowRunningInsecureContentBoolean (optional) - Allow an https page to run JavaScript, CSS or plugins from http URLs. Default isfalse.imagesBoolean (optional) - Enables image support. Default istrue.textAreasAreResizableBoolean (optional) - Make TextArea elements resizable. Default istrue.webglBoolean (optional) - Enables WebGL support. Default istrue.pluginsBoolean (optional) - Whether plugins should be enabled. Default isfalse.experimentalFeaturesBoolean (optional) - Enables Chromium's experimental features. Default isfalse.scrollBounceBoolean (optional) - Enables scroll bounce (rubber banding) effect on macOS. Default isfalse.enableBlinkFeaturesString (optional) - A list of feature strings separated by,, likeCSSVariables,KeyboardEventKeyto enable. The full list of supported feature strings can be found in the RuntimeEnabledFeatures.json5 file.disableBlinkFeaturesString (optional) - A list of feature strings separated by,, likeCSSVariables,KeyboardEventKeyto disable. The full list of supported feature strings can be found in the RuntimeEnabledFeatures.json5 file.defaultFontFamilyObject (optional) - Sets the default font for the font-family.standardString (optional) - Defaults toTimes New Roman.serifString (optional) - Defaults toTimes New Roman.sansSerifString (optional) - Defaults toArial.monospaceString (optional) - Defaults toCourier New.cursiveString (optional) - Defaults toScript.fantasyString (optional) - Defaults toImpact.
defaultFontSizeInteger (optional) - Defaults to16.defaultMonospaceFontSizeInteger (optional) - Defaults to13.minimumFontSizeInteger (optional) - Defaults to0.defaultEncodingString (optional) - Defaults toISO-8859-1.backgroundThrottlingBoolean (optional) - Whether to throttle animations and timers when the page becomes background. This also affects the Page Visibility API. Defaults totrue.offscreenBoolean (optional) - Whether to enable offscreen rendering for the browser window. Defaults tofalse. See the offscreen rendering tutorial for more details.contextIsolationBoolean (optional) - Whether to run Electron APIs and the specifiedpreloadscript in a separate JavaScript context. Defaults tofalse. The context that thepreloadscript runs in will still have full access to thedocumentandwindowglobals 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 thepreloadscript and not the loaded page. This option should be used when loading potentially untrusted remote content to ensure the loaded content cannot tamper with thepreloadscript 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.worldSafeExecuteJavaScriptBoolean (optional) - If true, values returned fromwebFrame.executeJavaScriptwill 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. DeprecatednativeWindowOpenBoolean (optional) - Whether to use nativewindow.open(). Defaults tofalse. Child windows will always have node integration disabled unlessnodeIntegrationInSubFramesis true. Note: This option is currently experimental.webviewTagBoolean (optional) - Whether to enable the<webview>tag. Defaults tofalse. Note: Thepreloadscript 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 maliciouspreloadscript. You can use thewill-attach-webviewevent on webContents to strip away thepreloadscript and to validate or alter the<webview>'s initial settings.additionalArgumentsString[] (optional) - A list of strings that will be appended toprocess.argvin the renderer process of this app. Useful for passing small bits of data down to renderer process preload scripts.safeDialogsBoolean (optional) - Whether to enable browser style consecutive dialog protection. Default isfalse.safeDialogsMessageString (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.disableDialogsBoolean (optional) - Whether to disable dialogs completely. OverridessafeDialogs. Default isfalse.navigateOnDragDropBoolean (optional) - Whether dragging and dropping a file or link onto the page causes a navigation. Default isfalse.autoplayPolicyString (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.disableHtmlFullscreenWindowResizeBoolean (optional) - Whether to prevent the window from resizing when entering HTML Fullscreen. Default isfalse.accessibleTitleString (optional) - An alternative title string provided only to accessibility tools such as screen readers. This string is not directly visible to users.spellcheckBoolean (optional) - Whether to enable the builtin spellchecker. Default istrue.enableWebSQLBoolean (optional) - Whether to enable the WebSQL api. Default istrue.v8CacheOptionsString (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
texturedtype adds metal gradient appearance (NSTexturedBackgroundWindowMask). - The
desktoptype 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 useglobalShortcutto 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:
eventEventtitleStringexplicitSetBoolean
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:
eventEvent
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:
eventEventnewBoundsRectangle - 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: 'will-move' macOS Windows
Returns:
eventEventnewBoundsRectangle - 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.
Note: On macOS this event is an alias of moved.
Event: 'moved' macOS
Emitted once when the window is moved to a new position.
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:
eventEventisAlwaysOnTopBoolean
Emitted when the window is set or unset to show always on top of other windows.
Event: 'app-command' Windows Linux
Returns:
eventEventcommandString
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')
let 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-backwardbrowser-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:
eventEventdirectionString
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:
eventEventrotationFloat
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.
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)
webContentsWebContents
Returns BrowserWindow | null - The window that owns the given webContents
or null if the contents are not owned by a window.
BrowserWindow.fromBrowserView(browserView)
browserViewBrowserView
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
pathString
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
nameString
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
pathString
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
nameString
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')
let installed = BrowserWindow.getDevToolsExtensions().hasOwnProperty('devtron')
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
let 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
flagBoolean
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]) macOS Linux
aspectRatioFloat - The aspect ratio to maintain for some portion of the content view.extraSizeSize (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.
win.setBackgroundColor(backgroundColor)
backgroundColorString - Window's background color as a hexadecimal value, like#66CD00or#FFFor#80FFFFFF(alpha is supported iftransparentistrue). Default is#FFF(white).
Sets the background color of the window. See Setting
backgroundColor.
win.previewFile(path[, displayName]) macOS
pathString - 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.displayNameString (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])
boundsPartial<Rectangle>animateBoolean (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])
boundsRectangleanimateBoolean (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])
widthIntegerheightIntegeranimateBoolean (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])
widthIntegerheightIntegeranimateBoolean (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)
widthIntegerheightInteger
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)
widthIntegerheightInteger
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)
resizableBoolean
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
movableBoolean
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
minimizableBoolean
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
maximizableBoolean
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)
fullscreenableBoolean
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
closableBoolean
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])
flagBooleanlevelString (optional) macOS Windows - Values includenormal,floating,torn-off-menu,modal-panel,main-menu,status,pop-up-menu,screen-saver, and(Deprecated). The default isdockfloatingwhenflagis true. Thelevelis reset tonormalwhen the flag is false. Note that fromfloatingtostatusincluded, the window is placed below the Dock on macOS and below the taskbar on Windows. Frompop-up-menuto a higher it is shown above the Dock on macOS and above the taskbar on Windows. See the macOS docs for more details.relativeLevelInteger (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)
mediaSourceIdString - 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])
xIntegeryIntegeranimateBoolean (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
offsetYFloatoffsetXFloat (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')
let win = new BrowserWindow()
let 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
messageIntegercallbackFunction
Hooks a windows message. The callback is called when
the message is received in the WndProc.
win.isWindowMessageHooked(message) Windows
messageInteger
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
filenameString
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
editedBoolean
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])
rectRectangle (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])
urlStringoptionsObject (optional)httpReferrer(String | Referrer) (optional) - An HTTP Referrer URL.userAgentString (optional) - A user agent originating the request.extraHeadersString (optional) - Extra headers separated by "\n"postData(UploadRawData[] | UploadFile[] | UploadBlob[]) (optional)baseURLForDataURLString (optional) - Base URL (with trailing path separator) for files to be loaded by the data URL. This is needed only if the specifiedurlis 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:
let 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])
filePathStringoptionsObject (optional)queryRecord<String, String> (optional) - Passed tourl.format().searchString (optional) - Passed tourl.format().hashString (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])
progressDoubleoptionsObject (optional)modeString Windows - Mode for the progress bar. Can benone,normal,indeterminate,errororpaused.
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
overlayNativeImage | null - the icon to display on the bottom right corner of the taskbar icon. If this parameter isnull, the overlay is cleareddescriptionString - 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
opacityNumber - 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
rectsRectangle[] - 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
buttonsThumbarButton[]
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:
ButtonObjecticonNativeImage - The icon showing in thumbnail toolbar.clickFunctiontooltipString (optional) - The text of the button's tooltip.flagsString[] (optional) - Control specific states and behaviors of the button. By default, it is['enabled'].
The flags is an array that can include following Strings:
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
regionRectangle - 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
toolTipString
Sets the toolTip that is displayed when hovering over the window thumbnail in the taskbar.
win.setAppDetails(options) Windows
optionsObjectappIdString (optional) - Window's App User Model ID. It has to be set, otherwise the other options will have no effect.appIconPathString (optional) - Window's Relaunch Icon.appIconIndexInteger (optional) - Index of the icon inappIconPath. Ignored whenappIconPathis not set. Default is0.relaunchCommandString (optional) - Window's Relaunch Command.relaunchDisplayNameString (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
visibleBoolean
Sets whether the window traffic light buttons should be visible.
This cannot be called when titleBarStyle is set to customButtonsOnHover.
win.setAutoHideMenuBar(hide)
hideBoolean
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
visibleBoolean
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])
visibleBooleanoptionsObject (optional)visibleOnFullScreenBoolean (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])
ignoreBooleanoptionsObject (optional)forwardBoolean (optional) macOS Windows - If true, forwards mouse move messages to Chromium, enabling mouse related events such asmouseleave. Only used whenignoreis true. Ifignoreis 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
enableBoolean
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
focusableBoolean
Changes whether the window can be focused.
On macOS it does not remove the focus from the window.
win.setParentWindow(parent)
parentBrowserWindow | 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
browserWindowBrowserWindow
Adds a window as a tab on this window, after the tab for the window instance.
win.setVibrancy(type) macOS
typeString | 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
positionPoint
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
touchBarTouchBar | 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
browserViewBrowserView | null - AttachbrowserViewtowin. If there are otherBrowserViews 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 BrowserViews are attached.
win.addBrowserView(browserView) Experimental
browserViewBrowserView
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)
messageanytargetOriginString
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
# this next line is needed only if building with sccache
$ export GN_EXTRA_ARGS="${GN_EXTRA_ARGS} cc_wrapper=\"${PWD}/electron/external_binaries/sccache\""
$ 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.
To speed up subsequent builds, you can use sccache. Add the GN arg
cc_wrapper = "sccache" by running gn args out/Testing to bring up an
editor and adding a line to the end of the file.
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-tlsIf 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
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, replacing2019andCommunitywith 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 2.7.10 or higher
- Contrary to the
depot_toolssetup instructions linked below, you will need to use your locally installed Python with at least version 2.7.10 (with support for TLS 1.2). To do so, make sure that in PATH, your locally installed Python comes before thedepot_toolsfolder. Right nowdepot_toolsstill comes with Python 2.7.6, which will cause thegclientcommand to fail (see https://crbug.com/868864). - Python for Windows (pywin32) Extensions is also needed in order to run the build process.
- Contrary to the
- Node.js
- Git
- Debugging Tools for Windows of Windows SDK 10.0.15063.468 if you plan on
creating a full distribution since
symstore.exeis used for creating a symbol store from.pdbfiles.- 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.
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.gndefines how Electron itself is built and includes the default configurations for linking with Chromium.build/args/{debug,release,all}.gncontain 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
dataString - PEM encoded dataissuerCertificatePrincipal - Issuer principalissuerNameString - Issuer's Common NameissuerCertCertificate - Issuer certificate (if not self-signed)subjectCertificatePrincipal - Subject principalsubjectNameString - Subject's Common NameserialNumberString - Hex value represented stringvalidStartNumber - Start date of the certificate being valid in secondsvalidExpiryNumber - End date of the certificate being valid in secondsfingerprintString - Fingerprint of the certificate
CertificatePrincipal Object
commonNameString - Common Name.organizationsString[] - Organization names.organizationUnitsString[] - Organization Unit names.localityString - Locality.stateString - State or province.countryString - 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:
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) - Ifoptionsis 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:methodString (optional) - The HTTP request method. Defaults to the GET method.urlString (optional) - The request URL. Must be provided in the absolute form with the protocol scheme specified as http or https.sessionSession (optional) - TheSessioninstance with which the request is associated.partitionString (optional) - The name of thepartitionwith which the request is associated. Defaults to the empty string. Thesessionoption prevails onpartition. Thus if asessionis explicitly specified,partitionis ignored.useSessionCookiesBoolean (optional) - Whether to send cookies with this request from the provided session. This will make thenetrequest's cookie behavior match afetchrequest. Default isfalse.protocolString (optional) - The protocol scheme in the form 'scheme:'. Currently supported values are 'http:' or 'https:'. Defaults to 'http:'.hostString (optional) - The server host provided as a concatenation of the hostname and the port number 'hostname:port'.hostnameString (optional) - The server host name.portInteger (optional) - The server's listening port number.pathString (optional) - The path part of the request URL.redirectString (optional) - The redirect mode for this request. Should be one offollow,errorormanual. Defaults tofollow. When mode iserror, any redirection will be aborted. When mode ismanualthe redirection will be cancelled unlessrequest.followRedirectis invoked synchronously during theredirectevent.
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:
responseIncomingMessage - An object representing the HTTP response message.
Event: 'login'
Returns:
authInfoObjectisProxyBooleanschemeStringhostStringportIntegerrealmString
callbackFunctionusernameString (optional)passwordString (optional)
Emitted when an authenticating proxy is asking for user credentials.
The callback function is expected to be called back with user credentials:
usernameStringpasswordString
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:
errorError - 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:
statusCodeIntegermethodStringredirectUrlStringresponseHeadersRecord<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)
nameString - An extra HTTP header name.valueString - 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.
request.getHeader(name)
nameString - Specify an extra header name.
Returns String - The value of a previously set extra header name.
request.removeHeader(name)
nameString - 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.encodingString (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'.callbackFunction (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)encodingString (optional)callbackFunction (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:
activeBoolean - Whether the request is currently active. If this is false no other properties will be setstartedBoolean - Whether the upload has started. If this is false bothcurrentandtotalwill be set to 0.currentInteger - The number of bytes that have been uploaded so fartotalInteger - 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])
typeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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])
textStringtypeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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])
typeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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])
markupStringtypeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis only available on Linux.
Writes markup to the clipboard.
const { clipboard } = require('electron')
clipboard.writeHTML('<b>Hi</b')
clipboard.readImage([type])
typeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis only available on Linux.
Returns NativeImage - The image content in the clipboard.
clipboard.writeImage(image[, type])
imageNativeImagetypeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis only available on Linux.
Writes image to the clipboard.
clipboard.readRTF([type])
typeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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])
textStringtypeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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:
titleStringurlString
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
titleStringurlStringtypeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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
textString
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])
typeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis only available on Linux.
Clears the clipboard content.
clipboard.availableFormats([type])
typeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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
formatStringtypeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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
formatString
Returns String - Reads format type from the clipboard.
clipboard.readBuffer(format) Experimental
formatString
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
formatStringbufferBuffertypeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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])
dataObjecttextString (optional)htmlString (optional)imageNativeImage (optional)rtfString (optional)bookmarkString (optional) - The title of the URL attext.
typeString (optional) - Can beselectionorclipboard; default is 'clipboard'.selectionis 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
- Comodo
- 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-winstallerwill generate an installer for windows and sign it for youelectron-forgecan sign installers it generates through the Squirrel.Windows or MSI targets.electron-buildercan 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/tmpwhen you need to reference the temporary directory.
- Use
- Using a plain
returnwhen returning explicitly at the end of a function.- Not
return null,return undefined,nullorundefined
- 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.jsrather thanfile_name.js, because in github/atom module names are usually in themodule-nameform. This rule only applies to.jsfiles. - Use newer ES6/ES2015 syntax where appropriate
constfor requires and other constants. If the value is a primitive, use uppercase naming (egconst NUMBER_OF_RETRIES = 5).letfor 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> TagorProcess 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])
switchString - A command-line switch, without the leading--valueString (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)
valueString - 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)
switchString - A command-line switch
Returns Boolean - Whether the command-line switch is present.
commandLine.getSwitchValue(switch)
switchString - 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-sourcesremote.require()/remote-requireremote.getGlobal()/remote-get-builtinremote.getBuiltin()/remote-get-globalremote.getCurrentWindow()/remote-get-current-windowremote.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.1Forces all hostnames to be mapped to 127.0.0.1MAP *.google.com proxyForces all google.com subdomains to be resolved to "proxy".MAP test.com [::1]:77Forces "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.comRemaps 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({
include_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])
resultFilePathString (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
valueNumberpercentageNumber
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
apiKeyString - The key to inject the API ontowindowwith. The API will be accessible onwindow[apiKey].apiRecord<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 = apiObjectnow 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
nameString - The name of the cookie.valueString - The value of the cookie.domainString (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains.hostOnlyBoolean (optional) - Whether the cookie is a host-only cookie; this will only betrueif no domain was passed.pathString (optional) - The path of the cookie.secureBoolean (optional) - Whether the cookie is marked as secure.httpOnlyBoolean (optional) - Whether the cookie is marked as HTTP only.sessionBoolean (optional) - Whether the cookie is a session cookie or a persistent cookie with an expiration date.expirationDateDouble (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch. Not provided for session cookies.sameSiteString - The Same Site policy applied to this cookie. Can beunspecified,no_restriction,laxorstrict.
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'
eventEventcookieCookie - The cookie that was changed.causeString - 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.
removedBoolean -trueif the cookie was removed,falseotherwise.
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)
filterObjecturlString (optional) - Retrieves cookies which are associated withurl. Empty implies retrieving cookies of all URLs.nameString (optional) - Filters cookies by name.domainString (optional) - Retrieves cookies whose domains match or are subdomains ofdomains.pathString (optional) - Retrieves cookies whose path matchespath.secureBoolean (optional) - Filters cookies by their Secure property.sessionBoolean (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)
detailsObjecturlString - The URL to associate the cookie with. The promise will be rejected if the URL is invalid.nameString (optional) - The name of the cookie. Empty by default if omitted.valueString (optional) - The value of the cookie. Empty by default if omitted.domainString (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.pathString (optional) - The path of the cookie. Empty by default if omitted.secureBoolean (optional) - Whether the cookie should be marked as Secure. Defaults to false.httpOnlyBoolean (optional) - Whether the cookie should be marked as HTTP only. Defaults to false.expirationDateDouble (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.sameSiteString (optional) - The Same Site policy to apply to this cookie. Can beunspecified,no_restriction,laxorstrict. 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)
urlString - The URL associated with the cookie.nameString - 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
percentCPUUsageNumber - Percentage of CPU used since the last call to getCPUUsage. First call returns 0.idleWakeupsPerSecondNumber - 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
dateDateidString
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)
optionsObjectsubmitURLString - URL that crash reports will be sent to as POST.productNameString (optional) - Defaults toapp.name.companyNameString (optional) Deprecated - Deprecated alias for{ globalExtra: { _companyName: ... } }.uploadToServerBoolean (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.ignoreSystemCrashHandlerBoolean (optional) - If true, crashes generated in the main process will not be forwarded to the system crash handler. Default isfalse.rateLimitBoolean (optional) macOS Windows - If true, limit the number of crashes uploaded to 1/hour. Default isfalse.compressBoolean (optional) - If true, crash reports will be compressed and uploaded withContent-Encoding: gzip. Default isfalse.extraRecord<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, calladdExtraParameterfrom the child process.globalExtraRecord<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,productNameand 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)
uploadToServerBoolean - 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)
keyString - Parameter key, must be no longer than 39 bytes.valueString - 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)
keyString - Parameter key, must be no longer than 39 bytes.
Remove a 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:
verString - The version of Electron.platformString - e.g. 'win32'.process_typeString - e.g. 'renderer'.guidString - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72'._versionString - The version inpackage.json._productNameString - The product name in thecrashReporteroptionsobject.prodString - Name of the underlying product. In this case Electron._companyNameString - The company name in thecrashReporteroptionsobject.upload_file_minidumpFile - The crash report in the format ofminidump.- All level one properties of the
extraobject in thecrashReporteroptionsobject.
CustomScheme Object
schemeString - Custom schemes to be registered with options.privilegesObject (optional)standardBoolean (optional) - Default false.secureBoolean (optional) - Default false.bypassCSPBoolean (optional) - Default false.allowServiceWorkersBoolean (optional) - Default false.supportFetchAPIBoolean (optional) - Default false.corsEnabledBoolean (optional) - Default false.
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')
let 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:
eventEventreasonString - 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:
eventEventmethodString - Method name.paramsany - Event parameters defined by the 'parameters' attribute in the remote debugging protocol.sessionIdString - 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])
protocolVersionString (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])
methodString - Method name, should be one of the methods defined by the remote debugging protocol.commandParamsany (optional) - JSON object with request parameters.sessionIdString (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
~/.lldbinitto 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://inspectand selecting to inspect the launched Electron app present there. - Debugging the Main Process in VSCode
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
desktopCapturer
Access information about media sources that can be used to capture audio and video from the desktop using the
navigator.mediaDevices.getUserMediaAPI.
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)
optionsObjecttypesString[] - An array of Strings that lists the types of desktop sources to be captured, available types arescreenandwindow.thumbnailSizeSize (optional) - The size that the media source thumbnail should be scaled to. Default is150x150. 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.fetchWindowIconsBoolean (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
idString - The identifier of a window or screen that can be used as achromeMediaSourceIdconstraint when calling [navigator.webkitGetUserMedia]. The format of the identifier will bewindow:XXorscreen:XX, whereXXis a random generated number.nameString - A screen source will be named eitherEntire ScreenorScreen <index>, while the name of a window source will match the window title.thumbnailNativeImage - A thumbnail image. Note: There is no guarantee that the size of the thumbnail is the same as thethumbnailSizespecified in theoptionspassed todesktopCapturer.getSources. The actual size depends on the scale of the screen or window.display_idString - A unique identifier that will correspond to theidof the matching Display returned by the Screen API. On some platforms, this is equivalent to theXXportion of theidfield above and on others it will differ. It will be an empty string if not available.appIconNativeImage - 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 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.
Developer Environment
Electron development is essentially Node.js development. To turn your operating system into an environment capable of building desktop apps with Electron, you will merely need Node.js, npm, a code editor of your choice, and a rudimentary understanding of your operating system's command line client.
Setting up macOS
Electron supports macOS 10.10 (Yosemite) and up. Apple does not allow running macOS in virtual machines unless the host computer is already an Apple computer, so if you find yourself in need of a Mac, consider using a cloud service that rents access to Macs (like MacInCloud or xcloud).
First, install a recent version of Node.js. We recommend that you install
either the latest LTS or Current version available. Visit
the Node.js download page and select the macOS Installer.
While Homebrew is an offered option, but we recommend against it - many tools
will be incompatible with the way Homebrew installs Node.js.
Once downloaded, execute the installer and let the installation wizard guide you through the installation.
Once installed, confirm that everything works as expected. Find the macOS
Terminal application in your /Applications/Utilities folder (or by
searching for the word Terminal in Spotlight). Open up Terminal
or another command line client of your choice and confirm that both node
and npm are available:
# This command should print the version of Node.js
node -v
# This command should print the version of npm
npm -v
If both commands printed a version number, you are all set! Before you get started, you might want to install a code editor suited for JavaScript development.
Setting up Windows
Electron supports Windows 7 and later versions – attempting to develop Electron applications on earlier versions of Windows will not work. Microsoft provides free virtual machine images with Windows 10 for developers.
First, install a recent version of Node.js. We recommend that you install
either the latest LTS or Current version available. Visit
the Node.js download page and select the Windows Installer.
Once downloaded, execute the installer and let the installation wizard guide
you through the installation.
On the screen that allows you to configure the installation, make sure to
select the Node.js runtime, npm package manager, and Add to PATH
options.
Once installed, confirm that everything works as expected. Find the Windows
PowerShell by opening the Start Menu and typing PowerShell. Open
up PowerShell or another command line client of your choice and confirm that
both node and npm are available:
# This command should print the version of Node.js
node -v
# This command should print the version of npm
npm -v
If both commands printed a version number, you are all set! Before you get started, you might want to install a code editor suited for JavaScript development.
Setting up Linux
Generally speaking, Electron supports Ubuntu 12.04, Fedora 21, Debian 8 and later.
First, install a recent version of Node.js. Depending on your Linux
distribution, the installation steps might differ. Assuming that you normally
install software using a package manager like apt or pacman, use the
official Node.js guidance on installing on Linux.
You're running Linux, so you likely already know how to operate a command line
client. Open up your favorite client and confirm that both node and npm
are available globally:
# This command should print the version of Node.js
node -v
# This command should print the version of npm
npm -v
If both commands printed a version number, you are all set! Before you get started, you might want to install a code editor suited for JavaScript development.
A Good Editor
We might suggest two free popular editors built in Electron: GitHub's Atom and Microsoft's Visual Studio Code. Both of them have excellent JavaScript support.
If you are one of the many developers with a strong preference, know that virtually all code editors and IDEs these days support JavaScript.
DevTools Extension
Electron supports the Chrome DevTools Extension, which can be used to extend the ability of devtools for debugging popular web frameworks.
How to load a DevTools Extension
This document outlines the process for manually loading an extension. You may also try electron-devtools-installer, a third-party tool that downloads extensions directly from the Chrome WebStore.
To load an extension in Electron, you need to download it in Chrome browser,
locate its filesystem path, and then load it by calling the
BrowserWindow.addDevToolsExtension(extension) API.
Using the React Developer Tools as example:
-
Install it in Chrome browser.
-
Navigate to
chrome://extensions, and find its extension ID, which is a hash string likefmkadmapgofadopljbjfkapdkoienihi. -
Find out 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
BrowserWindow.addDevToolsExtensionAPI, for the React Developer Tools, it is something like:const path = require('path') const os = require('os') BrowserWindow.addDevToolsExtension( path.join(os.homedir(), '/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.3.0_0') )
Note: The BrowserWindow.addDevToolsExtension API cannot be called before the
ready event of the app module is emitted.
The extension will be remembered so you only need to call this API once per extension. 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.
How to remove a DevTools Extension
You can pass the name of the extension to the BrowserWindow.removeDevToolsExtension
API to remove it. The name of the extension is returned by
BrowserWindow.addDevToolsExtension and you can get the names of all installed
DevTools Extensions using the BrowserWindow.getDevToolsExtensions API.
Supported DevTools Extensions
Electron only supports a limited set of chrome.* APIs, so some extensions
using unsupported chrome.* APIs for chrome extension features may not work.
Following Devtools Extensions are tested and guaranteed 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, some extensions can not even work for recent versions of Chrome browser, and we are not able to do anything for them.
Then file a bug at Electron's issues list, 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)
browserWindowBrowserWindow (optional)optionsObjecttitleString (optional)defaultPathString (optional)buttonLabelString (optional) - Custom label for the confirmation button, when left empty the default label will be used.filtersFileFilter[] (optional)propertiesString[] (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.createDirectorymacOS - Allow creating new directories from dialog.promptToCreateWindows - 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.noResolveAliasesmacOS - Disable the automatic alias (symlink) path resolution. Selected aliases will now return the alias path instead of their target path.treatPackageAsDirectorymacOS - Treat packages, such as.appfolders, as a directory instead of a file.dontAddToRecentWindows - Do not add the item being opened to the recent documents list.
messageString (optional) macOS - Message to display above input boxes.securityScopedBookmarksBoolean (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)
browserWindowBrowserWindow (optional)optionsObjecttitleString (optional)defaultPathString (optional)buttonLabelString (optional) - Custom label for the confirmation button, when left empty the default label will be used.filtersFileFilter[] (optional)propertiesString[] (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.createDirectorymacOS - Allow creating new directories from dialog.promptToCreateWindows - 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.noResolveAliasesmacOS - Disable the automatic alias (symlink) path resolution. Selected aliases will now return the alias path instead of their target path.treatPackageAsDirectorymacOS - Treat packages, such as.appfolders, as a directory instead of a file.dontAddToRecentWindows - Do not add the item being opened to the recent documents list.
messageString (optional) macOS - Message to display above input boxes.securityScopedBookmarksBoolean (optional) macOS mas - Create security scoped bookmarks when packaged for the Mac App Store.
Returns Promise<Object> - Resolve with an object containing the following:
canceledBoolean - whether or not the dialog was canceled.filePathsString[] - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array.bookmarksString[] (optional) macOS mas - An array matching thefilePathsarray of base64 encoded strings which contains security scoped bookmark data.securityScopedBookmarksmust 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)
browserWindowBrowserWindow (optional)optionsObjecttitleString (optional)defaultPathString (optional) - Absolute directory path, absolute file path, or file name to use by default.buttonLabelString (optional) - Custom label for the confirmation button, when left empty the default label will be used.filtersFileFilter[] (optional)messageString (optional) macOS - Message to display above text fields.nameFieldLabelString (optional) macOS - Custom label for the text displayed in front of the filename text field.showsTagFieldBoolean (optional) macOS - Show the tags input box, defaults totrue.propertiesString[] (optional)showHiddenFiles- Show hidden files in dialog.createDirectorymacOS - Allow creating new directories from dialog.treatPackageAsDirectorymacOS - Treat packages, such as.appfolders, as a directory instead of a file.showOverwriteConfirmationLinux - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.dontAddToRecentWindows - Do not add the item being saved to the recent documents list.
securityScopedBookmarksBoolean (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)
browserWindowBrowserWindow (optional)optionsObjecttitleString (optional)defaultPathString (optional) - Absolute directory path, absolute file path, or file name to use by default.buttonLabelString (optional) - Custom label for the confirmation button, when left empty the default label will be used.filtersFileFilter[] (optional)messageString (optional) macOS - Message to display above text fields.nameFieldLabelString (optional) macOS - Custom label for the text displayed in front of the filename text field.showsTagFieldBoolean (optional) macOS - Show the tags input box, defaults totrue.propertiesString[] (optional)showHiddenFiles- Show hidden files in dialog.createDirectorymacOS - Allow creating new directories from dialog.treatPackageAsDirectorymacOS - Treat packages, such as.appfolders, as a directory instead of a file.showOverwriteConfirmationLinux - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.dontAddToRecentWindows - Do not add the item being saved to the recent documents list.
securityScopedBookmarksBoolean (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:
canceledBoolean - whether or not the dialog was canceled.filePathString (optional) - If the dialog is canceled, this will beundefined.bookmarkString (optional) macOS mas - Base64 encoded string which contains the security scoped bookmark data for the saved file.securityScopedBookmarksmust 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)
browserWindowBrowserWindow (optional)optionsObjecttypeString (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.buttonsString[] (optional) - Array of texts for buttons. On Windows, an empty array will result in one button labeled "OK".defaultIdInteger (optional) - Index of the button in the buttons array which will be selected by default when the message box opens.titleString (optional) - Title of the message box, some platforms will not show it.messageString - Content of the message box.detailString (optional) - Extra information of the message.checkboxLabelString (optional) - If provided, the message box will include a checkbox with the given label.checkboxCheckedBoolean (optional) - Initial checked state of the checkbox.falseby default.icon(NativeImage | String) (optional)cancelIdInteger (optional) - The index of the button to be used to cancel the dialog, via theEsckey. 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,0will be used as the return value.noLinkBoolean (optional) - On Windows Electron will try to figure out which one of thebuttonsare 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 setnoLinktotrue.normalizeAccessKeysBoolean (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&wwill be converted toVie_won Linux andViewon macOS and can be selected viaAlt-Won 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 independed window.
dialog.showMessageBox([browserWindow, ]options)
browserWindowBrowserWindow (optional)optionsObjecttypeString (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.buttonsString[] (optional) - Array of texts for buttons. On Windows, an empty array will result in one button labeled "OK".defaultIdInteger (optional) - Index of the button in the buttons array which will be selected by default when the message box opens.titleString (optional) - Title of the message box, some platforms will not show it.messageString - Content of the message box.detailString (optional) - Extra information of the message.checkboxLabelString (optional) - If provided, the message box will include a checkbox with the given label.checkboxCheckedBoolean (optional) - Initial checked state of the checkbox.falseby default.iconNativeImage (optional)cancelIdInteger (optional) - The index of the button to be used to cancel the dialog, via theEsckey. 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,0will be used as the return value.noLinkBoolean (optional) - On Windows Electron will try to figure out which one of thebuttonsare 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 setnoLinktotrue.normalizeAccessKeysBoolean (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&wwill be converted toVie_won Linux andViewon macOS and can be selected viaAlt-Won Windows and Linux.
Returns Promise<Object> - resolves with a promise containing the following properties:
responseNumber - The index of the clicked button.checkboxCheckedBoolean - The checked state of the checkbox ifcheckboxLabelwas 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)
titleString - The title to display in the error box.contentString - 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 readyevent on Linux, the message will be emitted to stderr,
and no GUI dialog will appear.
dialog.showCertificateTrustDialog([browserWindow, ]options) macOS Windows
browserWindowBrowserWindow (optional)optionsObjectcertificateCertificate - The certificate to trust/import.messageString - 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
messageargument is not used, as the OS provides its own confirmation dialog. - The
browserWindowargument 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
idNumber - Unique identifier associated with the display.rotationNumber - Can be 0, 90, 180, 270, represents screen rotation in clock-wise degrees.scaleFactorNumber - Output device's pixel scale factor.touchSupportString - Can beavailable,unavailable,unknown.monochromeBoolean - Whether or not the display is a monochrome display.accelerometerSupportString - Can beavailable,unavailable,unknown.colorSpaceString - represent a color space (three-dimensional object which contains all realizable color combinations) for the purpose of color conversionscolorDepthNumber - The number of bits per pixel.depthPerComponentNumber - The number of bits per color component.boundsRectanglesizeSizeworkAreaRectangleworkAreaSizeSizeinternalBoolean -truefor an internal display andfalsefor 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
typeString (optional) - Can becriticalorinformational. 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
filePathString
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')
let 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:
eventEventstateString - Can beprogressingorinterrupted.
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:
eventEventstateString - Can becompleted,cancelledorinterrupted.
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)
pathString - 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)
optionsSaveDialogOptions - Set the save file dialog options. This object has the same properties as theoptionsparameter 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.1andstabledates 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.x |
| 12.0.0 | TBD | TBD | TBD | TBD |
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
-betatags - Introduction of conventional commit messages
- Well-defined stabilization branches
- The
masterbranch 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.0to admit only stability or security related fixes to your2.0.0release. - Use
^2.0.0to 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-xline 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
masterbranch will always contain the next major versionX.0.0-nightly.DATEin 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.
masteris 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-trashtrash-clikioclient5kioclient
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
preventDefaultVoidFunction
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
idStringmanifestany - Copy of the extension's manifest data.nameStringpathString - The extension's file path.versionStringurlString - The extension'schrome-extension://URL.
ExtensionInfo Object
nameStringversionString
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.getURLchrome.extension.getBackgroundPage
chrome.runtime
The following properties of chrome.runtime are supported:
chrome.runtime.lastErrorchrome.runtime.id
The following methods of chrome.runtime are supported:
chrome.runtime.getBackgroundPagechrome.runtime.getManifestchrome.runtime.getURLchrome.runtime.connectchrome.runtime.sendMessage
The following events of chrome.runtime are supported:
chrome.runtime.onStartupchrome.runtime.onInstalledchrome.runtime.onSuspendchrome.runtime.onSuspendCanceledchrome.runtime.onConnectchrome.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.sendMessagechrome.tabs.executeScript
Note: In Chrome, passing
-1as a tab ID signifies the "currently active tab". Since Electron has no such concept, passing-1as a tab ID is not supported and will raise an error.
chrome.management
The following methods of chrome.management are supported:
chrome.management.getAllchrome.management.getchrome.management.getSelfchrome.management.getPermissionWarningsByIdchrome.management.getPermissionWarningsByManifestchrome.management.onEnabledchrome.management.onDisabled
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
nameStringextensionsString[]
File Object
Use the HTML5
FileAPI 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
pathString - The path to the file to send.headersRecord<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')
let 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')
let 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')
let 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')
let 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')
let 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
resizabletotruemay make a transparent window stop working on some platforms. - The
blurfilter 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-gpuin 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')
let 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:
let win = require('electron').remote.getCurrentWindow()
let 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.
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. You should not use this module until 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)
acceleratorAcceleratorcallbackFunction
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)
acceleratorsString[] - an array of Accelerators.callbackFunction
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)
acceleratorAccelerator
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)
acceleratorAccelerator
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 iframes, 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_canvasString - Canvas.flash_3dString - Flash.flash_stage3dString - Flash Stage3D.flash_stage3d_baselineString - Flash Stage3D Baseline profile.gpu_compositingString - Compositing.multiple_raster_threadsString - Multiple Raster Threads.native_gpu_memory_buffersString - Native GpuMemoryBuffers.rasterizationString - Rasterization.video_decodeString - Video Decode.video_encodeString - Video Encode.vpx_decodeString - VPx Video Decode.webglString - WebGL.webgl2String - 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:
eventEventtransactionsTransaction[] - Array ofTransactionobjects.
Methods
The inAppPurchase module has the following methods:
inAppPurchase.purchaseProduct(productID[, quantity])
productIDString - The identifiers of the product to purchase. (The identifier ofcom.example.app.product1isproduct1).quantityInteger (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)
productIDsString[] - 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)
dateString - 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:
chunkBuffer - 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-agentare discarded. set-cookieis always an array. Duplicates are added to the array.- For duplicate
cookieheaders, 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
modifiersString[] (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_HOMEor~/.cache/electron/ - macOS:
~/Library/Caches/electron/ - Windows:
$LOCALAPPDATA/electron/Cacheor~/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
readOperationCountNumber - The number of I/O read operations.writeOperationCountNumber - The number of I/O write operations.otherOperationCountNumber - Then number of I/O other operations.readTransferCountNumber - The number of I/O read transfers.writeTransferCountNumber - The number of I/O write transfers.otherTransferCountNumber - 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)
channelStringlistenerFunctioneventIpcMainEvent...argsany[]
Listens to channel, when a new message arrives listener would be called with
listener(event, args...).
ipcMain.once(channel, listener)
channelStringlistenerFunctioneventIpcMainEvent...argsany[]
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)
channelStringlistenerFunction...argsany[]
Removes the specified listener from the listener array for the specified
channel.
ipcMain.removeAllListeners([channel])
channelString (optional)
Removes listeners of the specified channel.
ipcMain.handle(channel, listener)
channelStringlistenerFunction<Promise| any> eventIpcMainInvokeEvent...argsany[]
Adds a handler for an invokeable 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)
channelStringlistenerFunction<Promise| any> eventIpcMainInvokeEvent...argsany[]
Handles a single invokeable 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
frameIdInteger - The ID of the renderer frame that sent this messagereturnValueany - Set this to the value to be returned in a synchronous messagesenderWebContents - Returns thewebContentsthat sent the messageportsMessagePortMain[] - A list of MessagePorts that were transferred with this messagereplyFunction - 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.channelString...argsany[]
IpcMainInvokeEvent Object extends Event
frameIdInteger - The ID of the renderer frame that sent this messagesenderWebContents - Returns thewebContentsthat 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)
channelStringlistenerFunctioneventIpcRendererEvent...argsany[]
Listens to channel, when a new message arrives listener would be called with
listener(event, args...).
ipcRenderer.once(channel, listener)
channelStringlistenerFunctioneventIpcRendererEvent...argsany[]
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)
channelStringlistenerFunction...argsany[]
Removes the specified listener from the listener array for the specified
channel.
ipcRenderer.removeAllListeners(channel)
channelString
Removes all listeners, or those of the specified channel.
ipcRenderer.send(channel, ...args)
channelString...argsany[]
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)
channelString...argsany[]
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 respons to the message, consider using ipcRenderer.send.
ipcRenderer.sendSync(channel, ...args)
channelString...argsany[]
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])
channelStringmessageanytransferMessagePort[] (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)
webContentsIdNumberchannelString...argsany[]
Sends a message to a window with webContentsId via channel.
ipcRenderer.sendToHost(channel, ...args)
channelString...argsany[]
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
senderIpcRenderer - TheIpcRendererinstance that emitted the event originallysenderIdInteger - ThewebContents.idthat 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.senderIdto0.portsMessagePort[] - 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/electronissue 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/electronin 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.
<!--
Thanks for opening an issue! A few things to keep in mind:
- The issue tracker is only for bugs and feature requests.
- Before reporting a bug, please try reproducing your issue against
the latest version of Electron.
- If you need general advice, join our Slack: http://atom-slack.herokuapp.com
-->
* Electron version:
* Operating system:
### Expected behavior
<!-- What do you think should happen? -->
### Actual behavior
<!-- What actually happens? -->
### How to reproduce
<!--
Your best chance of getting this bug looked at quickly is to provide a REPOSITORY that can be cloned and run.
You can fork https://github.com/electron/electron-quick-start and include a link to the branch with your changes.
If you provide a URL, please list the commands required to clone/setup/run your repo e.g.
$ git clone $YOUR_URL -b $BRANCH
$ npm install
$ npm start || electron .
-->
If you believe that you have found a bug in Electron, please fill out this form 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
typeString (optional) - One of the following:tasks- Items in this category will be placed into the standardTaskscategory. 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,namemust be set by the app.
nameString (optional) - Must be set iftypeiscustom, otherwise it should be omitted.itemsJumpListItem[] (optional) - Array ofJumpListItemobjects iftypeistasksorcustom, 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
typeString (optional) - One of the following:task- A task will launch an app with specific arguments.separator- Can be used to separate items in the standardTaskscategory.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).
pathString (optional) - Path of the file to open, should only be set iftypeisfile.programString (optional) - Path of the program to execute, usually you should specifyprocess.execPathwhich opens the current program. Should only be set iftypeistask.argsString (optional) - The command line arguments whenprogramis executed. Should only be set iftypeistask.titleString (optional) - The text to be displayed for the item in the Jump List. Should only be set iftypeistask.descriptionString (optional) - Description of the task (displayed in a tooltip). Should only be set iftypeistask.iconPathString (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.execPathto show the program icon.iconIndexNumber (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.workingDirectoryString (optional) - The working directory. Default is empty.
KeyboardEvent Object extends Event
ctrlKeyBoolean (optional) - whether the Control key was used in an accelerator to trigger the EventmetaKeyBoolean (optional) - whether a meta key was used in an accelerator to trigger the EventshiftKeyBoolean (optional) - whether a Shift key was used in an accelerator to trigger the EventaltKeyBoolean (optional) - whether an Alt key was used in an accelerator to trigger the EventtriggeredByAcceleratorBoolean (optional) - whether an accelerator was used to trigger the event as opposed to another user gesture like mouse click
KeyboardInputEvent Object extends InputEvent
typeString - The type of the event, can bekeyDown,keyUporchar.keyCodeString - The character that will be sent as the keyboard event. Should only use the valid key codes in Accelerator.
Keyboard Shortcuts
Configure local and global keyboard shortcuts
Local Shortcuts
You can use the Menu module to configure keyboard shortcuts that will
be triggered only when the app is focused. To do so, specify an
accelerator property when creating a MenuItem.
const { Menu, MenuItem } = require('electron')
const menu = new Menu()
menu.append(new MenuItem({
label: 'Print',
accelerator: 'CmdOrCtrl+P',
click: () => { console.log('time to print stuff') }
}))
You can configure different key combinations based on the user's operating system.
{
accelerator: process.platform === 'darwin' ? 'Alt+Cmd+I' : 'Ctrl+Shift+I'
}
Global Shortcuts
You can use the globalShortcut module to detect keyboard events even when the application does not have keyboard focus.
const { app, globalShortcut } = require('electron')
app.whenReady().then(() => {
globalShortcut.register('CommandOrControl+X', () => {
console.log('CommandOrControl+X is pressed')
})
})
Shortcuts within a BrowserWindow
If you want to handle keyboard shortcuts for a BrowserWindow, you can use the keyup and keydown event listeners on the window object inside the renderer process.
window.addEventListener('keyup', doSomething, true)
Note the third parameter true which means the listener will always receive key presses before other listeners so they can't have stopPropagation() called on them.
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.
If you don't want to do manual shortcut parsing there are libraries that do advanced key detection such as mousetrap.
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')
})
Custom Linux Desktop Launcher Actions
On many Linux environments, you can add custom entries to its 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.
Launcher shortcuts of Audacious:

Generally speaking, shortcuts are added by providing a Name and Exec
property for each entry in the shortcuts menu. Unity will execute the
Exec field once clicked by the user. The format is 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;
Unity's preferred way of telling your application what to do is to use
parameters. You can find these in your app 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:
crashReporterautoUpdater
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 - http://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
workingSetSizeInteger - The amount of memory currently pinned to actual physical RAM.peakWorkingSetSizeInteger - The maximum amount of memory that has ever been pinned to actual physical RAM.privateBytesInteger (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
countNumbersizeNumberliveSizeNumber
new Menu()
Creates a new menu.
Static Methods
The Menu class has the following static methods:
Menu.setApplicationMenu(menu)
menuMenu | 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
actionString
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])
optionsObject (optional)windowBrowserWindow (optional) - Default is the focused window.xNumber (optional) - Default is the current mouse cursor position. Must be declared ifyis declared.yNumber (optional) - Default is the current mouse cursor position. Must be declared ifxis declared.positioningItemNumber (optional) macOS - The index of the menu item to be positioned under the mouse cursor at the specified coordinates. Default is -1.callbackFunction (optional) - Called when menu is closed.
Pops up this menu as a context menu in the BrowserWindow.
menu.closePopup([browserWindow])
browserWindowBrowserWindow (optional) - Default is the focused window.
Closes the context menu in the browserWindow.
menu.insert(pos, menuItem)
posIntegermenuItemMenuItem
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:
eventEvent
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 MenuItems 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:
windowhelpservices
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)
optionsObjectclickFunction (optional) - Will be called withclick(menuItem, browserWindow, event)when the menu item is clicked.menuItemMenuItembrowserWindowBrowserWindow | undefined - This will not be defined if no window is open.eventKeyboardEvent
roleString (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,moveTabToNewWindoworwindowMenu- Define the action of the menu item, when specified theclickproperty will be ignored. See roles.typeString (optional) - Can benormal,separator,submenu,checkboxorradio.labelString (optional)sublabelString (optional)toolTipString (optional) macOS - Hover text for this menu item.acceleratorAccelerator (optional)icon(NativeImage | String) (optional)enabledBoolean (optional) - If false, the menu item will be greyed out and unclickable.acceleratorWorksWhenHiddenBoolean (optional) macOS - default istrue, and whenfalsewill prevent the accelerator from triggering the item if the item is not visible`.visibleBoolean (optional) - If false, the menu item will be entirely hidden.checkedBoolean (optional) - Should only be specified forcheckboxorradiotype menu items.registerAcceleratorBoolean (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 forsubmenutype menu items. Ifsubmenuis specified, thetype: 'submenu'can be omitted. If the value is not aMenuthen it will be automatically converted to one usingMenu.buildFromTemplate.idString (optional) - Unique within a single menu. If defined then it can be used as a reference to this item by the position attribute.beforeString[] (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.afterString[] (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.beforeGroupContainingString[] (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.afterGroupContainingString[] (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:
undoabout- Trigger a native about panel (custom message box on Window, which does not provide its own).redocutcopypastepasteAndMatchStyleselectAlldeleteminimize- 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 thehideaction.hideOthers- Map to thehideOtherApplicationsaction.unhide- Map to theunhideAllApplicationsaction.startSpeaking- Map to thestartSpeakingaction.stopSpeaking- Map to thestopSpeakingaction.front- Map to thearrangeInFrontaction.zoom- Map to theperformZoomaction.toggleTabBar- Map to thetoggleTabBaraction.selectNextTab- Map to theselectNextTabaction.selectPreviousTab- Map to theselectPreviousTabaction.mergeAllWindows- Map to themergeAllWindowsaction.moveTabToNewWindow- Map to themoveTabToNewWindowaction.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 theclearRecentDocumentsaction.
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).
eventKeyboardEventfocusedWindowBrowserWindowfocusedWebContentsWebContents
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])
messageanytransferMessagePortMain[] (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:
messageEventObjectdataanyportsMessagePortMain[]
Emitted when a MessagePortMain object receives a message.
Event: 'close'
Emitted when the remote end of a MessagePortMain object becomes disconnected.
MimeTypedBuffer Object
mimeTypeString (optional) - MIME type of the buffer.charsetString (optional) - Charset of the buffer.dataBuffer - The actual Buffer content.
Supporting macOS Dark Mode
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 either have NSRequiresAquaSystemAppearance set to false in your
Info.plist file, or be on Electron >=7.0.0. Both Electron Packager and
Electron Forge have a darwinDarkModeSupport option
to automate the Info.plist changes during app build time.
Automatically updating the native interfaces
"Native Interfaces" include the file picker, window border, dialogs, context menus, and more; basically,
anything where the UI comes from macOS and not your app. As of Electron 7.0.0, the default behavior
is to opt into this automatic theming from the OS. If you wish to opt-out and are 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.
Automatically updating 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 listening for the theme updated event on Electron's nativeTheme module.
For example:
const { nativeTheme } = require('electron')
nativeTheme.on('updated', function theThemeHasChanged () {
updateMyAppTheme(nativeTheme.shouldUseDarkColors)
})
MouseInputEvent Object extends InputEvent
typeString - The type of the event, can bemouseDown,mouseUp,mouseEnter,mouseLeave,contextMenu,mouseWheelormouseMove.xIntegeryIntegerbuttonString (optional) - The button pressed, can beleft,middle,right.globalXInteger (optional)globalYInteger (optional)movementXInteger (optional)movementYInteger (optional)clickCountInteger (optional)
MouseWheelInputEvent Object extends MouseInputEvent
typeString - The type of the event, can bemouseWheel.deltaXInteger (optional)deltaYInteger (optional)wheelTicksXInteger (optional)wheelTicksYInteger (optional)accelerationRatioXInteger (optional)accelerationRatioYInteger (optional)hasPreciseScrollingDeltasBoolean (optional)canScrollBoolean (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.pngxxxTemplate@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
pathString - path to a file that we intend to construct a thumbnail out of.maxSizeSize - the maximum width and height (positive numbers) the thumbnail returned can be. The Windows implementation will ignoremaxSize.heightand scale the height according tomaxSize.width.
Returns Promise<NativeImage> - fulfilled with the file's thumbnail preview image, which is a NativeImage.
nativeImage.createFromPath(path)
pathString
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)
bufferBufferoptionsObjectwidthIntegerheightIntegerscaleFactorDouble (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])
bufferBufferoptionsObject (optional)widthInteger (optional) - Required for bitmap buffers.heightInteger (optional) - Required for bitmap buffers.scaleFactorDouble (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)
dataURLString
Returns NativeImage
Creates a new NativeImage instance from dataURL.
nativeImage.createFromNamedImage(imageName[, hslShift]) macOS
imageNameStringhslShiftNumber[] (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])
optionsObject (optional)scaleFactorDouble (optional) - Defaults to 1.0.
Returns Buffer - A Buffer that contains the image's PNG encoded data.
image.toJPEG(quality)
qualityInteger - Between 0 - 100.
Returns Buffer - A Buffer that contains the image's JPEG encoded data.
image.toBitmap([options])
optionsObject (optional)scaleFactorDouble (optional) - Defaults to 1.0.
Returns Buffer - A Buffer that contains a copy of the image's raw bitmap pixel
data.
image.toDataURL([options])
optionsObject (optional)scaleFactorDouble (optional) - Defaults to 1.0.
Returns String - The data URL of the image.
image.getBitmap([options])
optionsObject (optional)scaleFactorDouble (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])
scaleFactorDouble (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)
rectRectangle - The area of the image to crop.
Returns NativeImage - The cropped image.
image.resize(options)
optionsObjectwidthInteger (optional) - Defaults to the image's width.heightInteger (optional) - Defaults to the image's height.qualityString (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])
scaleFactorDouble (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)
optionsObjectscaleFactorDouble - The scale factor to add the image representation for.widthInteger (optional) - Defaults to 0. Required if a bitmap buffer is specified asbuffer.heightInteger (optional) - Defaults to 0. Required if a bitmap buffer is specified asbuffer.bufferBuffer (optional) - The buffer containing the raw image data.dataURLString (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.shouldUseDarkColorswill betruewhen 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-schemeCSS query will matchdarkmode. - The
updatedevent will be emitted
Settings this property to light will have the following effects:
nativeTheme.shouldUseDarkColorswill befalsewhen 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-schemeCSS query will matchlightmode. - The
updatedevent 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-constrast 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) - TheClientRequestconstructor 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])
pathString - File path to record network logs.optionsObject (optional)captureModeString (optional) - What kinds of data should be captured. By default, only metadata about requests will be captured. Setting this toincludeSensitivewill include cookies and authentication data. Setting it toeverythingwill include all bytes transferred on sockets. Can bedefault,includeSensitiveoreverything.maxFileSizeNumber (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
newGuestBrowserWindow (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])
optionsObject (optional)titleString - A title for the notification, which will be shown at the top of the notification window when it is shown.subtitleString (optional) macOS - A subtitle for the notification, which will be displayed below the title.bodyString - The body text of the notification, which will be displayed below the title or subtitle.silentBoolean (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.hasReplyBoolean (optional) macOS - Whether or not to add an inline reply option to the notification.timeoutTypeString (optional) Linux Windows - The timeout duration of the notification. Can be 'default' or 'never'.replyPlaceholderString (optional) macOS - The placeholder to write in the inline reply input field.soundString (optional) macOS - The name of the sound file to play when the notification is shown.urgencyString (optional) Linux - The urgency level of the notification. Can be 'normal', 'critical', or 'low'.actionsNotificationAction[] (optional) macOS - Actions to add to the notification. Please read the available actions and limitations in theNotificationActiondocumentation.closeButtonTextString (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:
eventEvent
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:
eventEvent
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:
eventEventreplyString - 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:
eventEventindexNumber - 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
typeString - The type of action, can bebutton.textString (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
NSUserNotificationAlertStyleset toalertin 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.exeto 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.
Offscreen Rendering
Offscreen rendering lets you obtain the content of a browser window in a bitmap, so it can be rendered anywhere, for example on a texture in a 3D scene. The offscreen rendering in Electron uses a similar approach than the Chromium Embedded Framework project.
Two modes of rendering can be used and only the dirty area is passed in the
'paint' event to be more efficient. The rendering can be stopped, continued
and the frame rate can be set. The specified frame rate is a top limit value,
when there is nothing happening on a webpage, no frames are generated. The
maximum frame rate is 60, because above that there is no benefit, only
performance loss.
Note: 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 performance, thus this mode is quite a bit slower than the other one. 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, thus 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.
Usage
const { app, BrowserWindow } = require('electron')
app.disableHardwareAcceleration()
let win
app.whenReady().then(() => {
win = new BrowserWindow({
webPreferences: {
offscreen: true
}
})
win.loadURL('http://github.com')
win.webContents.on('paint', (event, dirty, image) => {
// updateBitmap(dirty, image.getBitmap())
})
win.webContents.setFrameRate(30)
})
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:
falseif all network requests are guaranteed to fail (e.g. when disconnected from the network).truein 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}/online-status.html`)
})
create the online-status.html file and 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}/online-status.html`)
})
ipcMain.on('online-status-changed', (event, status) => {
console.log(status)
})
create the online-status.html file and 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 intiative 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
.patchesfile 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-patchesignores 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
2) 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 without impacting the user experience.
For more information about how to use it,
check out its documentation on MDN.
Web Workers are a powerful tool to run code on a separate thread. There are some caveats to consider – consult Electron's multithreading documentation and the MDN documentation for Web Workers. They're an ideal solution for any operation that requires a lot of CPU power for an extended period of time.
5) Unnecessary polyfills
One of Electron's great benefits is that you know exactly which engine will parse your JavaScript, HTML, and CSS. If you're re-purposing code that was written for the web at large, make sure to not polyfill features included in Electron.
Why?
When building a web application for today's Internet, the oldest environments dictate what features you can and cannot use. Even though Electron supports well-performing CSS filters and animations, an older browser might not. Where you could use WebGL, your developers may have chosen a more resource-hungry solution to support older phones.
When it comes to JavaScript, you may have included toolkit libraries like
jQuery for DOM selectors or polyfills like the regenerator-runtime to support
async/await.
It is rare for a JavaScript-based polyfill to be faster than the equivalent native feature in Electron. Do not slow down your Electron app by shipping your own version of standard web platform features.
How?
Operate under the assumption that polyfills in current versions of Electron are unnecessary. If you have doubts, check caniuse.com and check if the version of Chromium used in your Electron version supports the feature you desire.
In addition, carefully examine the libraries you use. Are they really necessary?
jQuery, for example, was such a success that many of its features are now part
of the standard JavaScript feature set available.
If you're using a transpiler/compiler like TypeScript, examine its configuration and ensure that you're targeting the latest ECMAScript version supported by Electron.
6) Unnecessary or blocking network requests
Avoid fetching rarely changing resources from the internet if they could easily be bundled with your application.
Why?
Many users of Electron start with an entirely web-based app that they're turning into a desktop application. As web developers, we are used to loading resources from a variety of content delivery networks. Now that you are shipping a proper desktop application, attempt to "cut the cord" where possible and avoid letting your users wait for resources that never change and could easily be included in your app.
A typical example is Google Fonts. Many developers make use of Google's impressive collection of free fonts, which comes with a content delivery network. The pitch is straightforward: Include a few lines of CSS and Google will take care of the rest.
When building an Electron app, your users are better served if you download the fonts and include them in your app's bundle.
How?
In an ideal world, your application wouldn't need the network to operate at all. To get there, you must understand what resources your app is downloading - and how large those resources are.
To do so, open up the developer tools. Navigate to the Network tab and check
the Disable cache option. Then, reload your renderer. Unless your app
prohibits such reloads, you can usually trigger a reload by hitting Cmd + R
or Ctrl + R with the developer tools in focus.
The tools will now meticulously record all network requests. In a first pass, take stock of all the resources being downloaded, focusing on the larger files first. Are any of them images, fonts, or media files that don't change and could be included with your bundle? If so, include them.
As a next step, enable Network Throttling. Find the drop-down that currently
reads Online and select a slower speed such as Fast 3G. Reload your
renderer and see if there are any resources that your app is unnecessarily
waiting for. In many cases, an app will wait for a network request to complete
despite not actually needing the involved resource.
As a tip, loading resources from the Internet that you might want to change without shipping an application update is a powerful strategy. For advanced control over how resources are being loaded, consider investing in Service Workers.
7) Bundle your code
As already pointed out in
"Loading and running code too soon",
calling require() is an expensive operation. If you are able to do so,
bundle your application's code into a single file.
Why?
Modern JavaScript development usually involves many files and modules. While
that's perfectly fine for developing with Electron, we heavily recommend that
you bundle all your code into one single file to ensure that the overhead
included in calling require() is only paid once when your application loads.
How?
There are numerous JavaScript bundlers out there and we know better than to anger the community by recommending one tool over another. We do however recommend that you use a bundler that is able to handle Electron's unique environment that needs to handle both Node.js and browser environments.
As of writing this article, the popular choices include Webpack, Parcel, and rollup.js.
Point Object
xNumberyNumber
Note: Both x and y must be whole integers, when providing a point object
as input to an Electron API we will automatically round your x and y values
to the nearest whole integer.
PostBody Object
dataArray<PostData> - The post data to be sent to the new window.contentTypeString - Thecontent-typeheader used for the data. One ofapplication/x-www-form-urlencodedormultipart/form-data. Corresponds to theenctypeattribute of the submitted HTML form.boundaryString (optional) - The boundary used to separate multiple parts of the message. Only valid whencontentTypeismultipart/form-data.
Note that keys starting with -- are not currently supported. For example, this will errantly submit as multipart/form-data when nativeWindowOpen is set to false in webPreferences:
<form
target="_blank"
method="POST"
enctype="application/x-www-form-urlencoded"
action="https://postman-echo.com/post"
>
<input type="text" name="--theKey">
<input type="submit">
</form>
PostData Object
typeString - One of the following:rawData- The data is available as aBuffer, in therawDatafield.file- The object represents a file. ThefilePath,offset,lengthandmodificationTimefields will be used to describe the file.blob- The object represents aBlob. TheblobUUIDfield will be used to describe theBlob.
bytesString (optional) - The raw bytes of the post data in aBuffer. Required for therawDatatype.filePathString (optional) - The path of the file being uploaded. Required for thefiletype.blobUUIDString (optional) - TheUUIDof theBlobbeing uploaded. Required for theblobtype.offsetInteger (optional) - The offset from the beginning of the file being uploaded, in bytes. Only valid forfiletypes.lengthInteger (optional) - The length of the file being uploaded, in bytes. If set to-1, the whole file will be uploaded. Only valid forfiletypes.modificationTimeDouble (optional) - The modification time of the file represented by a double, which is the number of seconds since theUNIX Epoch(Jan 1, 1970). Only valid forfiletypes.
Events
The powerMonitor module emits the following events:
Event: 'suspend' macOS Windows
Emitted when the system is suspending.
Event: 'resume' macOS Windows
Emitted when system is resuming.
Event: 'on-ac' macOS Windows
Emitted when the system changes to AC power.
Event: 'on-battery' macOS Windows
Emitted when system changes to battery power.
Event: 'shutdown' Linux macOS
Emitted when the system is about to reboot or shut down. If the event handler
invokes e.preventDefault(), Electron will attempt to delay system shutdown in
order for the app to exit cleanly. If e.preventDefault() is called, the app
should exit as soon as possible by calling something like app.quit().
Event: 'lock-screen' macOS Windows
Emitted when the system is about to lock the screen.
Event: 'unlock-screen' macOS Windows
Emitted as soon as the systems screen is unlocked.
Methods
The powerMonitor module has the following methods:
powerMonitor.getSystemIdleState(idleThreshold)
idleThresholdInteger
Returns String - The system's current state. Can be active, idle, locked or unknown.
Calculate the system idle state. idleThreshold is the amount of time (in seconds)
before considered idle. locked is available on supported systems only.
powerMonitor.getSystemIdleTime()
Returns Integer - Idle time in seconds
Calculate system idle time in seconds.
powerSaveBlocker
Block the system from entering low-power (sleep) mode.
Process: Main
For example:
const { powerSaveBlocker } = require('electron')
const id = powerSaveBlocker.start('prevent-display-sleep')
console.log(powerSaveBlocker.isStarted(id))
powerSaveBlocker.stop(id)
Methods
The powerSaveBlocker module has the following methods:
powerSaveBlocker.start(type)
typeString - Power save blocker type.prevent-app-suspension- Prevent the application from being suspended. Keeps system active but allows screen to be turned off. Example use cases: downloading a file or playing audio.prevent-display-sleep- Prevent the display from going to sleep. Keeps system and screen active. Example use case: playing video.
Returns Integer - The blocker ID that is assigned to this power blocker.
Starts preventing the system from entering lower-power mode. Returns an integer identifying the power save blocker.
Note: prevent-display-sleep has higher precedence over
prevent-app-suspension. Only the highest precedence type takes effect. In
other words, prevent-display-sleep always takes precedence over
prevent-app-suspension.
For example, an API calling A requests for prevent-app-suspension, and
another calling B requests for prevent-display-sleep. prevent-display-sleep
will be used until B stops its request. After that, prevent-app-suspension
is used.
powerSaveBlocker.stop(id)
idInteger - The power save blocker id returned bypowerSaveBlocker.start.
Stops the specified power save blocker.
powerSaveBlocker.isStarted(id)
idInteger - The power save blocker id returned bypowerSaveBlocker.start.
Returns Boolean - Whether the corresponding powerSaveBlocker has started.
PrinterInfo Object
nameString - the name of the printer as understood by the OS.displayNameString - the name of the printer as shown in Print Preview.descriptionString - a longer description of the printer's type.statusNumber - the current status of the printer.isDefaultBoolean - whether or not a given printer is set as the default printer on the OS.optionsObject - an object containing a variable number of platform-specific printer information.
The number represented by status means different things on different platforms: on Windows it's potential values can be found here, and on Linux and macOS they can be found here.
Example
Below is an example of some of the additional options that may be set which may be different on each platform.
{
name: 'Austin_4th_Floor_Printer___C02XK13BJHD4',
displayName: 'Austin 4th Floor Printer @ C02XK13BJHD4',
description: 'TOSHIBA ColorMFP',
status: 3,
isDefault: false,
options: {
copies: '1',
'device-uri': 'dnssd://Austin%204th%20Floor%20Printer%20%40%20C02XK13BJHD4._ipps._tcp.local./?uuid=71687f1e-1147-3274-6674-22de61b110bd',
finishings: '3',
'job-cancel-after': '10800',
'job-hold-until': 'no-hold',
'job-priority': '50',
'job-sheets': 'none,none',
'marker-change-time': '0',
'number-up': '1',
'printer-commands': 'ReportLevels,PrintSelfTestPage,com.toshiba.ColourProfiles.update,com.toshiba.EFiling.update,com.toshiba.EFiling.checkPassword',
'printer-info': 'Austin 4th Floor Printer @ C02XK13BJHD4',
'printer-is-accepting-jobs': 'true',
'printer-is-shared': 'false',
'printer-is-temporary': 'false',
'printer-location': '',
'printer-make-and-model': 'TOSHIBA ColorMFP',
'printer-state': '3',
'printer-state-change-time': '1573472937',
'printer-state-reasons': 'offline-report,com.toshiba.snmp.failed',
'printer-type': '10531038',
'printer-uri-supported': 'ipp://localhost/printers/Austin_4th_Floor_Printer___C02XK13BJHD4',
system_driverinfo: 'T'
}
}
process
Extensions to process object.
Electron's process object is extended from the
Node.js process object.
It adds the following events, properties, and methods:
Sandbox
In sandboxed renderers the process object contains only a subset of the APIs:
crash()hang()getCreationTime()getHeapStatistics()getBlinkMemoryInfo()getProcessMemoryInfo()getSystemMemoryInfo()getSystemVersion()getCPUUsage()getIOCounters()argvexecPathenvpidarchplatformsandboxedtypeversionversionsmaswindowsStore
Event: 'loaded'
Emitted when Electron has loaded its internal initialization script and is beginning to load the web page or the main script.
It can be used by the preload script to add removed Node global symbols back to the global scope when node integration is turned off:
// preload.js
const _setImmediate = setImmediate
const _clearImmediate = clearImmediate
process.once('loaded', () => {
global.setImmediate = _setImmediate
global.clearImmediate = _clearImmediate
})
process.defaultApp Readonly
A Boolean. When app is started by being passed as parameter to the default app, this
property is true in the main process, otherwise it is undefined.
process.isMainFrame Readonly
A Boolean, true when the current renderer context is the "main" renderer
frame. If you want the ID of the current frame you should use webFrame.routingId.
process.mas Readonly
A Boolean. For Mac App Store build, this property is true, for other builds it is
undefined.
process.noAsar
A Boolean that controls ASAR support inside your application. Setting this to true
will disable the support for asar archives in Node's built-in modules.
process.noDeprecation
A Boolean that controls whether or not deprecation warnings are printed to stderr.
Setting this to true will silence deprecation warnings. This property is used
instead of the --no-deprecation command line flag.
process.resourcesPath Readonly
A String representing the path to the resources directory.
process.sandboxed Readonly
A Boolean. When the renderer process is sandboxed, this property is true,
otherwise it is undefined.
process.throwDeprecation
A Boolean that controls whether or not deprecation warnings will be thrown as
exceptions. Setting this to true will throw errors for deprecations. This
property is used instead of the --throw-deprecation command line flag.
process.traceDeprecation
A Boolean that controls whether or not deprecations printed to stderr include
their stack trace. Setting this to true will print stack traces for deprecations.
This property is instead of the --trace-deprecation command line flag.
process.traceProcessWarnings
A Boolean that controls whether or not process warnings printed to stderr include
their stack trace. Setting this to true will print stack traces for process warnings
(including deprecations). This property is instead of the --trace-warnings command
line flag.
process.type Readonly
A String representing the current process's type, can be:
browser- The main processrenderer- A renderer processworker- In a web worker
process.versions.chrome Readonly
A String representing Chrome's version string.
process.versions.electron Readonly
A String representing Electron's version string.
process.windowsStore Readonly
A Boolean. If the app is running as a Windows Store app (appx), this property is true,
for otherwise it is undefined.
Methods
The process object has the following methods:
process.crash()
Causes the main thread of the current process crash.
process.getCreationTime()
Returns Number | null - The number of milliseconds since epoch, or null if the information is unavailable
Indicates the creation time of the application. The time is represented as number of milliseconds since epoch. It returns null if it is unable to get the process creation time.
process.getCPUUsage()
Returns CPUUsage
process.getHeapStatistics()
Returns Object:
totalHeapSizeIntegertotalHeapSizeExecutableIntegertotalPhysicalSizeIntegertotalAvailableSizeIntegerusedHeapSizeIntegerheapSizeLimitIntegermallocedMemoryIntegerpeakMallocedMemoryIntegerdoesZapGarbageBoolean
Returns an object with V8 heap statistics. Note that all statistics are reported in Kilobytes.
process.getBlinkMemoryInfo()
Returns Object:
allocatedInteger - Size of all allocated objects in Kilobytes.markedInteger - Size of all marked objects in Kilobytes.totalInteger - Total allocated space in Kilobytes.
Returns an object with Blink memory information. It can be useful for debugging rendering / DOM related memory issues. Note that all values are reported in Kilobytes.
process.getProcessMemoryInfo()
Returns Promise<ProcessMemoryInfo> - Resolves with a ProcessMemoryInfo
Returns an object giving memory usage statistics about the current process. Note that all statistics are reported in Kilobytes. This api should be called after app ready.
Chromium does not provide residentSet value for macOS. This is because macOS
performs in-memory compression of pages that haven't been recently used. As a
result the resident set size value is not what one would expect. private memory
is more representative of the actual pre-compression memory usage of the process
on macOS.
process.getSystemMemoryInfo()
Returns Object:
totalInteger - The total amount of physical memory in Kilobytes available to the system.freeInteger - The total amount of memory not being used by applications or disk cache.swapTotalInteger Windows Linux - The total amount of swap memory in Kilobytes available to the system.swapFreeInteger Windows Linux - The free amount of swap memory in Kilobytes available to the system.
Returns an object giving memory usage statistics about the entire system. Note that all statistics are reported in Kilobytes.
process.getSystemVersion()
Returns String - The version of the host operating system.
Example:
const version = process.getSystemVersion()
console.log(version)
// On macOS -> '10.13.6'
// On Windows -> '10.0.17763'
// On Linux -> '4.15.0-45-generic'
Note: It returns the actual operating system version instead of kernel version on macOS unlike os.release().
process.takeHeapSnapshot(filePath)
filePathString - Path to the output file.
Returns Boolean - Indicates whether the snapshot has been created successfully.
Takes a V8 heap snapshot and saves it to filePath.
process.hang()
Causes the main thread of the current process hang.
process.setFdLimit(maxDescriptors) macOS Linux
maxDescriptorsInteger
Sets the file descriptor soft limit to maxDescriptors or the OS hard
limit, whichever is lower for the current process.
ProcessMemoryInfo Object
residentSetInteger Linux Windows - The amount of memory currently pinned to actual physical RAM in Kilobytes.privateInteger - The amount of memory not shared by other processes, such as JS heap or HTML content in Kilobytes.sharedInteger - The amount of memory shared between processes, typically memory consumed by the Electron code itself in Kilobytes.
ProcessMetric Object
pidInteger - Process id of the process.typeString - Process type. One of the following values:BrowserTabUtilityZygoteSandbox helperGPUPepper PluginPepper Plugin BrokerUnknown
cpuCPUUsage - CPU usage of the process.creationTimeNumber - Creation time for this process. The time is represented as number of milliseconds since epoch. Since thepidcan be reused after a process dies, it is useful to use both thepidand thecreationTimeto uniquely identify a process.memoryMemoryInfo - Memory information for the process.sandboxedBoolean (optional) macOS Windows - Whether the process is sandboxed on OS level.integrityLevelString (optional) Windows - One of the following values:untrustedlowmediumhighunknown
Product Object
productIdentifierString - The string that identifies the product to the Apple App Store.localizedDescriptionString - A description of the product.localizedTitleString - The name of the product.contentVersionString - A string that identifies the version of the content.contentLengthsNumber[] - The total size of the content, in bytes.priceNumber - The cost of the product in the local currency.formattedPriceString - The locale formatted price of the product.currencyCodeString - 3 character code presenting a product's currency based on the ISO 4217 standard.isDownloadableBoolean - A Boolean value that indicates whether the App Store has downloadable content for this product.trueif at least one file has been associated with the product.
Progress Bar in Taskbar (Windows, macOS, Unity)
On Windows a taskbar button can be used to display a progress bar. This enables a window to provide progress information to the user without the user having to switch to the window itself.
On macOS the progress bar will be displayed as a part of the dock icon.
The Unity DE also has a similar feature that allows you to specify the progress bar in the launcher.
Progress bar in taskbar button:

All three cases are covered by the same API - the setProgressBar() method
available on instances of BrowserWindows. Call it with a number between 0
and 1 to indicate your progress. If you have a long-running task that's
currently at 63% towards completion, you'd call it with setProgressBar(0.63).
Generally speaking, setting the parameter to a value below zero (like -1)
will remove the progress bar while setting it to a value higher than one
(like 2) will switch the progress bar to intermediate mode.
See the API documentation for more options and modes.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.setProgressBar(0.5)
Promisification
The Electron team recently underwent an initiative to convert callback-based APIs to Promise-based ones. See converted functions below:
- app.getFileIcon(path[, options], callback)
- contents.capturePage([rect, ]callback)
- contents.executeJavaScript(code[, userGesture, callback])
- contents.printToPDF(options, callback)
- contents.savePage(fullPath, saveType, callback)
- contentTracing.getCategories(callback)
- contentTracing.startRecording(options, callback)
- contentTracing.stopRecording(resultFilePath, callback)
- contentTracing.getTraceBufferUsage(callback)
- cookies.flushStore(callback)
- cookies.get(filter, callback)
- cookies.remove(url, name, callback)
- cookies.set(details, callback)
- debugger.sendCommand(method[, commandParams, callback])
- desktopCapturer.getSources(options, callback)
- dialog.showOpenDialog([browserWindow, ]options[, callback])
- dialog.showSaveDialog([browserWindow, ]options[, callback])
- inAppPurchase.purchaseProduct(productID, quantity, callback)
- inAppPurchase.getProducts(productIDs, callback)
- dialog.showMessageBox([browserWindow, ]options[, callback])
- dialog.showCertificateTrustDialog([browserWindow, ]options, callback)
- netLog.stopLogging([callback])
- protocol.isProtocolHandled(scheme, callback)
- ses.clearHostResolverCache([callback])
- ses.clearStorageData([options, callback])
- ses.setProxy(config, callback)
- ses.resolveProxy(url, callback)
- ses.getCacheSize(callback)
- ses.clearAuthCache(options[, callback])
- ses.clearCache(callback)
- ses.getBlobData(identifier, callback)
- shell.openExternal(url[, options, callback])
- webFrame.executeJavaScript(code[, userGesture, callback])
- webFrame.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture, callback])
- webviewTag.capturePage([rect, ]callback)
- webviewTag.executeJavaScript(code[, userGesture, callback])
- webviewTag.printToPDF(options, callback)
- win.capturePage([rect, ]callback)
Property Updates
The Electron team is currently undergoing an initiative to convert separate getter and setter functions in Electron to bespoke properties with get and set functionality. During this transition period, both the new properties and old getters and setters of these functions will work correctly and be documented.
Candidates
BrowserWindowmenubarVisible
crashReportermoduleuploadToServer
webFramemoduleszoomFactorzoomLevelaudioMuted
<webview>zoomFactorzoomLevelaudioMuted
Converted Properties
appmoduleaccessibilitySupportapplicationMenubadgeCountname
DownloadItemclasssavePath
BrowserWindowmoduleautohideMenuBarresizablemaximizableminimizablefullscreenablemovableclosablebackgroundThrottling
NativeImageisMacTemplateImage
SystemPreferencesmoduleappLevelAppearance
protocol
Register a custom protocol and intercept existing protocol requests.
Process: Main
An example of implementing a protocol that has the same effect as the
file:// protocol:
const { app, protocol } = require('electron')
const path = require('path')
app.whenReady().then(() => {
protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
})
})
Note: All methods unless specified can only be used after the ready event
of the app module gets emitted.
Using protocol with a custom partition or session
A protocol is registered to a specific Electron session
object. If you don't specify a session, then your protocol will be applied to
the default session that Electron uses. However, if you define a partition or
session on your browserWindow's webPreferences, then that window will use
a different session and your custom protocol will not work if you just use
electron.protocol.XXX.
To have your custom protocol work in combination with a custom session, you need to register it to that session explicitly.
const { session, app, protocol } = require('electron')
const path = require('path')
app.whenReady().then(() => {
const partition = 'persist:example'
const ses = session.fromPartition(partition)
ses.protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
})
mainWindow = new BrowserWindow({ webPreferences: { partition } })
})
Methods
The protocol module has the following methods:
protocol.registerSchemesAsPrivileged(customSchemes)
customSchemesCustomScheme[]
Note: This method can only be used before the ready event of the app
module gets emitted and can be called only once.
Registers the scheme as standard, secure, bypasses content security policy for
resources, allows registering ServiceWorker and supports fetch API. Specify a
privilege with the value of true to enable the capability.
An example of registering a privileged scheme, that bypasses Content Security Policy:
const { protocol } = require('electron')
protocol.registerSchemesAsPrivileged([
{ scheme: 'foo', privileges: { bypassCSP: true } }
])
A standard scheme adheres to what RFC 3986 calls generic URI
syntax. For example http and
https are standard schemes, while file is not.
Registering a scheme as standard allows relative and absolute resources to
be resolved correctly when served. Otherwise the scheme will behave like the
file protocol, but without the ability to resolve relative URLs.
For example when you load following page with custom protocol without registering it as standard scheme, the image will not be loaded because non-standard schemes can not recognize relative URLs:
<body>
<img src='test.png'>
</body>
Registering a scheme as standard will allow access to files through the FileSystem API. Otherwise the renderer will throw a security error for the scheme.
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB,
cookies) are disabled for non standard schemes. So in general if you want to
register a custom protocol to replace the http protocol, you have to register
it as a standard scheme.
protocol.registerFileProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponse(String | ProtocolResponse)
Returns Boolean - Whether the protocol was successfully registered
Registers a protocol of scheme that will send a file as the response. The
handler will be called with request and callback where request is
an incoming request for the scheme.
To handle the request, the callback should be called with either the file's
path or an object that has a path property, e.g. callback(filePath) or
callback({ path: filePath }). The filePath must be an absolute path.
By default the scheme is treated like http:, which is parsed differently
from protocols that follow the "generic URI syntax" like file:.
protocol.registerBufferProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponse(Buffer | ProtocolResponse)
Returns Boolean - Whether the protocol was successfully registered
Registers a protocol of scheme that will send a Buffer as a response.
The usage is the same with registerFileProtocol, except that the callback
should be called with either a Buffer object or an object that has the data
property.
Example:
protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
})
protocol.registerStringProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponse(String | ProtocolResponse)
Returns Boolean - Whether the protocol was successfully registered
Registers a protocol of scheme that will send a String as a response.
The usage is the same with registerFileProtocol, except that the callback
should be called with either a String or an object that has the data
property.
protocol.registerHttpProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponseProtocolResponse
Returns Boolean - Whether the protocol was successfully registered
Registers a protocol of scheme that will send an HTTP request as a response.
The usage is the same with registerFileProtocol, except that the callback
should be called with an object that has the url property.
protocol.registerStreamProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponse(ReadableStream | ProtocolResponse)
Returns Boolean - Whether the protocol was successfully registered
Registers a protocol of scheme that will send a stream as a response.
The usage is the same with registerFileProtocol, except that the
callback should be called with either a ReadableStream object or an object that
has the data property.
Example:
const { protocol } = require('electron')
const { PassThrough } = require('stream')
function createStream (text) {
const rv = new PassThrough() // PassThrough is also a Readable stream
rv.push(text)
rv.push(null)
return rv
}
protocol.registerStreamProtocol('atom', (request, callback) => {
callback({
statusCode: 200,
headers: {
'content-type': 'text/html'
},
data: createStream('<h5>Response</h5>')
})
})
It is possible to pass any object that implements the readable stream API (emits
data/end/error events). For example, here's how a file could be returned:
protocol.registerStreamProtocol('atom', (request, callback) => {
callback(fs.createReadStream('index.html'))
})
protocol.unregisterProtocol(scheme)
schemeString
Returns Boolean - Whether the protocol was successfully unregistered
Unregisters the custom protocol of scheme.
protocol.isProtocolRegistered(scheme)
schemeString
Returns Boolean - Whether scheme is already registered.
protocol.interceptFileProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponse(String | ProtocolResponse)
Returns Boolean - Whether the protocol was successfully intercepted
Intercepts scheme protocol and uses handler as the protocol's new handler
which sends a file as a response.
protocol.interceptStringProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponse(String | ProtocolResponse)
Returns Boolean - Whether the protocol was successfully intercepted
Intercepts scheme protocol and uses handler as the protocol's new handler
which sends a String as a response.
protocol.interceptBufferProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponse(Buffer | ProtocolResponse)
Returns Boolean - Whether the protocol was successfully intercepted
Intercepts scheme protocol and uses handler as the protocol's new handler
which sends a Buffer as a response.
protocol.interceptHttpProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponseProtocolResponse
Returns Boolean - Whether the protocol was successfully intercepted
Intercepts scheme protocol and uses handler as the protocol's new handler
which sends a new HTTP request as a response.
protocol.interceptStreamProtocol(scheme, handler)
schemeStringhandlerFunctionrequestProtocolRequestcallbackFunctionresponse(ReadableStream | ProtocolResponse)
Returns Boolean - Whether the protocol was successfully intercepted
Same as protocol.registerStreamProtocol, except that it replaces an existing
protocol handler.
protocol.uninterceptProtocol(scheme)
schemeString
Returns Boolean - Whether the protocol was successfully unintercepted
Remove the interceptor installed for scheme and restore its original handler.
protocol.isProtocolIntercepted(scheme)
schemeString
Returns Boolean - Whether scheme is already intercepted.
ProtocolRequest Object
urlStringreferrerStringmethodStringuploadDataUploadData[] (optional)headersRecord<String, String>
ProtocolResponse Object
errorInteger (optional) - When assigned, therequestwill fail with theerrornumber . For the available error numbers you can use, please see the net error list.statusCodeNumber (optional) - The HTTP response code, default is 200.charsetString (optional) - The charset of response body, default is"utf-8".mimeTypeString (optional) - The MIME type of response body, default is"text/html". SettingmimeTypewould implicitly set thecontent-typeheader in response, but ifcontent-typeis already set inheaders, themimeTypewould be ignored.headersRecord<string, string | string[]> (optional) - An object containing the response headers. The keys must be String, and values must be either String or Array of String.data(Buffer | String | ReadableStream) (optional) - The response body. When returning stream as response, this is a Node.js readable stream representing the response body. When returningBufferas response, this is aBuffer. When returningStringas response, this is aString. This is ignored for other types of responses.pathString (optional) - Path to the file which would be sent as response body. This is only used for file responses.urlString (optional) - Download theurland pipe the result as response body. This is only used for URL responses.referrerString (optional) - ThereferrerURL. This is only used for file and URL responses.methodString (optional) - The HTTPmethod. This is only used for file and URL responses.sessionSession (optional) - The session used for requesting URL, by default the HTTP request will reuse the current session. Settingsessiontonullwould use a random independent session. This is only used for URL responses.uploadDataProtocolResponseUploadData (optional) - The data used as upload data. This is only used for URL responses whenmethodis"POST".
ProtocolResponseUploadData Object
contentTypeString - MIME type of the content.dataString | Buffer - Content to be sent.
Step 1: Fork
Fork the project on GitHub and clone your fork locally.
$ git clone git@github.com:username/electron.git
$ cd electron
$ git remote add upstream https://github.com/electron/electron.git
$ git fetch upstream
Step 2: Build
Build steps and dependencies differ slightly depending on your operating system. See these detailed guides on building Electron locally:
Once you've built the project locally, you're ready to start making changes!
Step 3: Branch
To keep your development environment organized, create local branches to
hold your work. These should be branched directly off of the master branch.
$ git checkout -b my-branch -t upstream/master
Step 4: Code
Most pull requests opened against the electron/electron repository include
changes to either the C/C++ code in the shell/ folder,
the JavaScript code in the lib/ folder, the documentation in docs/api/
or tests in the spec/ folder.
Please be sure to run npm run lint from time to time on any code changes
to ensure that they follow the project's code style.
See coding style for more information about best practice when modifying code in different parts of the project.
Step 5: Commit
It is recommended to keep your changes grouped logically within individual commits. Many contributors find it easier to review changes that are split across multiple commits. There is no limit to the number of commits in a pull request.
$ git add my/changed/files
$ git commit
Note that multiple commits often get squashed when they are landed.
Commit message guidelines
A good commit message should describe what changed and why. The Electron project uses semantic commit messages to streamline the release process.
Before a pull request can be merged, it must have a pull request title with a semantic prefix.
Examples of commit messages with semantic prefixes:
fix: don't overwrite prevent_default if default wasn't preventedfeat: add app.isPackaged() methoddocs: app.isDefaultProtocolClient is now available on Linux
Common prefixes:
- fix: A bug fix
- feat: A new feature
- docs: Documentation changes
- test: Adding missing tests or correcting existing tests
- build: Changes that affect the build system
- ci: Changes to our CI configuration files and scripts
- perf: A code change that improves performance
- refactor: A code change that neither fixes a bug nor adds a feature
- style: Changes that do not affect the meaning of the code (linting)
- vendor: Bumping a dependency like libchromiumcontent or node
Other things to keep in mind when writing a commit message:
- The first line should:
- contain a short description of the change (preferably 50 characters or less, and no more than 72 characters)
- be entirely in lowercase with the exception of proper nouns, acronyms, and the words that refer to code, like function/variable names
- Keep the second line blank.
- Wrap all other lines at 72 columns.
Breaking Changes
A commit that has the text BREAKING CHANGE: at the beginning of its optional
body or footer section introduces a breaking API change (correlating with Major
in semantic versioning). A breaking change can be part of commits of any type.
e.g., a fix:, feat: & chore: types would all be valid, in addition to any
other type.
See conventionalcommits.org for more details.
Step 6: Rebase
Once you have committed your changes, it is a good idea to use git rebase
(not git merge) to synchronize your work with the main repository.
$ git fetch upstream
$ git rebase upstream/master
This ensures that your working branch has the latest changes from electron/electron
master.
Step 7: Test
Bug fixes and features should always come with tests. A testing guide has been provided to make the process easier. Looking at other tests to see how they should be structured can also help.
Before submitting your changes in a pull request, always run the full test suite. To run the tests:
$ npm run test
Make sure the linter does not report any issues and that all tests pass. Please do not submit patches that fail either check.
If you are updating tests and want to run a single spec to check it:
$ npm run test -match=menu
The above would only run spec modules matching menu, which is useful for
anyone who's working on tests that would otherwise be at the very end of
the testing cycle.
Step 8: Push
Once your commits are ready to go -- with passing tests and linting -- begin the process of opening a pull request by pushing your working branch to your fork on GitHub.
$ git push origin my-branch
Step 9: Opening the Pull Request
From within GitHub, opening a new pull request will present you with a template that should be filled out:
<!--
Thank you for your pull request. Please provide a description above and review
the requirements below.
Bug fixes and new features should include tests and possibly benchmarks.
Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTING.md
-->
Step 10: Discuss and update
You will probably get feedback or requests for changes to your pull request. This is a big part of the submission process so don't be discouraged! Some contributors may sign off on the pull request right away. Others may have detailed comments or feedback. This is a necessary part of the process in order to evaluate whether the changes are correct and necessary.
To make changes to an existing pull request, make the changes to your local branch, add a new commit with those changes, and push those to your fork. GitHub will automatically update the pull request.
$ git add my/changed/files
$ git commit
$ git push origin my-branch
There are a number of more advanced mechanisms for managing commits using
git rebase that can be used, but are beyond the scope of this guide.
Feel free to post a comment in the pull request to ping reviewers if you are awaiting an answer on something. If you encounter words or acronyms that seem unfamiliar, refer to this glossary.
Approval and Request Changes Workflow
All pull requests require approval from a Code Owner of the area you modified in order to land. Whenever a maintainer reviews a pull request they may request changes. These may be small, such as fixing a typo, or may involve substantive changes. Such requests are intended to be helpful, but at times may come across as abrupt or unhelpful, especially if they do not include concrete suggestions on how to change them.
Try not to be discouraged. If you feel that a review is unfair, say so or seek the input of another project contributor. Often such comments are the result of a reviewer having taken insufficient time to review and are not ill-intended. Such difficulties can often be resolved with a bit of patience. That said, reviewers should be expected to provide helpful feedback.
Step 11: Landing
In order to land, a pull request needs to be reviewed and approved by at least one Electron Code Owner and pass CI. After that, if there are no objections from other contributors, the pull request can be merged.
Congratulations and thanks for your contribution!
Continuous Integration Testing
Every pull request is tested on the Continuous Integration (CI) system to confirm that it works on Electron's supported platforms.
Ideally, the pull request will pass ("be green") on all of CI's platforms. This means that all tests pass and there are no linting errors. However, it is not uncommon for the CI infrastructure itself to fail on specific platforms or for so-called "flaky" tests to fail ("be red"). Each CI failure must be manually inspected to determine the cause.
CI starts automatically when you open a pull request, but only core maintainers can restart a CI run. If you believe CI is giving a false negative, ask a maintainer to restart the tests.
Quickstart
Electron is a framework that enables you to create desktop applications with JavaScript, HTML, and CSS. These applications can then be packaged to run directly on macOS, Windows, or Linux, or distributed via the Mac App Store or the Microsoft Store.
Typically, you create a desktop application for an operating system (OS) using each operating system's specific native application frameworks. Electron makes it possible to write your application once using technologies that you already know.
Prerequisites
Before proceeding with Electron you need to install Node.js.
We recommend that you install either the latest LTS or Current version available.
Please install Node.js using pre-built installers for your platform. You may encounter incompatibility issues with different development tools otherwise.
To check that Node.js was installed correctly, type the following commands in your terminal client:
node -v
npm -v
The commands should print the versions of Node.js and npm accordingly. If both commands succeeded, you are ready to install Electron.
Create a basic application
From a development perspective, an Electron application is essentially a Node.js application. This means that the starting point of your Electron application will be a package.json file like in any other Node.js application. A minimal Electron application has the following structure:
my-electron-app/
├── package.json
├── main.js
└── index.html
Let's create a basic application based on the structure above.
Install Electron
Create a folder for your project and install Electron there:
mkdir my-electron-app && cd my-electron-app
npm init -y
npm i --save-dev electron
Create the main script file
The main script specifies the entry point of your Electron application (in our case, the main.js file) that will run the Main process. Typically, the script that runs in the Main process controls the lifecycle of the application, displays the graphical user interface and its elements, performs native operating system interactions, and creates Renderer processes within web pages. An Electron application can have only one Main process.
The main script may look as follows:
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
win.webContents.openDevTools()
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
What is going on above?
- Line 1: First, you import the
appandBrowserWindowmodules of theelectronpackage to be able to manage your application's lifecycle events, as well as create and control browser windows. - Line 3: After that, you define a function that creates a new browser window with node integration enabled, loads
index.htmlfile into this window (line 12, we will discuss the file later) and opens Developer Tools (line 13). - Line 16: You create a new browser window by invoking the
createWindowfunction once the Electron application is initialized. - Line 18: You add a new listener that tries to quit the application when it no longer has any open windows. This listener is a no-op on macOS due to the operating system's window management behavior.
- Line 24: You add a new listener that creates a new browser window only if when the application has no visible windows after being activated. For example, after launching the application for the first time, or re-launching the already running application.
Create a web page
This is the web page you want to display once the application is initialized. This web page represents the Renderer process. You can create multiple browser windows, where each window uses its own independent Renderer. Each window can optionally be granted with full access to Node.js API through the nodeIntegration preference.
The index.html page looks as follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>
Modify your package.json file
Your Electron application uses the package.json file as the main entry point (as any other Node.js application). The main script of your application is main.js, so modify the package.json file accordingly:
{
"name": "my-electron-app",
"version": "0.1.0",
"main": "main.js"
}
NOTE: If the
mainfield is omitted, Electron will attempt to load anindex.jsfile from the directory containingpackage.json.
By default, the npm start command will run the main script with Node.js. To run the script with Electron, you need to change it as such:
{
"name": "my-electron-app",
"version": "0.1.0",
"main": "main.js",
"scripts": {
"start": "electron ."
}
}
Package and distribute the application
The simplest and the fastest way to distribute your newly created app is using Electron Forge.
-
Import Electron Forge to your app folder:
npx @electron-forge/cli import ✔ Checking your system ✔ Initializing Git Repository ✔ Writing modified package.json file ✔ Installing dependencies ✔ Writing modified package.json file ✔ Fixing .gitignore We have ATTEMPTED to convert your app to be in a format that electron-forge understands. Thanks for using "electron-forge"!!! -
Create a distributable:
npm run make > my-gsod-electron-app@1.0.0 make /my-electron-app > electron-forge make ✔ Checking your system ✔ Resolving Forge Config We need to package your application before we can make it ✔ Preparing to Package Application for arch: x64 ✔ Preparing native dependencies ✔ Packaging Application Making for the following targets: zip ✔ Making for target: zip - On platform: darwin - For arch: x64Electron-forge creates the
outfolder where your package will be located:// Example for MacOS out/ ├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip ├── ... └── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
Learning the basics
This section guides you through the basics of how Electron works under the hood. It aims at strengthening knowledge about Electron and the application created earlier in the Quickstart section.
Application architecture
Electron consists of three main pillars:
- Chromium for displaying web content.
- Node.js for working with the local filesystem and the operating system.
- Custom APIs for working with often-needed OS native functions.
Developing an application with Electron is like building a Node.js app with a web interface or building web pages with seamless Node.js integration.
Main and Renderer Processes
As it was mentioned before, Electron has two types of processes: Main and Renderer.
- The Main process creates web pages by creating
BrowserWindowinstances. EachBrowserWindowinstance runs the web page in its Renderer process. When aBrowserWindowinstance is destroyed, the corresponding Renderer process gets terminated as well. - The Main process manages all web pages and their corresponding Renderer processes.
- The Renderer process manages only the corresponding web page. A crash in one Renderer process does not affect other Renderer processes.
- The Renderer process communicates with the Main process via IPC to perform GUI operations in a web page. Calling native GUI-related APIs from the Renderer process directly is restricted due to security concerns and potential resource leakage.
The communication between processes is possible via Inter-Process Communication (IPC) modules: ipcMain and ipcRenderer.
Electron API
Electron APIs are assigned based on the process type, meaning that some modules can be used from either the Main or Renderer process, and some from both. Electron's API documentation indicates which process each module can be used from.
For example, to access the Electron API in both processes, require its included module:
const electron = require('electron')
To create a window, call the BrowserWindow class, which is only available in the Main process:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
To call the Main process from the Renderer, use the IPC module:
// In the Main process
const { ipcMain } = require('electron')
ipcMain.handle('perform-action', (event, ...args) => {
// ... do actions on behalf of the Renderer
})
// In the Renderer process
const { ipcRenderer } = require('electron')
ipcRenderer.invoke('perform-action', ...args)
NOTE: Because Renderer processes may run untrusted code (especially from third parties), it is important to carefully validate the requests that come to the Main process.
Node.js API
NOTE: To access the Node.js API from the Renderer process, you need to set the
nodeIntegrationpreference totrue.
Electron exposes full access to Node.js API and its modules both in the Main and the Renderer processes. For example, you can read all the files from the root directory:
const fs = require('fs')
const root = fs.readdirSync('/')
console.log(root)
To use a Node.js module, you first need to install it as a dependency:
npm install --save aws-sdk
Then, in your Electron application, require the module:
const S3 = require('aws-sdk/clients/s3')
Official Guides
Please make sure that you use the documents that match your Electron version. The version number should be a part of the page URL. If it's not, you are probably using the documentation of a development branch which may contain API changes that are not compatible with your Electron version. To view older versions of the documentation, you can browse by tag on GitHub by opening the "Switch branches/tags" dropdown and selecting the tag that matches your version.
FAQ
There are questions that are asked quite often. Check this out before creating an issue:
Guides and Tutorials
- Setting up the Development Environment
- Creating your First App
- Boilerplates and CLIs
- Application Architecture
- Adding Features to Your App
- Notifications
- Recent Documents
- Application Progress
- Custom Dock Menu
- Custom Windows Taskbar
- Custom Linux Desktop Actions
- Keyboard Shortcuts
- Offline/Online Detection
- Represented File for macOS BrowserWindows
- Native File Drag & Drop
- Offscreen Rendering
- Supporting macOS Dark Mode
- Web embeds in Electron
- Accessibility
- Testing and Debugging
- Distribution
- Security
- Updates
- Getting Support
Detailed Tutorials
These individual tutorials expand on topics discussed in the guide above.
- Installing Electron
- Electron Releases & Developer Feedback
- Packaging App Source Code with asar
- Testing Widevine CDM
Developing Electron
These guides are intended for people working on the Electron project itself. For guides on Electron app development, see /docs/README.md.
- Code of Conduct
- Contributing to Electron
- Issues
- Pull Requests
- Documentation Styleguide
- Source Code Directory Structure
- Coding Style
- Using clang-format on C++ Code
- Build System Overview
- Build Instructions (macOS)
- Build Instructions (Windows)
- Build Instructions (Linux)
- Chromium Development
- V8 Development
- Testing
- Debugging on Windows
- Debugging on macOS
- Setting Up Symbol Server in Debugger
- Patches
Overview
Windows and macOS provide access to a list of recent documents opened by the application via JumpList or dock menu, respectively.
JumpList:

Application dock menu:

To add a file to recent documents, you need to use the app.addRecentDocument API.
Add an item to recent documents
Starting with a working application from the
Quick Start Guide, add the following lines to the
main.js file:
const { app } = require('electron')
app.addRecentDocument('/Users/USERNAME/Desktop/work.type')
After launching the Electron application, right click the application icon. You should see the item you just added. In this guide, the item is a Markdown file located in the root of the project:

Clear the list of recent documents
To clear the list of recent documents, you need to use
app.clearRecentDocuments API in the main.js file:
const { app } = require('electron')
app.clearRecentDocuments()
Windows Notes
To use this feature on Windows, your application has to be registered as a handler of the file type of the document, otherwise the file won't appear in JumpList even after you have added it. You can find everything on registering your application in Application Registration.
When a user clicks a file from the JumpList, a new instance of your application will be started with the path of the file added as a command line argument.
Add the Recent Documents list to the application menu
You can add menu items to access and clear recent documents by adding the following code snippet to your menu template:
{
"submenu":[
{
"label":"Open Recent",
"role":"recentdocuments",
"submenu":[
{
"label":"Clear Recent",
"role":"clearrecentdocuments"
}
]
}
]
}

When a file is requested from the recent documents menu, the open-file event
of app module will be emitted for it.
Rectangle Object
xNumber - The x coordinate of the origin of the rectangle (must be an integer).yNumber - The y coordinate of the origin of the rectangle (must be an integer).widthNumber - The width of the rectangle (must be an integer).heightNumber - The height of the rectangle (must be an integer).
Referrer Object
urlString - HTTP Referrer URL.policyString - Can bedefault,unsafe-url,no-referrer-when-downgrade,no-referrer,origin,strict-origin-when-cross-origin,same-originorstrict-origin. See the Referrer-Policy spec for more details on the meaning of these values.
remote
Use main process modules from the renderer process.
Process: Renderer
The remote module provides a simple way to do inter-process communication
(IPC) between the renderer process (web page) and the main process.
In Electron, GUI-related modules (such as dialog, menu etc.) are only
available in the main process, not in the renderer process. In order to use them
from the renderer process, the ipc module is necessary to send inter-process
messages to the main process. With the remote module, you can invoke methods
of the main process object without explicitly sending inter-process messages,
similar to Java's RMI. An example of creating a browser window from a
renderer process:
const { BrowserWindow } = require('electron').remote
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')
Note: For the reverse (access the renderer process from the main process), you can use webContents.executeJavaScript.
Note: The remote module can be disabled for security reasons in the following contexts:
BrowserWindow- by setting theenableRemoteModuleoption tofalse.<webview>- by setting theenableremotemoduleattribute tofalse.
Remote Objects
Each object (including functions) returned by the remote module represents an
object in the main process (we call it a remote object or remote function).
When you invoke methods of a remote object, call a remote function, or create
a new object with the remote constructor (function), you are actually sending
synchronous inter-process messages.
In the example above, both BrowserWindow and win were remote objects and
new BrowserWindow didn't create a BrowserWindow object in the renderer
process. Instead, it created a BrowserWindow object in the main process and
returned the corresponding remote object in the renderer process, namely the
win object.
Note: Only enumerable properties which are present when the remote object is first referenced are accessible via remote.
Note: Arrays and Buffers are copied over IPC when accessed via the remote
module. Modifying them in the renderer process does not modify them in the main
process and vice versa.
Lifetime of Remote Objects
Electron makes sure that as long as the remote object in the renderer process lives (in other words, has not been garbage collected), the corresponding object in the main process will not be released. When the remote object has been garbage collected, the corresponding object in the main process will be dereferenced.
If the remote object is leaked in the renderer process (e.g. stored in a map but never freed), the corresponding object in the main process will also be leaked, so you should be very careful not to leak remote objects.
Primary value types like strings and numbers, however, are sent by copy.
Passing callbacks to the main process
Code in the main process can accept callbacks from the renderer - for instance
the remote module - but you should be extremely careful when using this
feature.
First, in order to avoid deadlocks, the callbacks passed to the main process are called asynchronously. You should not expect the main process to get the return value of the passed callbacks.
For instance you can't use a function from the renderer process in an
Array.map called in the main process:
// main process mapNumbers.js
exports.withRendererCallback = (mapper) => {
return [1, 2, 3].map(mapper)
}
exports.withLocalCallback = () => {
return [1, 2, 3].map(x => x + 1)
}
// renderer process
const mapNumbers = require('electron').remote.require('./mapNumbers')
const withRendererCb = mapNumbers.withRendererCallback(x => x + 1)
const withLocalCb = mapNumbers.withLocalCallback()
console.log(withRendererCb, withLocalCb)
// [undefined, undefined, undefined], [2, 3, 4]
As you can see, the renderer callback's synchronous return value was not as expected, and didn't match the return value of an identical callback that lives in the main process.
Second, the callbacks passed to the main process will persist until the main process garbage-collects them.
For example, the following code seems innocent at first glance. It installs a
callback for the close event on a remote object:
require('electron').remote.getCurrentWindow().on('close', () => {
// window was closed...
})
But remember the callback is referenced by the main process until you explicitly uninstall it. If you do not, each time you reload your window the callback will be installed again, leaking one callback for each restart.
To make things worse, since the context of previously installed callbacks has
been released, exceptions will be raised in the main process when the close
event is emitted.
To avoid this problem, ensure you clean up any references to renderer callbacks passed to the main process. This involves cleaning up event handlers, or ensuring the main process is explicitly told to dereference callbacks that came from a renderer process that is exiting.
Accessing built-in modules in the main process
The built-in modules in the main process are added as getters in the remote
module, so you can use them directly like the electron module.
const app = require('electron').remote.app
console.log(app)
Methods
The remote module has the following methods:
remote.require(module)
moduleString
Returns any - The object returned by require(module) in the main process.
Modules specified by their relative path will resolve relative to the entrypoint
of the main process.
e.g.
project/
├── main
│ ├── foo.js
│ └── index.js
├── package.json
└── renderer
└── index.js
// main process: main/index.js
const { app } = require('electron')
app.whenReady().then(() => { /* ... */ })
// some relative module: main/foo.js
module.exports = 'bar'
// renderer process: renderer/index.js
const foo = require('electron').remote.require('./foo') // bar
remote.getCurrentWindow()
Returns BrowserWindow - The window to which this web page
belongs.
Note: Do not use removeAllListeners on BrowserWindow.
Use of this can remove all blur
listeners, disable click events on touch bar buttons, and other unintended
consequences.
remote.getCurrentWebContents()
Returns WebContents - The web contents of this web page.
remote.getGlobal(name)
nameString
Returns any - The global variable of name (e.g. global[name]) in the main
process.
remote.process Readonly
A NodeJS.Process object. The process object in the main process. This is the same as
remote.getGlobal('process') but is cached.
REPL
Read-Eval-Print-Loop (REPL) is a simple, interactive computer programming environment that takes single user inputs (i.e. single expressions), evaluates them, and returns the result to the user.
The repl module provides a REPL implementation that can be accessed using:
-
Assuming you have
electronorelectron-prebuiltinstalled as a local project dependency:./node_modules/.bin/electron --interactive -
Assuming you have
electronorelectron-prebuiltinstalled globally:electron --interactive
This only creates a REPL for the main process. You can use the Console tab of the Dev Tools to get a REPL for the renderer processes.
Note: electron --interactive is not available on Windows.
More information can be found in the Node.js REPL docs.
Represented File for macOS BrowserWindows
On macOS a window can set its represented file, so the file's icon can show in the title bar and when users Command-Click or Control-Click on the title a path popup will show.
You can also set the edited state of a window so that the file icon can indicate whether the document in this window has been modified.
Represented file popup menu:

To set the represented file of window, you can use the BrowserWindow.setRepresentedFilename and BrowserWindow.setDocumentEdited APIs:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.setRepresentedFilename('/etc/passwd')
win.setDocumentEdited(true)
sandbox Option
Create a browser window with a sandboxed renderer. With this option enabled, the renderer must communicate via IPC to the main process in order to access node APIs.
One of the key security features of Chromium is that all blink rendering/JavaScript code is executed within a sandbox. This sandbox uses OS-specific features to ensure that exploits in the renderer process cannot harm the system.
In other words, when the sandbox is enabled, the renderers can only make changes to the system by delegating tasks to the main process via IPC. Here's more information about the sandbox.
Since a major feature in Electron is the ability to run Node.js in the
renderer process (making it easier to develop desktop applications using web
technologies), the sandbox is disabled by electron. This is because
most Node.js APIs require system access. require() for example, is not
possible without file system permissions, which are not available in a sandboxed
environment.
Usually this is not a problem for desktop applications since the code is always
trusted, but it makes Electron less secure than Chromium for displaying
untrusted web content. For applications that require more security, the
sandbox flag will force Electron to spawn a classic Chromium renderer that is
compatible with the sandbox.
A sandboxed renderer doesn't have a Node.js environment running and doesn't expose Node.js JavaScript APIs to client code. The only exception is the preload script, which has access to a subset of the Electron renderer API.
Another difference is that sandboxed renderers don't modify any of the default
JavaScript APIs. Consequently, some APIs such as window.open will work as they
do in Chromium (i.e. they do not return a BrowserWindowProxy).
Example
To create a sandboxed window, pass sandbox: true to webPreferences:
let win
app.whenReady().then(() => {
win = new BrowserWindow({
webPreferences: {
sandbox: true
}
})
win.loadURL('http://google.com')
})
In the above code the BrowserWindow that was created has Node.js disabled and can communicate
only via IPC. The use of this option stops Electron from creating a Node.js runtime in the renderer. Also,
within this new window window.open follows the native behavior (by default Electron creates a BrowserWindow
and returns a proxy to this via window.open).
app.enableSandbox can be used to force sandbox: true for all BrowserWindow instances.
let win
app.enableSandbox()
app.whenReady().then(() => {
// no need to pass `sandbox: true` since `app.enableSandbox()` was called.
win = new BrowserWindow()
win.loadURL('http://google.com')
})
Preload
An app can make customizations to sandboxed renderers using a preload script. Here's an example:
let win
app.whenReady().then(() => {
win = new BrowserWindow({
webPreferences: {
sandbox: true,
preload: path.join(app.getAppPath(), 'preload.js')
}
})
win.loadURL('http://google.com')
})
and preload.js:
// This file is loaded whenever a javascript context is created. It runs in a
// private scope that can access a subset of Electron renderer APIs. We must be
// careful to not leak any objects into the global scope!
const { ipcRenderer, remote } = require('electron')
const fs = remote.require('fs')
// read a configuration file using the `fs` module
const buf = fs.readFileSync('allowed-popup-urls.json')
const allowedUrls = JSON.parse(buf.toString('utf8'))
const defaultWindowOpen = window.open
function customWindowOpen (url, ...args) {
if (allowedUrls.indexOf(url) === -1) {
ipcRenderer.sendSync('blocked-popup-notification', location.origin, url)
return null
}
return defaultWindowOpen(url, ...args)
}
window.open = customWindowOpen
Important things to notice in the preload script:
- Even though the sandboxed renderer doesn't have Node.js running, it still has
access to a limited node-like environment:
Buffer,process,setImmediate,clearImmediateandrequireare available. - The preload script can indirectly access all APIs from the main process through the
remoteandipcRenderermodules. - The preload script must be contained in a single script, but it is possible to have complex preload code composed with multiple modules by using a tool like webpack or browserify. An example of using browserify is below.
To create a browserify bundle and use it as a preload script, something like the following should be used:
browserify preload/index.js \
-x electron \
--insert-global-vars=__filename,__dirname -o preload.js
The -x flag should be used with any required module that is already exposed in
the preload scope, and tells browserify to use the enclosing require function
for it. --insert-global-vars will ensure that process, Buffer and
setImmediate are also taken from the enclosing scope(normally browserify
injects code for those).
Currently the require function provided in the preload scope exposes the
following modules:
electroncrashReporterdesktopCaptureripcRenderernativeImageremotewebFrame
eventstimersurl
More may be added as needed to expose more Electron APIs in the sandbox, but any
module in the main process can already be used through
electron.remote.require.
Rendering untrusted content
Rendering untrusted content in Electron is still somewhat uncharted territory, though some apps are finding success (e.g. Beaker Browser). Our goal is to get as close to Chrome as we can in terms of the security of sandboxed content, but ultimately we will always be behind due to a few fundamental issues:
- We do not have the dedicated resources or expertise that Chromium has to apply to the security of its product. We do our best to make use of what we have, to inherit everything we can from Chromium, and to respond quickly to security issues, but Electron cannot be as secure as Chromium without the resources that Chromium is able to dedicate.
- Some security features in Chrome (such as Safe Browsing and Certificate Transparency) require a centralized authority and dedicated servers, both of which run counter to the goals of the Electron project. As such, we disable those features in Electron, at the cost of the associated security they would otherwise bring.
- There is only one Chromium, whereas there are many thousands of apps built on Electron, all of which behave slightly differently. Accounting for those differences can yield a huge possibility space, and make it challenging to ensure the security of the platform in unusual use cases.
- We can't push security updates to users directly, so we rely on app vendors to upgrade the version of Electron underlying their app in order for security updates to reach users.
Here are some things to consider before rendering untrusted content:
- A preload script can accidentally leak privileged APIs to untrusted code,
unless
contextIsolationis also enabled. - Some bug in the V8 engine may allow malicious code to access the renderer
preload APIs, effectively granting full access to the system through the
remotemodule. Therefore, it is highly recommended to disable theremotemodule. If disabling is not feasible, you should selectively filter theremotemodule. - While we make our best effort to backport Chromium security fixes to older versions of Electron, we do not make a guarantee that every fix will be backported. Your best chance at staying secure is to be on the latest stable version of Electron.
screen
Retrieve information about screen size, displays, cursor position, etc.
Process: Main
This module cannot be used until the ready event of the app
module is emitted.
screen is an EventEmitter.
Note: In the renderer / DevTools, window.screen is a reserved DOM
property, so writing let { screen } = require('electron') will not work.
An example of creating a window that fills the whole screen:
const { app, BrowserWindow, screen } = require('electron')
let win
app.whenReady().then(() => {
const { width, height } = screen.getPrimaryDisplay().workAreaSize
win = new BrowserWindow({ width, height })
win.loadURL('https://github.com')
})
Another example of creating a window in the external display:
const { app, BrowserWindow, screen } = require('electron')
let win
app.whenReady().then(() => {
let displays = screen.getAllDisplays()
let externalDisplay = displays.find((display) => {
return display.bounds.x !== 0 || display.bounds.y !== 0
})
if (externalDisplay) {
win = new BrowserWindow({
x: externalDisplay.bounds.x + 50,
y: externalDisplay.bounds.y + 50
})
win.loadURL('https://github.com')
}
})
Events
The screen module emits the following events:
Event: 'display-added'
Returns:
eventEventnewDisplayDisplay
Emitted when newDisplay has been added.
Event: 'display-removed'
Returns:
eventEventoldDisplayDisplay
Emitted when oldDisplay has been removed.
Event: 'display-metrics-changed'
Returns:
eventEventdisplayDisplaychangedMetricsString[]
Emitted when one or more metrics change in a display. The changedMetrics is
an array of strings that describe the changes. Possible changes are bounds,
workArea, scaleFactor and rotation.
Methods
The screen module has the following methods:
screen.getPrimaryDisplay()
Returns Display - The primary display.
screen.getAllDisplays()
Returns Display[] - An array of displays that are currently available.
screen.getDisplayNearestPoint(point)
pointPoint
Returns Display - The display nearest the specified point.
screen.getDisplayMatching(rect)
rectRectangle
Returns Display - The display that most closely
intersects the provided bounds.
screen.screenToDipPoint(point) Windows
pointPoint
Returns Point
Converts a screen physical point to a screen DIP point. The DPI scale is performed relative to the display containing the physical point.
screen.dipToScreenPoint(point) Windows
pointPoint
Returns Point
Converts a screen DIP point to a screen physical point. The DPI scale is performed relative to the display containing the DIP point.
screen.screenToDipRect(window, rect) Windows
windowBrowserWindow | nullrectRectangle
Returns Rectangle
Converts a screen physical rect to a screen DIP rect.
The DPI scale is performed relative to the display nearest to window.
If window is null, scaling will be performed to the display nearest to rect.
screen.dipToScreenRect(window, rect) Windows
windowBrowserWindow | nullrectRectangle
Returns Rectangle
Converts a screen DIP rect to a screen physical rect.
The DPI scale is performed relative to the display nearest to window.
If window is null, scaling will be performed to the display nearest to rect.
ScrubberItem Object
labelString (optional) - The text to appear in this item.iconNativeImage (optional) - The image to appear in this item.
Security, Native Capabilities, and Your Responsibility
As web developers, we usually enjoy the strong security net of the browser - the risks associated with the code we write are relatively small. Our websites are granted limited powers in a sandbox, and we trust that our users enjoy a browser built by a large team of engineers that is able to quickly respond to newly discovered security threats.
When working with Electron, it is important to understand that Electron is not a web browser. It allows you to build feature-rich desktop applications with familiar web technologies, but your code wields much greater power. JavaScript can access the filesystem, user shell, and more. This allows you to build high quality native applications, but the inherent security risks scale with the additional powers granted to your code.
With that in mind, be aware that displaying arbitrary content from untrusted sources poses a severe security risk that Electron is not intended to handle. In fact, the most popular Electron apps (Atom, Slack, Visual Studio Code, etc) display primarily local content (or trusted, secure remote content without Node integration) – if your application executes code from an online source, it is your responsibility to ensure that the code is not malicious.
Reporting Security Issues
For information on how to properly disclose an Electron vulnerability, see SECURITY.md
Chromium Security Issues and Upgrades
Electron keeps up to date with alternating Chromium releases. For more information, see the Electron Release Cadence blog post.
Security Is Everyone's Responsibility
It is important to remember that the security of your Electron application is the result of the overall security of the framework foundation (Chromium, Node.js), Electron itself, all NPM dependencies and your code. As such, it is your responsibility to follow a few important best practices:
-
Keep your application up-to-date with the latest Electron framework release. When releasing your product, you’re also shipping a bundle composed of Electron, Chromium shared library and Node.js. Vulnerabilities affecting these components may impact the security of your application. By updating Electron to the latest version, you ensure that critical vulnerabilities (such as nodeIntegration bypasses) are already patched and cannot be exploited in your application. For more information, see "Use a current version of Electron".
-
Evaluate your dependencies. While NPM provides half a million reusable packages, it is your responsibility to choose trusted 3rd-party libraries. If you use outdated libraries affected by known vulnerabilities or rely on poorly maintained code, your application security could be in jeopardy.
-
Adopt secure coding practices. The first line of defense for your application is your own code. Common web vulnerabilities, such as Cross-Site Scripting (XSS), have a higher security impact on Electron applications hence it is highly recommended to adopt secure software development best practices and perform security testing.
Isolation For Untrusted Content
A security issue exists whenever you receive code from an untrusted source (e.g.
a remote server) and execute it locally. As an example, consider a remote
website being displayed inside a default BrowserWindow. If
an attacker somehow manages to change said content (either by attacking the
source directly, or by sitting between your app and the actual destination), they
will be able to execute native code on the user's machine.
⚠️ Under no circumstances should you load and execute remote code with Node.js integration enabled. Instead, use only local files (packaged together with your application) to execute Node.js code. To display remote content, use the
<webview>tag orBrowserView, make sure to disable thenodeIntegrationand enablecontextIsolation.
Electron Security Warnings
From Electron 2.0 on, developers will see warnings and recommendations printed to the developer console. They only show up when the binary's name is Electron, indicating that a developer is currently looking at the console.
You can force-enable or force-disable these warnings by setting
ELECTRON_ENABLE_SECURITY_WARNINGS or ELECTRON_DISABLE_SECURITY_WARNINGS on
either process.env or the window object.
Checklist: Security Recommendations
You should at least follow these steps to improve the security of your application:
- Only load secure content
- Disable the Node.js integration in all renderers that display remote content
- Enable context isolation in all renderers that display remote content
- Use
ses.setPermissionRequestHandler()in all sessions that load remote content - Do not disable
webSecurity - Define a
Content-Security-Policyand use restrictive rules (i.e.script-src 'self') - Do not set
allowRunningInsecureContenttotrue - Do not enable experimental features
- Do not use
enableBlinkFeatures <webview>: Do not useallowpopups<webview>: Verify options and params- Disable or limit navigation
- Disable or limit creation of new windows
- Do not use
openExternalwith untrusted content - Disable the
remotemodule - Filter the
remotemodule - Use a current version of Electron
To automate the detection of misconfigurations and insecure patterns, it is possible to use electronegativity. For additional details on potential weaknesses and implementation bugs when developing applications using Electron, please refer to this guide for developers and auditors
1) Only Load Secure Content
Any resources not included with your application should be loaded using a
secure protocol like HTTPS. In other words, do not use insecure protocols
like HTTP. Similarly, we recommend the use of WSS over WS, FTPS over
FTP, and so on.
Why?
HTTPS has three main benefits:
1) It authenticates the remote server, ensuring your app connects to the correct host instead of an impersonator. 2) It ensures data integrity, asserting that the data was not modified while in transit between your application and the host. 3) It encrypts the traffic between your user and the destination host, making it more difficult to eavesdrop on the information sent between your app and the host.
How?
// Bad
browserWindow.loadURL('http://example.com')
// Good
browserWindow.loadURL('https://example.com')
<!-- Bad -->
<script crossorigin src="http://example.com/react.js"></script>
<link rel="stylesheet" href="http://example.com/style.css">
<!-- Good -->
<script crossorigin src="https://example.com/react.js"></script>
<link rel="stylesheet" href="https://example.com/style.css">
2) Do not enable Node.js Integration for Remote Content
This recommendation is the default behavior in Electron since 5.0.0.
It is paramount that you do not enable Node.js integration in any renderer
(BrowserWindow, BrowserView, or
<webview>) that loads remote content. The goal is to limit the
powers you grant to remote content, thus making it dramatically more difficult
for an attacker to harm your users should they gain the ability to execute
JavaScript on your website.
After this, you can grant additional permissions for specific hosts. For example,
if you are opening a BrowserWindow pointed at https://example.com/, you can
give that website exactly the abilities it needs, but no more.
Why?
A cross-site-scripting (XSS) attack is more dangerous if an attacker can jump out of the renderer process and execute code on the user's computer. Cross-site-scripting attacks are fairly common - and while an issue, their power is usually limited to messing with the website that they are executed on. Disabling Node.js integration helps prevent an XSS from being escalated into a so-called "Remote Code Execution" (RCE) attack.
How?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true
}
})
mainWindow.loadURL('https://example.com')
// Good
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})
mainWindow.loadURL('https://example.com')
<!-- Bad -->
<webview nodeIntegration src="page.html"></webview>
<!-- Good -->
<webview src="page.html"></webview>
When disabling Node.js integration, you can still expose APIs to your website that
do consume Node.js modules or features. Preload scripts continue to have access
to require and other Node.js features, allowing developers to expose a custom
API to remotely loaded content.
In the following example preload script, the later loaded website will have
access to a window.readConfig() method, but no Node.js features.
const { readFileSync } = require('fs')
window.readConfig = function () {
const data = readFileSync('./config.json')
return data
}
3) Enable Context Isolation for Remote Content
Context isolation is an Electron feature that allows developers to run code
in preload scripts and in Electron APIs in a dedicated JavaScript context. In
practice, that means that global objects like Array.prototype.push or
JSON.parse cannot be modified by scripts running in the renderer process.
Electron uses the same technology as Chromium's Content Scripts to enable this behavior.
Even when you use nodeIntegration: false to enforce strong isolation and
prevent the use of Node primitives, contextIsolation must also be used.
Why & How?
For more information on what contextIsolation is and how to enable it please
see our dedicated Context Isolation document.
4) Handle Session Permission Requests From Remote Content
You may have seen permission requests while using Chrome: They pop up whenever the website attempts to use a feature that the user has to manually approve ( like notifications).
The API is based on the Chromium permissions API and implements the same types of permissions.
Why?
By default, Electron will automatically approve all permission requests unless the developer has manually configured a custom handler. While a solid default, security-conscious developers might want to assume the very opposite.
How?
const { session } = require('electron')
session
.fromPartition('some-partition')
.setPermissionRequestHandler((webContents, permission, callback) => {
const url = webContents.getURL()
if (permission === 'notifications') {
// Approves the permissions request
callback(true)
}
// Verify URL
if (!url.startsWith('https://example.com/')) {
// Denies the permissions request
return callback(false)
}
})
5) Do Not Disable WebSecurity
Recommendation is Electron's default
You may have already guessed that disabling the webSecurity property on a
renderer process (BrowserWindow,
BrowserView, or <webview>) disables crucial
security features.
Do not disable webSecurity in production applications.
Why?
Disabling webSecurity will disable the same-origin policy and set
allowRunningInsecureContent property to true. In other words, it allows
the execution of insecure code from different domains.
How?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
webSecurity: false
}
})
// Good
const mainWindow = new BrowserWindow()
<!-- Bad -->
<webview disablewebsecurity src="page.html"></webview>
<!-- Good -->
<webview src="page.html"></webview>
6) Define a Content Security Policy
A Content Security Policy (CSP) is an additional layer of protection against cross-site-scripting attacks and data injection attacks. We recommend that they be enabled by any website you load inside Electron.
Why?
CSP allows the server serving content to restrict and control the resources
Electron can load for that given web page. https://example.com should
be allowed to load scripts from the origins you defined while scripts from
https://evil.attacker.com should not be allowed to run. Defining a CSP is an
easy way to improve your application's security.
The following CSP will allow Electron to execute scripts from the current
website and from apis.example.com.
// Bad
Content-Security-Policy: '*'
// Good
Content-Security-Policy: script-src 'self' https://apis.example.com
CSP HTTP Header
Electron respects the Content-Security-Policy HTTP header
which can be set using Electron's
webRequest.onHeadersReceived
handler:
const { session } = require('electron')
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': ['default-src \'none\'']
}
})
})
CSP Meta Tag
CSP's preferred delivery mechanism is an HTTP header, however it is not possible
to use this method when loading a resource using the file:// protocol. It can
be useful in some cases, such as using the file:// protocol, to set a policy
on a page directly in the markup using a <meta> tag:
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
7) Do Not Set allowRunningInsecureContent to true
Recommendation is Electron's default
By default, Electron will not allow websites loaded over HTTPS to load and
execute scripts, CSS, or plugins from insecure sources (HTTP). Setting the
property allowRunningInsecureContent to true disables that protection.
Loading the initial HTML of a website over HTTPS and attempting to load
subsequent resources via HTTP is also known as "mixed content".
Why?
Loading content over HTTPS assures the authenticity and integrity
of the loaded resources while encrypting the traffic itself. See the section on
only displaying secure content for more details.
How?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
allowRunningInsecureContent: true
}
})
// Good
const mainWindow = new BrowserWindow({})
8) Do Not Enable Experimental Features
Recommendation is Electron's default
Advanced users of Electron can enable experimental Chromium features using the
experimentalFeatures property.
Why?
Experimental features are, as the name suggests, experimental and have not been enabled for all Chromium users. Furthermore, their impact on Electron as a whole has likely not been tested.
Legitimate use cases exist, but unless you know what you are doing, you should not enable this property.
How?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
experimentalFeatures: true
}
})
// Good
const mainWindow = new BrowserWindow({})
9) Do Not Use enableBlinkFeatures
Recommendation is Electron's default
Blink is the name of the rendering engine behind Chromium. As with
experimentalFeatures, the enableBlinkFeatures property allows developers to
enable features that have been disabled by default.
Why?
Generally speaking, there are likely good reasons if a feature was not enabled by default. Legitimate use cases for enabling specific features exist. As a developer, you should know exactly why you need to enable a feature, what the ramifications are, and how it impacts the security of your application. Under no circumstances should you enable features speculatively.
How?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
enableBlinkFeatures: 'ExecCommandInJavaScript'
}
})
// Good
const mainWindow = new BrowserWindow()
10) Do Not Use allowpopups
Recommendation is Electron's default
If you are using <webview>, you might need the pages and scripts
loaded in your <webview> tag to open new windows. The allowpopups attribute
enables them to create new BrowserWindows using the
window.open() method. <webview> tags are otherwise not allowed to create new
windows.
Why?
If you do not need popups, you are better off not allowing the creation of
new BrowserWindows by default. This follows the principle
of minimally required access: Don't let a website create new popups unless
you know it needs that feature.
How?
<!-- Bad -->
<webview allowpopups src="page.html"></webview>
<!-- Good -->
<webview src="page.html"></webview>
11) Verify WebView Options Before Creation
A WebView created in a renderer process that does not have Node.js integration
enabled will not be able to enable integration itself. However, a WebView will
always create an independent renderer process with its own webPreferences.
It is a good idea to control the creation of new <webview> tags
from the main process and to verify that their webPreferences do not disable
security features.
Why?
Since <webview> live in the DOM, they can be created by a script running on your
website even if Node.js integration is otherwise disabled.
Electron enables developers to disable various security features that control
a renderer process. In most cases, developers do not need to disable any of
those features - and you should therefore not allow different configurations
for newly created <webview> tags.
How?
Before a <webview> tag is attached, Electron will fire the
will-attach-webview event on the hosting webContents. Use the event to
prevent the creation of webViews with possibly insecure options.
app.on('web-contents-created', (event, contents) => {
contents.on('will-attach-webview', (event, webPreferences, params) => {
// Strip away preload scripts if unused or verify their location is legitimate
delete webPreferences.preload
delete webPreferences.preloadURL
// Disable Node.js integration
webPreferences.nodeIntegration = false
// Verify URL being loaded
if (!params.src.startsWith('https://example.com/')) {
event.preventDefault()
}
})
})
Again, this list merely minimizes the risk, it does not remove it. If your goal is to display a website, a browser will be a more secure option.
12) Disable or limit navigation
If your app has no need to navigate or only needs to navigate to known pages, it is a good idea to limit navigation outright to that known scope, disallowing any other kinds of navigation.
Why?
Navigation is a common attack vector. If an attacker can convince your app to
navigate away from its current page, they can possibly force your app to open
web sites on the Internet. Even if your webContents are configured to be more
secure (like having nodeIntegration disabled or contextIsolation enabled),
getting your app to open a random web site will make the work of exploiting your
app a lot easier.
A common attack pattern is that the attacker convinces your app's users to interact with the app in such a way that it navigates to one of the attacker's pages. This is usually done via links, plugins, or other user-generated content.
How?
If your app has no need for navigation, you can call event.preventDefault()
in a will-navigate handler. If you know which pages your app
might navigate to, check the URL in the event handler and only let navigation
occur if it matches the URLs you're expecting.
We recommend that you use Node's parser for URLs. Simple string comparisons can
sometimes be fooled - a startsWith('https://example.com') test would let
https://example.com.attacker.com through.
const URL = require('url').URL
app.on('web-contents-created', (event, contents) => {
contents.on('will-navigate', (event, navigationUrl) => {
const parsedUrl = new URL(navigationUrl)
if (parsedUrl.origin !== 'https://example.com') {
event.preventDefault()
}
})
})
13) Disable or limit creation of new windows
If you have a known set of windows, it's a good idea to limit the creation of additional windows in your app.
Why?
Much like navigation, the creation of new webContents is a common attack
vector. Attackers attempt to convince your app to create new windows, frames,
or other renderer processes with more privileges than they had before; or
with pages opened that they couldn't open before.
If you have no need to create windows in addition to the ones you know you'll
need to create, disabling the creation buys you a little bit of extra
security at no cost. This is commonly the case for apps that open one
BrowserWindow and do not need to open an arbitrary number of additional
windows at runtime.
How?
webContents will emit the new-window event
before creating new windows. That event will be passed, amongst other
parameters, the url the window was requested to open and the options used to
create it. We recommend that you use the event to scrutinize the creation of
windows, limiting it to only what you need.
const { shell } = require('electron')
app.on('web-contents-created', (event, contents) => {
contents.on('new-window', async (event, navigationUrl) => {
// In this example, we'll ask the operating system
// to open this event's url in the default browser.
event.preventDefault()
await shell.openExternal(navigationUrl)
})
})
14) Do not use openExternal with untrusted content
Shell's openExternal allows opening a given protocol URI with
the desktop's native utilities. On macOS, for instance, this function is similar
to the open terminal command utility and will open the specific application
based on the URI and filetype association.
Why?
Improper use of openExternal can be leveraged to compromise
the user's host. When openExternal is used with untrusted content, it can be
leveraged to execute arbitrary commands.
How?
// Bad
const { shell } = require('electron')
shell.openExternal(USER_CONTROLLED_DATA_HERE)
// Good
const { shell } = require('electron')
shell.openExternal('https://example.com/index.html')
15) Disable the remote module
The remote module provides a way for the renderer processes to
access APIs normally only available in the main process. Using it, a
renderer can invoke methods of a main process object without explicitly sending
inter-process messages. If your desktop application does not run untrusted
content, this can be a useful way to have your renderer processes access and
work with modules that are only available to the main process, such as
GUI-related modules (dialogs, menus, etc.).
However, if your app can run untrusted content and even if you
sandbox your renderer processes accordingly, the remote module
makes it easy for malicious code to escape the sandbox and have access to
system resources via the higher privileges of the main process. Therefore,
it should be disabled in such circumstances.
Why?
remote uses an internal IPC channel to communicate with the main process.
"Prototype pollution" attacks can grant malicious code access to the internal
IPC channel, which can then be used to escape the sandbox by mimicking remote
IPC messages and getting access to main process modules running with higher
privileges.
Additionally, it's possible for preload scripts to accidentally leak modules to a
sandboxed renderer. Leaking remote arms malicious code with a multitude
of main process modules with which to perform an attack.
Disabling the remote module eliminates these attack vectors. Enabling
context isolation also prevents the "prototype pollution" attacks from
succeeding.
How?
// Bad if the renderer can run untrusted content
const mainWindow = new BrowserWindow({})
// Good
const mainWindow = new BrowserWindow({
webPreferences: {
enableRemoteModule: false
}
})
<!-- Bad if the renderer can run untrusted content -->
<webview src="page.html"></webview>
<!-- Good -->
<webview enableremotemodule="false" src="page.html"></webview>
16) Filter the remote module
If you cannot disable the remote module, you should filter the globals,
Node, and Electron modules (so-called built-ins) accessible via remote
that your application does not require. This can be done by blocking
certain modules entirely and by replacing others with proxies that
expose only the functionality that your app needs.
Why?
Due to the system access privileges of the main process, functionality provided by the main process modules may be dangerous in the hands of malicious code running in a compromised renderer process. By limiting the set of accessible modules to the minimum that your app needs and filtering out the others, you reduce the toolset that malicious code can use to attack the system.
Note that the safest option is to fully disable the remote module. If you choose to filter access rather than completely disable the module, you must be very careful to ensure that no escalation of privilege is possible through the modules you allow past the filter.
How?
const readOnlyFsProxy = require(/* ... */) // exposes only file read functionality
const allowedModules = new Set(['crypto'])
const proxiedModules = new Map(['fs', readOnlyFsProxy])
const allowedElectronModules = new Set(['shell'])
const allowedGlobals = new Set()
app.on('remote-require', (event, webContents, moduleName) => {
if (proxiedModules.has(moduleName)) {
event.returnValue = proxiedModules.get(moduleName)
}
if (!allowedModules.has(moduleName)) {
event.preventDefault()
}
})
app.on('remote-get-builtin', (event, webContents, moduleName) => {
if (!allowedElectronModules.has(moduleName)) {
event.preventDefault()
}
})
app.on('remote-get-global', (event, webContents, globalName) => {
if (!allowedGlobals.has(globalName)) {
event.preventDefault()
}
})
app.on('remote-get-current-window', (event, webContents) => {
event.preventDefault()
})
app.on('remote-get-current-web-contents', (event, webContents) => {
event.preventDefault()
})
17) Use a current version of Electron
You should strive for always using the latest available version of Electron. Whenever a new major version is released, you should attempt to update your app as quickly as possible.
Why?
An application built with an older version of Electron, Chromium, and Node.js is an easier target than an application that is using more recent versions of those components. Generally speaking, security issues and exploits for older versions of Chromium and Node.js are more widely available.
Both Chromium and Node.js are impressive feats of engineering built by thousands of talented developers. Given their popularity, their security is carefully tested and analyzed by equally skilled security researchers. Many of those researchers disclose vulnerabilities responsibly, which generally means that researchers will give Chromium and Node.js some time to fix issues before publishing them. Your application will be more secure if it is running a recent version of Electron (and thus, Chromium and Node.js) for which potential security issues are not as widely known.
SegmentedControlSegment Object
labelString (optional) - The text to appear in this segment.iconNativeImage (optional) - The image to appear in this segment.enabledBoolean (optional) - Whether this segment is selectable. Default: true.
ServiceWorkerInfo Object
scriptUrlString - The full URL to the script that this service worker runsscopeString - The base URL that this service worker is active for.renderProcessIdNumber - The virtual ID of the process that this service worker is running in. This is not an OS level PID. This aligns with the ID set used forwebContents.getProcessId().
Class: ServiceWorkers
Query and receive events from a sessions active service workers.
Process: Main
Instances of the ServiceWorkers class are accessed by using serviceWorkers property of
a Session.
For example:
const { session } = require('electron')
// Get all service workers.
console.log(session.defaultSession.serviceWorkers.getAllRunning())
// Handle logs and get service worker info
session.defaultSession.serviceWorkers.on('console-message', (event, messageDetails) => {
console.log(
'Got service worker message',
messageDetails,
'from',
session.defaultSession.serviceWorkers.getFromVersionID(messageDetails.versionId)
)
})
Instance Events
The following events are available on instances of ServiceWorkers:
Event: 'console-message'
Returns:
eventEventmessageDetailsObject - Information about the console messagemessageString - The actual console messageversionIdNumber - The version ID of the service worker that sent the log messagesourceString - The type of source for this message. Can bejavascript,xml,network,console-api,storage,app-cache,rendering,security,deprecation,worker,violation,intervention,recommendationorother.levelNumber - The log level, from 0 to 3. In order it matchesverbose,info,warninganderror.sourceUrlString - The URL the message came fromlineNumberNumber - The line number of the source that triggered this console message
Emitted when a service worker logs something to the console.
Instance Methods
The following methods are available on instances of ServiceWorkers:
serviceWorkers.getAllRunning()
Returns Record<Number, ServiceWorkerInfo> - A ServiceWorkerInfo object where the keys are the service worker version ID and the values are the information about that service worker.
serviceWorkers.getFromVersionID(versionId)
versionIdNumber
Returns ServiceWorkerInfo - Information about this service worker
If the service worker does not exist or is not running this method will throw an exception.
session
Manage browser sessions, cookies, cache, proxy settings, etc.
Process: Main
The session module can be used to create new Session objects.
You can also access the session of existing pages by using the session
property of WebContents, or from the session module.
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
const ses = win.webContents.session
console.log(ses.getUserAgent())
Methods
The session module has the following methods:
session.fromPartition(partition[, options])
partitionStringoptionsObject (optional)cacheBoolean - Whether to enable cache.
Returns Session - A session instance from partition string. When there is an existing
Session with the same partition, it will be returned; otherwise a new
Session instance will be created with options.
If partition starts with persist:, the page will use a persistent session
available to all pages in the app with the same partition. if there is no
persist: prefix, the page will use an in-memory session. If the partition is
empty then default session of the app will be returned.
To create a Session with options, you have to ensure the Session with the
partition has never been used before. There is no way to change the options
of an existing Session object.
Properties
The session module has the following properties:
session.defaultSession
A Session object, the default session object of the app.
Class: Session
Get and set properties of a session.
Process: Main
You can create a Session object in the session module:
const { session } = require('electron')
const ses = session.fromPartition('persist:name')
console.log(ses.getUserAgent())
Instance Events
The following events are available on instances of Session:
Event: 'will-download'
Returns:
eventEventitemDownloadItemwebContentsWebContents
Emitted when Electron is about to download item in webContents.
Calling event.preventDefault() will cancel the download and item will not be
available from next tick of the process.
const { session } = require('electron')
session.defaultSession.on('will-download', (event, item, webContents) => {
event.preventDefault()
require('request')(item.getURL(), (data) => {
require('fs').writeFileSync('/somewhere', data)
})
})
Event: 'preconnect'
Returns:
eventEventpreconnectUrlString - The URL being requested for preconnection by the renderer.allowCredentialsBoolean - True if the renderer is requesting that the connection include credentials (see the spec for more details.)
Emitted when a render process requests preconnection to a URL, generally due to a resource hint.
Event: 'spellcheck-dictionary-initialized'
Returns:
eventEventlanguageCodeString - The language code of the dictionary file
Emitted when a hunspell dictionary file has been successfully initialized. This occurs after the file has been downloaded.
Event: 'spellcheck-dictionary-download-begin'
Returns:
eventEventlanguageCodeString - The language code of the dictionary file
Emitted when a hunspell dictionary file starts downloading
Event: 'spellcheck-dictionary-download-success'
Returns:
eventEventlanguageCodeString - The language code of the dictionary file
Emitted when a hunspell dictionary file has been successfully downloaded
Event: 'spellcheck-dictionary-download-failure'
Returns:
eventEventlanguageCodeString - The language code of the dictionary file
Emitted when a hunspell dictionary file download fails. For details on the failure you should collect a netlog and inspect the download request.
Instance Methods
The following methods are available on instances of Session:
ses.getCacheSize()
Returns Promise<Integer> - the session's current cache size, in bytes.
ses.clearCache()
Returns Promise<void> - resolves when the cache clear operation is complete.
Clears the session’s HTTP cache.
ses.clearStorageData([options])
optionsObject (optional)originString (optional) - Should followwindow.location.origin’s representationscheme://host:port.storagesString[] (optional) - The types of storages to clear, can contain:appcache,cookies,filesystem,indexdb,localstorage,shadercache,websql,serviceworkers,cachestorage. If not specified, clear all storage types.quotasString[] (optional) - The types of quotas to clear, can contain:temporary,persistent,syncable. If not specified, clear all quotas.
Returns Promise<void> - resolves when the storage data has been cleared.
ses.flushStorageData()
Writes any unwritten DOMStorage data to disk.
ses.setProxy(config)
configObjectpacScriptString (optional) - The URL associated with the PAC file.proxyRulesString (optional) - Rules indicating which proxies to use.proxyBypassRulesString (optional) - Rules indicating which URLs should bypass the proxy settings.
Returns Promise<void> - Resolves when the proxy setting process is complete.
Sets the proxy settings.
When pacScript and proxyRules are provided together, the proxyRules
option is ignored and pacScript configuration is applied.
The proxyRules has to follow the rules below:
proxyRules = schemeProxies[";"<schemeProxies>]
schemeProxies = [<urlScheme>"="]<proxyURIList>
urlScheme = "http" | "https" | "ftp" | "socks"
proxyURIList = <proxyURL>[","<proxyURIList>]
proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
For example:
http=foopy:80;ftp=foopy2- Use HTTP proxyfoopy:80forhttp://URLs, and HTTP proxyfoopy2:80forftp://URLs.foopy:80- Use HTTP proxyfoopy:80for all URLs.foopy:80,bar,direct://- Use HTTP proxyfoopy:80for all URLs, failing over tobariffoopy:80is unavailable, and after that using no proxy.socks4://foopy- Use SOCKS v4 proxyfoopy:1080for all URLs.http=foopy,socks5://bar.com- Use HTTP proxyfoopyfor http URLs, and fail over to the SOCKS5 proxybar.comiffoopyis unavailable.http=foopy,direct://- Use HTTP proxyfoopyfor http URLs, and use no proxy iffoopyis unavailable.http=foopy;socks=foopy2- Use HTTP proxyfoopyfor http URLs, and usesocks4://foopy2for all other URLs.
The proxyBypassRules is a comma separated list of rules described below:
-
[ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]Match all hostnames that match the pattern HOSTNAME_PATTERN.
Examples: "foobar.com", "foobar.com", ".foobar.com", "foobar.com:99", "https://x..y.com:99"
-
"." HOSTNAME_SUFFIX_PATTERN [ ":" PORT ]Match a particular domain suffix.
Examples: ".google.com", ".com", "http://.google.com"
-
[ SCHEME "://" ] IP_LITERAL [ ":" PORT ]Match URLs which are IP address literals.
Examples: "127.0.1", "[0:0::1]", "[::1]", "http://[::1]:99"
-
IP_LITERAL "/" PREFIX_LENGTH_IN_BITSMatch any URL that is to an IP literal that falls between the given range. IP range is specified using CIDR notation.
Examples: "192.168.1.1/16", "fefe:13::abc/33".
-
<local>Match local addresses. The meaning of
<local>is whether the host matches one of: "127.0.0.1", "::1", "localhost".
ses.resolveProxy(url)
urlURL
Returns Promise<String> - Resolves with the proxy information for url.
ses.setDownloadPath(path)
pathString - The download location.
Sets download saving directory. By default, the download directory will be the
Downloads under the respective app folder.
ses.enableNetworkEmulation(options)
optionsObjectofflineBoolean (optional) - Whether to emulate network outage. Defaults to false.latencyDouble (optional) - RTT in ms. Defaults to 0 which will disable latency throttling.downloadThroughputDouble (optional) - Download rate in Bps. Defaults to 0 which will disable download throttling.uploadThroughputDouble (optional) - Upload rate in Bps. Defaults to 0 which will disable upload throttling.
Emulates network with the given configuration for the session.
// To emulate a GPRS connection with 50kbps throughput and 500 ms latency.
window.webContents.session.enableNetworkEmulation({
latency: 500,
downloadThroughput: 6400,
uploadThroughput: 6400
})
// To emulate a network outage.
window.webContents.session.enableNetworkEmulation({ offline: true })
ses.preconnect(options)
optionsObjecturlString - URL for preconnect. Only the origin is relevant for opening the socket.numSocketsNumber (optional) - number of sockets to preconnect. Must be between 1 and 6. Defaults to 1.
Preconnects the given number of sockets to an origin.
ses.disableNetworkEmulation()
Disables any network emulation already active for the session. Resets to
the original network configuration.
ses.setCertificateVerifyProc(proc)
procFunction | nullrequestObjecthostnameStringcertificateCertificatevalidatedCertificateCertificateverificationResultString - Verification result from chromium.errorCodeInteger - Error code.
callbackFunctionverificationResultInteger - Value can be one of certificate error codes from here. Apart from the certificate error codes, the following special codes can be used.0- Indicates success and disables Certificate Transparency verification.-2- Indicates failure.-3- Uses the verification result from chromium.
Sets the certificate verify proc for session, the proc will be called with
proc(request, callback) whenever a server certificate
verification is requested. Calling callback(0) accepts the certificate,
calling callback(-2) rejects it.
Calling setCertificateVerifyProc(null) will revert back to default certificate
verify proc.
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
win.webContents.session.setCertificateVerifyProc((request, callback) => {
const { hostname } = request
if (hostname === 'github.com') {
callback(0)
} else {
callback(-2)
}
})
ses.setPermissionRequestHandler(handler)
handlerFunction | nullwebContentsWebContents - WebContents requesting the permission. Please note that if the request comes from a subframe you should userequestingUrlto check the request origin.permissionString - Enum of 'media', 'geolocation', 'notifications', 'midiSysex', 'pointerLock', 'fullscreen', 'openExternal'.callbackFunctionpermissionGrantedBoolean - Allow or deny the permission.
detailsObject - Some properties are only available on certain permission types.externalURLString (optional) - The url of theopenExternalrequest.mediaTypesString[] (optional) - The types of media access being requested, elements can bevideooraudiorequestingUrlString - The last URL the requesting frame loadedisMainFrameBoolean - Whether the frame making the request is the main frame
Sets the handler which can be used to respond to permission requests for the session.
Calling callback(true) will allow the permission and callback(false) will reject it.
To clear the handler, call setPermissionRequestHandler(null).
const { session } = require('electron')
session.fromPartition('some-partition').setPermissionRequestHandler((webContents, permission, callback) => {
if (webContents.getURL() === 'some-host' && permission === 'notifications') {
return callback(false) // denied.
}
callback(true)
})
ses.setPermissionCheckHandler(handler)
handlerFunction| null webContentsWebContents - WebContents checking the permission. Please note that if the request comes from a subframe you should userequestingUrlto check the request origin.permissionString - Enum of 'media'.requestingOriginString - The origin URL of the permission checkdetailsObject - Some properties are only available on certain permission types.securityOriginString - The security orign of themediacheck.mediaTypeString - The type of media access being requested, can bevideo,audioorunknownrequestingUrlString - The last URL the requesting frame loadedisMainFrameBoolean - Whether the frame making the request is the main frame
Sets the handler which can be used to respond to permission checks for the session.
Returning true will allow the permission and false will reject it.
To clear the handler, call setPermissionCheckHandler(null).
const { session } = require('electron')
session.fromPartition('some-partition').setPermissionCheckHandler((webContents, permission) => {
if (webContents.getURL() === 'some-host' && permission === 'notifications') {
return false // denied
}
return true
})
ses.clearHostResolverCache()
Returns Promise<void> - Resolves when the operation is complete.
Clears the host resolver cache.
ses.allowNTLMCredentialsForDomains(domains)
domainsString - A comma-separated list of servers for which integrated authentication is enabled.
Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate authentication.
const { session } = require('electron')
// consider any url ending with `example.com`, `foobar.com`, `baz`
// for integrated authentication.
session.defaultSession.allowNTLMCredentialsForDomains('*example.com, *foobar.com, *baz')
// consider all urls for integrated authentication.
session.defaultSession.allowNTLMCredentialsForDomains('*')
ses.setUserAgent(userAgent[, acceptLanguages])
userAgentStringacceptLanguagesString (optional)
Overrides the userAgent and acceptLanguages for this session.
The acceptLanguages must a comma separated ordered list of language codes, for
example "en-US,fr,de,ko,zh-CN,ja".
This doesn't affect existing WebContents, and each WebContents can use
webContents.setUserAgent to override the session-wide user agent.
ses.isPersistent()
Returns Boolean - Whether or not this session is a persistent one. The default
webContents session of a BrowserWindow is persistent. When creating a session
from a partition, session prefixed with persist: will be persistent, while others
will be temporary.
ses.getUserAgent()
Returns String - The user agent for this session.
ses.getBlobData(identifier)
identifierString - Valid UUID.
Returns Promise<Buffer> - resolves with blob data.
ses.downloadURL(url)
urlString
Initiates a download of the resource at url.
The API will generate a DownloadItem that can be accessed
with the will-download event.
Note: This does not perform any security checks that relate to a page's origin,
unlike webContents.downloadURL.
ses.createInterruptedDownload(options)
optionsObjectpathString - Absolute path of the download.urlChainString[] - Complete URL chain for the download.mimeTypeString (optional)offsetInteger - Start range for the download.lengthInteger - Total length of the download.lastModifiedString (optional) - Last-Modified header value.eTagString (optional) - ETag header value.startTimeDouble (optional) - Time when download was started in number of seconds since UNIX epoch.
Allows resuming cancelled or interrupted downloads from previous Session.
The API will generate a DownloadItem that can be accessed with the will-download
event. The DownloadItem will not have any WebContents associated with it and
the initial state will be interrupted. The download will start only when the
resume API is called on the DownloadItem.
ses.clearAuthCache()
Returns Promise<void> - resolves when the session’s HTTP authentication cache has been cleared.
ses.setPreloads(preloads)
preloadsString[] - An array of absolute path to preload scripts
Adds scripts that will be executed on ALL web contents that are associated with
this session just before normal preload scripts run.
ses.getPreloads()
Returns String[] an array of paths to preload scripts that have been
registered.
ses.setSpellCheckerLanguages(languages)
languagesString[] - An array of language codes to enable the spellchecker for.
The built in spellchecker does not automatically detect what language a user is typing in. In order for the
spell checker to correctly check their words you must call this API with an array of language codes. You can
get the list of supported language codes with the ses.availableSpellCheckerLanguages property.
Note: On macOS the OS spellchecker is used and will detect your language automatically. This API is a no-op on macOS.
ses.getSpellCheckerLanguages()
Returns String[] - An array of language codes the spellchecker is enabled for. If this list is empty the spellchecker
will fallback to using en-US. By default on launch if this setting is an empty list Electron will try to populate this
setting with the current OS locale. This setting is persisted across restarts.
Note: On macOS the OS spellchecker is used and has it's own list of languages. This API is a no-op on macOS.
ses.setSpellCheckerDictionaryDownloadURL(url)
urlString - A base URL for Electron to download hunspell dictionaries from.
By default Electron will download hunspell dictionaries from the Chromium CDN. If you want to override this
behavior you can use this API to point the dictionary downloader at your own hosted version of the hunspell
dictionaries. We publish a hunspell_dictionaries.zip file with each release which contains the files you need
to host here, the file server must be case insensitive you must upload each file twice, once with the case it
has in the ZIP file and once with the filename as all lower case.
If the files present in hunspell_dictionaries.zip are available at https://example.com/dictionaries/language-code.bdic
then you should call this api with ses.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/'). Please
note the trailing slash. The URL to the dictionaries is formed as ${url}${filename}.
Note: On macOS the OS spellchecker is used and therefore we do not download any dictionary files. This API is a no-op on macOS.
ses.listWordsInSpellCheckerDictionary()
Returns Promise<String[]> - An array of all words in app's custom dictionary.
Resolves when the full dictionary is loaded from disk.
ses.addWordToSpellCheckerDictionary(word)
wordString - The word you want to add to the dictionary
Returns Boolean - Whether the word was successfully written to the custom dictionary. This API
will not work on non-persistent (in-memory) sessions.
Note: On macOS and Windows 10 this word will be written to the OS custom dictionary as well
ses.removeWordFromSpellCheckerDictionary(word)
wordString - The word you want to remove from the dictionary
Returns Boolean - Whether the word was successfully removed from the custom dictionary. This API
will not work on non-persistent (in-memory) sessions.
Note: On macOS and Windows 10 this word will be removed from the OS custom dictionary as well
ses.loadExtension(path)
pathString - Path to a directory containing an unpacked Chrome extension
Returns Promise<Extension> - resolves when the extension is loaded.
This method will raise an exception if the extension could not be loaded. If there are warnings when installing the extension (e.g. if the extension requests an API that Electron does not support) then they will be logged to the console.
Note that Electron does not support the full range of Chrome extensions APIs. See Supported Extensions APIs for more details on what is supported.
Note that in previous versions of Electron, extensions that were loaded would
be remembered for future runs of the application. This is no longer the case:
loadExtension must be called on every boot of your app if you want the
extension to be loaded.
const { app, session } = require('electron')
const path = require('path')
app.on('ready', async () => {
await session.defaultSession.loadExtension(path.join(__dirname, 'react-devtools'))
// Note that in order to use the React DevTools extension, you'll need to
// download and unzip a copy of the extension.
})
This API does not support loading packed (.crx) extensions.
Note: This API cannot be called before the ready event of the app module
is emitted.
Note: Loading extensions into in-memory (non-persistent) sessions is not supported and will throw an error.
ses.removeExtension(extensionId)
extensionIdString - ID of extension to remove
Unloads an extension.
Note: This API cannot be called before the ready event of the app module
is emitted.
ses.getExtension(extensionId)
extensionIdString - ID of extension to query
Returns Extension | null - The loaded extension with the given ID.
Note: This API cannot be called before the ready event of the app module
is emitted.
ses.getAllExtensions()
Returns Extension[] - A list of all loaded extensions.
Note: This API cannot be called before the ready event of the app module
is emitted.
Instance Properties
The following properties are available on instances of Session:
ses.availableSpellCheckerLanguages Readonly
A String[] array which consists of all the known available spell checker languages. Providing a language
code to the setSpellCheckerLanaguages API that isn't in this array will result in an error.
ses.cookies Readonly
A Cookies object for this session.
ses.serviceWorkers Readonly
A ServiceWorkers object for this session.
ses.webRequest Readonly
A WebRequest object for this session.
ses.protocol Readonly
A Protocol object for this session.
const { app, session } = require('electron')
const path = require('path')
app.whenReady().then(() => {
const protocol = session.fromPartition('some-partition').protocol
protocol.registerFileProtocol('atom', (request, callback) => {
let url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) })
}, (error) => {
if (error) console.error('Failed to register protocol')
})
})
ses.netLog Readonly
A NetLog object for this session.
const { app, session } = require('electron')
app.whenReady().then(async () => {
const netLog = session.fromPartition('some-partition').netLog
netLog.startLogging('/path/to/net-log')
// After some network events
const path = await netLog.stopLogging()
console.log('Net-logs written to', path)
})
Setting Up Symbol Server in Debugger
Debug symbols allow you to have better debugging sessions. They have information about the functions contained in executables and dynamic libraries and provide you with information to get clean call stacks. A Symbol Server allows the debugger to load the correct symbols, binaries and sources automatically without forcing users to download large debugging files. The server functions like Microsoft's symbol server so the documentation there can be useful.
Note that because released Electron builds are heavily optimized, debugging is not always easy. 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. The only workaround is to build an unoptimized local build.
The official symbol server URL for Electron is
https://symbols.electronjs.org.
You cannot visit this URL directly, you must add it to the symbol path of your
debugging tool. In the examples below, a local cache directory is used to avoid
repeatedly fetching the PDB from the server. Replace c:\code\symbols with an
appropriate cache directory on your machine.
Using the Symbol Server in Windbg
The Windbg symbol path is configured with a string value delimited with asterisk
characters. To use only the Electron symbol server, add the following entry to
your symbol path (Note: you can replace c:\code\symbols with any writable
directory on your computer, if you'd prefer a different location for downloaded
symbols):
SRV*c:\code\symbols\*https://symbols.electronjs.org
Set this string as _NT_SYMBOL_PATH in the environment, using the Windbg menus,
or by typing the .sympath command. If you would like to get symbols from
Microsoft's symbol server as well, you should list that first:
SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\symbols\*https://symbols.electronjs.org
Troubleshooting: Symbols will not load
Type the following commands in Windbg to print why symbols are not loading:
> !sym noisy
> .reload /f electron.exe
SharedWorkerInfo Object
idString - The unique id of the shared worker.urlString - The url of the shared worker.
shell
Manage files and URLs using their default applications.
Process: Main, Renderer (non-sandboxed only)
The shell module provides functions related to desktop integration.
An example of opening a URL in the user's default browser:
const { shell } = require('electron')
shell.openExternal('https://github.com')
Note: While the shell module can be used in the renderer process, it will not function in a sandboxed renderer.
Methods
The shell module has the following methods:
shell.showItemInFolder(fullPath)
fullPathString
Show the given file in a file manager. If possible, select the file.
shell.openPath(path)
pathString
Returns Promise<String> - Resolves with an string containing the error message corresponding to the failure if a failure occurred, otherwise "".
Open the given file in the desktop's default manner.
shell.openExternal(url[, options])
urlString - Max 2081 characters on windows.optionsObject (optional)activateBoolean (optional) macOS -trueto bring the opened application to the foreground. The default istrue.workingDirectoryString (optional) Windows - The working directory.
Returns Promise<void>
Open the given external protocol URL in the desktop's default manner. (For example, mailto: URLs in the user's default mail agent).
shell.moveItemToTrash(fullPath[, deleteOnFail])
fullPathStringdeleteOnFailBoolean (optional) - Whether or not to unilaterally remove the item if the Trash is disabled or unsupported on the volume. macOS
Returns Boolean - Whether the item was successfully moved to the trash or otherwise deleted.
Move the given file to trash and returns a boolean status for the operation.
shell.beep()
Play the beep sound.
shell.writeShortcutLink(shortcutPath[, operation], options) Windows
shortcutPathStringoperationString (optional) - Default iscreate, can be one of following:create- Creates a new shortcut, overwriting if necessary.update- Updates specified properties only on an existing shortcut.replace- Overwrites an existing shortcut, fails if the shortcut doesn't exist.
optionsShortcutDetails
Returns Boolean - Whether the shortcut was created successfully.
Creates or updates a shortcut link at shortcutPath.
shell.readShortcutLink(shortcutPath) Windows
shortcutPathString
Returns ShortcutDetails
Resolves the shortcut link at shortcutPath.
An exception will be thrown when any error happens.
ShortcutDetails Object
targetString - The target to launch from this shortcut.cwdString (optional) - The working directory. Default is empty.argsString (optional) - The arguments to be applied totargetwhen launching from this shortcut. Default is empty.descriptionString (optional) - The description of the shortcut. Default is empty.iconString (optional) - The path to the icon, can be a DLL or EXE.iconandiconIndexhave to be set together. Default is empty, which uses the target's icon.iconIndexNumber (optional) - The resource ID of icon wheniconis a DLL or EXE. Default is 0.appUserModelIdString (optional) - The Application User Model ID. Default is empty.
Size Object
widthNumberheightNumber
Snapcraft Guide (Ubuntu Software Center & More)
This guide provides information on how to package your Electron application for any Snapcraft environment, including the Ubuntu Software Center.
Background and Requirements
Together with the broader Linux community, Canonical aims to fix many of the
common software installation problems with the snapcraft
project. Snaps are containerized software packages that include required
dependencies, auto-update, and work on all major Linux distributions without
system modification.
There are three ways to create a .snap file:
1) Using electron-forge or
electron-builder, both tools that come with snap
support out of the box. This is the easiest option.
2) Using electron-installer-snap, which takes electron-packager's output.
3) Using an already created .deb package.
In some cases, you will need to have the snapcraft tool installed.
Instructions to install snapcraft for your particular distribution are
available here.
Using electron-installer-snap
The module works like electron-winstaller and similar
modules in that its scope is limited to building snap packages. You can install
it with:
npm install --save-dev electron-installer-snap
Step 1: Package Your Electron Application
Package the application using electron-packager (or a
similar tool). Make sure to remove node_modules that you don't need in your
final application, since any module you don't actually need will increase
your application's size.
The output should look roughly like this:
.
└── dist
└── app-linux-x64
├── LICENSE
├── LICENSES.chromium.html
├── content_shell.pak
├── app
├── icudtl.dat
├── libgcrypt.so.11
├── libnode.so
├── locales
├── resources
├── v8_context_snapshot.bin
└── version
Step 2: Running electron-installer-snap
From a terminal that has snapcraft in its PATH, run electron-installer-snap
with the only required parameter --src, which is the location of your packaged
Electron application created in the first step.
npx electron-installer-snap --src=out/myappname-linux-x64
If you have an existing build pipeline, you can use electron-installer-snap
programmatically. For more information, see the Snapcraft API docs.
const snap = require('electron-installer-snap')
snap(options)
.then(snapPath => console.log(`Created snap at ${snapPath}!`))
Using an Existing Debian Package
Snapcraft is capable of taking an existing .deb file and turning it into
a .snap file. The creation of a snap is configured using a snapcraft.yaml
file that describes the sources, dependencies, description, and other core
building blocks.
Step 1: Create a Debian Package
If you do not already have a .deb package, using electron-installer-snap
might be an easier path to create snap packages. However, multiple solutions
for creating Debian packages exist, including electron-forge,
electron-builder or
electron-installer-debian.
Step 2: Create a snapcraft.yaml
For more information on the available configuration options, see the documentation on the snapcraft syntax. Let's look at an example:
name: myApp
version: '2.0.0'
summary: A little description for the app.
description: |
You know what? This app is amazing! It does all the things
for you. Some say it keeps you young, maybe even happy.
grade: stable
confinement: classic
parts:
slack:
plugin: dump
source: my-deb.deb
source-type: deb
after:
- desktop-gtk3
stage-packages:
- libasound2
- libnotify4
- libnspr4
- libnss3
- libpcre3
- libpulse0
- libxss1
- libxtst6
electron-launch:
plugin: dump
source: files/
prepare: |
chmod +x bin/electron-launch
apps:
myApp:
command: bin/electron-launch $SNAP/usr/lib/myApp/myApp
desktop: usr/share/applications/myApp.desktop
# Correct the TMPDIR path for Chromium Framework/Electron to ensure
# libappindicator has readable resources.
environment:
TMPDIR: $XDG_RUNTIME_DIR
As you can see, the snapcraft.yaml instructs the system to launch a file
called electron-launch. In this example, it passes information on to the
app's binary:
#!/bin/sh
exec "$@" --executed-from="$(pwd)" --pid=$$ > /dev/null 2>&1 &
Alternatively, if you're building your snap with strict confinement, you
can use the desktop-launch command:
apps:
myApp:
# Correct the TMPDIR path for Chromium Framework/Electron to ensure
# libappindicator has readable resources.
command: env TMPDIR=$XDG_RUNTIME_DIR PATH=/usr/local/bin:${PATH} ${SNAP}/bin/desktop-launch $SNAP/myApp/desktop
desktop: usr/share/applications/desktop.desktop
Source Code Directory Structure
The source code of Electron is separated into a few parts, mostly following Chromium on the separation conventions.
You may need to become familiar with Chromium's multi-process architecture to understand the source code better.
Structure of Source Code
Electron
├── build/ - Build configuration files needed to build with GN.
├── buildflags/ - Determines the set of features that can be conditionally built.
├── chromium_src/ - Source code copied from Chromium that isn't part of the content layer.
├── default_app/ - A default app run when Electron is started without
| providing a consumer app.
├── docs/ - Electron's documentation.
| ├── api/ - Documentation for Electron's externally-facing modules and APIs.
| ├── development/ - Documentation to aid in developing for and with Electron.
| ├── fiddles/ - A set of code snippets one can run in Electron Fiddle.
| ├── images/ - Images used in documentation.
| └── tutorial/ - Tutorial documents for various aspects of Electron.
├── lib/ - JavaScript/TypeScript source code.
| ├── browser/ - Main process initialization code.
| | ├── api/ - API implementation for main process modules.
| | └── remote/ - Code related to the remote module as it is
| | used in the main process.
| ├── common/ - Relating to logic needed by both main and renderer processes.
| | └── api/ - API implementation for modules that can be used in
| | both the main and renderer processes
| ├── isolated_renderer/ - Handles creation of isolated renderer processes when
| | contextIsolation is enabled.
| ├── renderer/ - Renderer process initialization code.
| | ├── api/ - API implementation for renderer process modules.
| | ├── extension/ - Code related to use of Chrome Extensions
| | | in Electron's renderer process.
| | ├── remote/ - Logic that handles use of the remote module in
| | | the main process.
| | └── web-view/ - Logic that handles the use of webviews in the
| | renderer process.
| ├── sandboxed_renderer/ - Logic that handles creation of sandboxed renderer
| | | processes.
| | └── api/ - API implementation for sandboxed renderer processes.
| └── worker/ - Logic that handles proper functionality of Node.js
| environments in Web Workers.
├── patches/ - Patches applied on top of Electron's core dependencies
| | in order to handle differences between our use cases and
| | default functionality.
| ├── boringssl/ - Patches applied to Google's fork of OpenSSL, BoringSSL.
| ├── chromium/ - Patches applied to Chromium.
| ├── node/ - Patches applied on top of Node.js.
| └── v8/ - Patches applied on top of Google's V8 engine.
├── shell/ - C++ source code.
| ├── app/ - System entry code.
| ├── browser/ - The frontend including the main window, UI, and all of the
| | | main process things. This talks to the renderer to manage web
| | | pages.
| | ├── ui/ - Implementation of UI stuff for different platforms.
| | | ├── cocoa/ - Cocoa specific source code.
| | | ├── win/ - Windows GUI specific source code.
| | | └── x/ - X11 specific source code.
| | ├── api/ - The implementation of the main process APIs.
| | ├── net/ - Network related code.
| | ├── mac/ - Mac specific Objective-C source code.
| | └── resources/ - Icons, platform-dependent files, etc.
| ├── renderer/ - Code that runs in renderer process.
| | └── api/ - The implementation of renderer process APIs.
| └── common/ - Code that used by both the main and renderer processes,
| | including some utility functions and code to integrate node's
| | message loop into Chromium's message loop.
| └── api/ - The implementation of common APIs, and foundations of
| Electron's built-in modules.
├── spec/ - Components of Electron's test suite run in the renderer process.
├── spec-main/ - Components of Electron's test suite run in the main process.
└── BUILD.gn - Building rules of Electron.
Structure of Other Directories
- .circleci - Config file for CI with CircleCI.
- .github - GitHub-specific config files including issues templates and CODEOWNERS.
- dist - Temporary directory created by
script/create-dist.pyscript when creating a distribution. - external_binaries - Downloaded binaries of third-party frameworks which
do not support building with
gn. - node_modules - Third party node modules used for building.
- npm - Logic for installation of Electron via npm.
- out - Temporary output directory of
ninja. - script - Scripts used for development purpose like building, packaging, testing, etc.
script/ - The set of all scripts Electron runs for a variety of purposes.
├── codesign/ - Fakes codesigning for Electron apps; used for testing.
├── lib/ - Miscellaneous python utility scripts.
└── release/ - Scripts run during Electron's release process.
├── notes/ - Generates release notes for new Electron versions.
└── uploaders/ - Uploads various release-related files during release.
- tools - Helper scripts used by GN files.
- Scripts put here should never be invoked by users directly, unlike those in
script.
- Scripts put here should never be invoked by users directly, unlike those in
- typings - TypeScript typings for Electron's internal code.
- vendor - Source code for some third party dependencies.
SpellChecker
Electron has built-in support for Chromium's spellchecker since Electron 8. On Windows and Linux this is powered by Hunspell dictionaries, and on macOS it makes use of the native spellchecker APIs.
How to enable the spellchecker?
For Electron 9 and higher the spellchecker is enabled by default. For Electron 8 you need to enable it in webPreferences.
const myWindow = new BrowserWindow({
webPreferences: {
spellcheck: true
}
})
How to set the languages the spellchecker uses?
On macOS as we use the native APIs there is no way to set the language that the spellchecker uses. By default on macOS the native spellchecker will automatically detect the language being used for you.
For Windows and Linux there are a few Electron APIs you should use to set the languages for the spellchecker.
// Sets the spellchecker to check English US and French
myWindow.session.setSpellCheckerLanguages(['en-US', 'fr'])
// An array of all available language codes
const possibleLanguages = myWindow.session.availableSpellCheckerLanguages
By default the spellchecker will enable the language matching the current OS locale.
How do I put the results of the spellchecker in my context menu?
All the required information to generate a context menu is provided in the context-menu event on each webContents instance. A small example
of how to make a context menu with this information is provided below.
const { Menu, MenuItem } = require('electron')
myWindow.webContents.on('context-menu', (event, params) => {
const menu = new Menu()
// Add each spelling suggestion
for (const suggestion of params.dictionarySuggestions) {
menu.append(new MenuItem({
label: suggestion,
click: () => mainWindow.webContents.replaceMisspelling(suggestion)
}))
}
// Allow users to add the misspelled word to the dictionary
if (params.misspelledWord) {
menu.append(
new MenuItem({
label: 'Add to dictionary',
click: () => mainWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
})
)
}
menu.popup()
})
Does the spellchecker use any Google services?
Although the spellchecker itself does not send any typings, words or user input to Google services the hunspell dictionary files are downloaded from a Google CDN by default. If you want to avoid this you can provide an alternative URL to download the dictionaries from.
myWindow.session.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')
Check out the docs for session.setSpellCheckerDictionaryDownloadURL for more information on where to get the dictionary files from and how you need to host them.
Electron Documentation Style Guide
These are the guidelines for writing Electron documentation.
Titles
- Each page must have a single
#-level title at the top. - Chapters in the same page must have
##-level titles. - Sub-chapters need to increase the number of
#in the title according to their nesting depth. - All words in the page's title must be capitalized, except for conjunctions like "of" and "and" .
- Only the first word of a chapter title must be capitalized.
Using Quick Start as example:
# Quick Start
...
## Main process
...
## Renderer process
...
## Run your app
...
### Run as a distribution
...
### Manually downloaded Electron binary
...
For API references, there are exceptions to this rule.
Markdown rules
- Use
shinstead ofcmdin code blocks (due to the syntax highlighter). - Lines should be wrapped at 80 columns.
- No nesting lists more than 2 levels (due to the markdown renderer).
- All
jsandjavascriptcode blocks are linted with standard-markdown.
Picking words
- Use "will" over "would" when describing outcomes.
- Prefer "in the ___ process" over "on".
API references
The following rules only apply to the documentation of APIs.
Page title
Each page must use the actual object name returned by require('electron')
as the title, such as BrowserWindow, autoUpdater, and session.
Under the page title must be a one-line description starting with >.
Using session as example:
# session
> Manage browser sessions, cookies, cache, proxy settings, etc.
Module methods and events
For modules that are not classes, their methods and events must be listed under
the ## Methods and ## Events chapters.
Using autoUpdater as an example:
# autoUpdater
## Events
### Event: 'error'
## Methods
### `autoUpdater.setFeedURL(url[, requestHeaders])`
Classes
- API classes or classes that are part of modules must be listed under a
## Class: TheClassNamechapter. - One page can have multiple classes.
- Constructors must be listed with
###-level titles. - Static Methods must be listed under a
### Static Methodschapter. - Instance Methods must be listed under an
### Instance Methodschapter. - All methods that have a return value must start their description with "Returns
[TYPE]- Return description"- If the method returns an
Object, its structure can be specified using a colon followed by a newline then an unordered list of properties in the same style as function parameters.
- If the method returns an
- Instance Events must be listed under an
### Instance Eventschapter. - Instance Properties must be listed under an
### Instance Propertieschapter.- Instance properties must start with "A [Property Type] ..."
Using the Session and Cookies classes as an example:
# session
## Methods
### session.fromPartition(partition)
## Static Properties
### session.defaultSession
## Class: Session
### Instance Events
#### Event: 'will-download'
### Instance Methods
#### `ses.getCacheSize()`
### Instance Properties
#### `ses.cookies`
## Class: Cookies
### Instance Methods
#### `cookies.get(filter, callback)`
Methods
The methods chapter must be in the following form:
### `objectName.methodName(required[, optional]))`
* `required` String - A parameter description.
* `optional` Integer (optional) - Another parameter description.
...
The title can be ### or ####-levels depending on whether it is a method of
a module or a class.
For modules, the objectName is the module's name. For classes, it must be the
name of the instance of the class, and must not be the same as the module's
name.
For example, the methods of the Session class under the session module must
use ses as the objectName.
The optional arguments are notated by square brackets [] surrounding the optional argument
as well as the comma required if this optional argument follows another
argument:
required[, optional]
Below the method is more detailed information on each of the arguments. The type of argument is notated by either the common types:
If an argument or a method is unique to certain platforms, those platforms are
denoted using a space-delimited italicized list following the datatype. Values
can be macOS, Windows or Linux.
* `animate` Boolean (optional) _macOS_ _Windows_ - Animate the thing.
Array type arguments must specify what elements the array may include in
the description below.
The description for Function type arguments should make it clear how it may be
called and list the types of the parameters that will be passed to it.
Events
The events chapter must be in following form:
### Event: 'wake-up'
Returns:
* `time` String
...
The title can be ### or ####-levels depending on whether it is an event of
a module or a class.
The arguments of an event follow the same rules as methods.
Properties
The properties chapter must be in following form:
### session.defaultSession
...
The title can be ### or ####-levels depending on whether it is a property of
a module or a class.
Finding Support
If you have a security concern, please see the security document.
If you're looking for programming help, for answers to questions, or to join in discussion with other developers who use Electron, you can interact with the community in these locations:
Electron's Discordhas channels for:- Getting help
- Ecosystem apps like Electron Forge and Electron Fiddle
- Sharing ideas with other Electron app developers
- And more!
electroncategory on the Atom forums#atom-shellchannel on Freenode#electronchannel on Atom's Slackelectron-ru(Russian)electron-br(Brazilian Portuguese)electron-kr(Korean)electron-jp(Japanese)electron-tr(Turkish)electron-id(Indonesia)electron-pl(Poland)
If you'd like to contribute to Electron, see the contributing document.
If you've found a bug in a supported version of Electron, please report it with the issue tracker.
awesome-electron is a community-maintained list of useful example apps, tools and resources.
Supported Versions
The latest three stable major versions are supported by the Electron team. For example, if the latest release is 6.1.x, then the 5.0.x as well as the 4.2.x series are supported. We only support the latest minor release for each stable release series. This means that in the case of a security fix 6.1.x will receive the fix, but we will not release a new version of 6.0.x.
The latest stable release unilaterally receives all fixes from master,
and the version prior to that receives the vast majority of those fixes
as time and bandwidth warrants. The oldest supported release line will receive
only security fixes directly.
All supported release lines will accept external pull requests to backport
fixes previously merged to master, though this may be on a case-by-case
basis for some older supported lines. All contested decisions around release
line backports will be resolved by the Releases Working Group as an agenda item at their weekly meeting the week the backport PR is raised.
When an API is changed or removed in a way that breaks existing functionality, the previous functionality will be supported for a minimum of two major versions when possible before being removed. For example, if a function takes three arguments, and that number is reduced to two in major version 10, the three-argument version would continue to work until, at minimum, major version 12. Past the minimum two-version threshold, we will attempt to support backwards compatibility beyond two versions until the maintainers feel the maintenance burden is too high to continue doing so.
Currently supported versions
- 10.x.y
- 9.x.y
- 8.x.y
End-of-life
When a release branch reaches the end of its support cycle, the series will be deprecated in NPM and a final end-of-support release will be made. This release will add a warning to inform that an unsupported version of Electron is in use.
These steps are to help app developers learn when a branch they're using becomes unsupported, but without being excessively intrusive to end users.
If an application has exceptional circumstances and needs to stay
on an unsupported series of Electron, developers can silence the
end-of-support warning by omitting the final release from the app's
package.json devDependencies. For example, since the 1-6-x series
ended with an end-of-support 1.6.18 release, developers could choose
to stay in the 1-6-x series without warnings with devDependency of
"electron": 1.6.0 - 1.6.17.
Supported Platforms
Following platforms are supported by Electron:
macOS
Only 64bit binaries are provided for macOS, and the minimum macOS version supported is macOS 10.10 (Yosemite).
Windows
Windows 7 and later are supported, older operating systems are not supported (and do not work).
Both ia32 (x86) and x64 (amd64) binaries are provided for Windows.
Electron 6.0.8 and later add native support for Windows on Arm (arm64) devices.
Running apps packaged with previous versions is possible using the ia32 binary.
Linux
The prebuilt ia32 (i686) and x64 (amd64) binaries of Electron are built on
Ubuntu 12.04, the armv7l binary is built against ARM v7 with hard-float ABI and
NEON for Debian Wheezy.
Until the release of Electron 2.0, Electron will also
continue to release the armv7l binary with a simple arm suffix. Both binaries
are identical.
Whether the prebuilt binary can run on a distribution depends on whether the distribution includes the libraries that Electron is linked to on the building platform, so only Ubuntu 12.04 is guaranteed to work, but following platforms are also verified to be able to run the prebuilt binaries of Electron:
- Ubuntu 12.04 and newer
- Fedora 21
- Debian 8
Synopsis
How to use Node.js and Electron APIs.
All of Node.js's built-in modules are available in Electron and third-party node modules also fully supported as well (including the native modules).
Electron also provides some extra built-in modules for developing native desktop applications. Some modules are only available in the main process, some are only available in the renderer process (web page), and some can be used in both processes.
The basic rule is: if a module is GUI or low-level system related, then it should be only available in the main process. You need to be familiar with the concept of main process vs. renderer process scripts to be able to use those modules.
The main process script is like a normal Node.js script:
const { app, BrowserWindow } = require('electron')
let win = null
app.whenReady().then(() => {
win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')
})
The renderer process is no different than a normal web page, except for the extra ability to use node modules:
<!DOCTYPE html>
<html>
<body>
<script>
const { app } = require('electron').remote
console.log(app.getVersion())
</script>
</body>
</html>
To run your app, read Run your app.
Destructuring assignment
As of 0.37, you can use destructuring assignment to make it easier to use built-in modules.
const { app, BrowserWindow } = require('electron')
let win
app.whenReady().then(() => {
win = new BrowserWindow()
win.loadURL('https://github.com')
})
If you need the entire electron module, you can require it and then using
destructuring to access the individual modules from electron.
const electron = require('electron')
const { app, BrowserWindow } = electron
let win
app.whenReady().then(() => {
win = new BrowserWindow()
win.loadURL('https://github.com')
})
This is equivalent to the following code:
const electron = require('electron')
const app = electron.app
const BrowserWindow = electron.BrowserWindow
let win
app.whenReady().then(() => {
win = new BrowserWindow()
win.loadURL('https://github.com')
})
systemPreferences
Get system preferences.
Process: Main
const { systemPreferences } = require('electron')
console.log(systemPreferences.isDarkMode())
Events
The systemPreferences object emits the following events:
Event: 'accent-color-changed' Windows
Returns:
eventEventnewColorString - The new RGBA color the user assigned to be their system accent color.
Event: 'inverted-color-scheme-changed' Windows Deprecated
Returns:
eventEventinvertedColorSchemeBoolean -trueif an inverted color scheme (a high contrast color scheme with light text and dark backgrounds) is being used,falseotherwise.
Deprecated: Should use the new updated event on the nativeTheme module.
Event: 'high-contrast-color-scheme-changed' Windows Deprecated
Returns:
eventEventhighContrastColorSchemeBoolean -trueif a high contrast theme is being used,falseotherwise.
Deprecated: Should use the new updated event on the nativeTheme module.
systemPreferences.isDarkMode() macOS Windows Deprecated
Returns Boolean - Whether the system is in Dark Mode.
Note: On macOS 10.15 Catalina in order for this API to return the correct value when in the "automatic" dark mode setting you must either have NSRequiresAquaSystemAppearance=false in your Info.plist or be on Electron >=7.0.0. See the dark mode guide for more information.
Deprecated: Should use the new nativeTheme.shouldUseDarkColors API.
systemPreferences.isSwipeTrackingFromScrollEventsEnabled() macOS
Returns Boolean - Whether the Swipe between pages setting is on.
systemPreferences.postNotification(event, userInfo[, deliverImmediately]) macOS
eventStringuserInfoRecord<String, any>deliverImmediatelyBoolean (optional) -trueto post notifications immediately even when the subscribing app is inactive.
Posts event as native notifications of macOS. The userInfo is an Object
that contains the user information dictionary sent along with the notification.
systemPreferences.postLocalNotification(event, userInfo) macOS
eventStringuserInfoRecord<String, any>
Posts event as native notifications of macOS. The userInfo is an Object
that contains the user information dictionary sent along with the notification.
systemPreferences.postWorkspaceNotification(event, userInfo) macOS
eventStringuserInfoRecord<String, any>
Posts event as native notifications of macOS. The userInfo is an Object
that contains the user information dictionary sent along with the notification.
systemPreferences.subscribeNotification(event, callback) macOS
eventStringcallbackFunctioneventStringuserInfoRecord<String, unknown>objectString
Returns Number - The ID of this subscription
Subscribes to native notifications of macOS, callback will be called with
callback(event, userInfo) when the corresponding event happens. The
userInfo is an Object that contains the user information dictionary sent
along with the notification. The object is the sender of the notification,
and only supports NSString values for now.
The id of the subscriber is returned, which can be used to unsubscribe the
event.
Under the hood this API subscribes to NSDistributedNotificationCenter,
example values of event are:
AppleInterfaceThemeChangedNotificationAppleAquaColorVariantChangedAppleColorPreferencesChangedNotificationAppleShowScrollBarsSettingChanged
systemPreferences.subscribeLocalNotification(event, callback) macOS
eventStringcallbackFunctioneventStringuserInfoRecord<String, unknown>objectString
Returns Number - The ID of this subscription
Same as subscribeNotification, but uses NSNotificationCenter for local defaults.
This is necessary for events such as NSUserDefaultsDidChangeNotification.
systemPreferences.subscribeWorkspaceNotification(event, callback) macOS
eventStringcallbackFunctioneventStringuserInfoRecord<String, unknown>objectString
Same as subscribeNotification, but uses NSWorkspace.sharedWorkspace.notificationCenter.
This is necessary for events such as NSWorkspaceDidActivateApplicationNotification.
systemPreferences.unsubscribeLocalNotification(id) macOS
idInteger
Same as unsubscribeNotification, but removes the subscriber from NSNotificationCenter.
systemPreferences.unsubscribeWorkspaceNotification(id) macOS
idInteger
Same as unsubscribeNotification, but removes the subscriber from NSWorkspace.sharedWorkspace.notificationCenter.
systemPreferences.registerDefaults(defaults) macOS
defaultsRecord<String, String | Boolean | Number> - a dictionary of (key: value) user defaults
Add the specified defaults to your application's NSUserDefaults.
systemPreferences.getUserDefault(key, type) macOS
keyStringtypeString - Can bestring,boolean,integer,float,double,url,arrayordictionary.
Returns any - The value of key in NSUserDefaults.
Some popular key and types are:
AppleInterfaceStyle:stringAppleAquaColorVariant:integerAppleHighlightColor:stringAppleShowScrollBars:stringNSNavRecentPlaces:arrayNSPreferredWebServices:dictionaryNSUserDictionaryReplacementItems:array
systemPreferences.setUserDefault(key, type, value) macOS
keyStringtypeString - Can bestring,boolean,integer,float,double,url,arrayordictionary.valueString
Set the value of key in NSUserDefaults.
Note that type should match actual type of value. An exception is thrown
if they don't.
Some popular key and types are:
ApplePressAndHoldEnabled:boolean
systemPreferences.removeUserDefault(key) macOS
keyString
Removes the key in NSUserDefaults. This can be used to restore the default
or global value of a key previously set with setUserDefault.
systemPreferences.isAeroGlassEnabled() Windows
Returns Boolean - true if DWM composition (Aero Glass) is
enabled, and false otherwise.
An example of using it to determine if you should create a transparent window or not (transparent windows won't work correctly when DWM composition is disabled):
const { BrowserWindow, systemPreferences } = require('electron')
let browserOptions = { width: 1000, height: 800 }
// Make the window transparent only if the platform supports it.
if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) {
browserOptions.transparent = true
browserOptions.frame = false
}
// Create the window.
let win = new BrowserWindow(browserOptions)
// Navigate.
if (browserOptions.transparent) {
win.loadURL(`file://${__dirname}/index.html`)
} else {
// No transparency, so we load a fallback that uses basic styles.
win.loadURL(`file://${__dirname}/fallback.html`)
}
systemPreferences.getAccentColor() Windows macOS
Returns String - The users current system wide accent color preference in RGBA
hexadecimal form.
const color = systemPreferences.getAccentColor() // `"aabbccdd"`
const red = color.substr(0, 2) // "aa"
const green = color.substr(2, 2) // "bb"
const blue = color.substr(4, 2) // "cc"
const alpha = color.substr(6, 2) // "dd"
This API is only available on macOS 10.14 Mojave or newer.
systemPreferences.getColor(color) Windows macOS
colorString - One of the following values:- On Windows:
3d-dark-shadow- Dark shadow for three-dimensional display elements.3d-face- Face color for three-dimensional display elements and for dialog box backgrounds.3d-highlight- Highlight color for three-dimensional display elements.3d-light- Light color for three-dimensional display elements.3d-shadow- Shadow color for three-dimensional display elements.active-border- Active window border.active-caption- Active window title bar. Specifies the left side color in the color gradient of an active window's title bar if the gradient effect is enabled.active-caption-gradient- Right side color in the color gradient of an active window's title bar.app-workspace- Background color of multiple document interface (MDI) applications.button-text- Text on push buttons.caption-text- Text in caption, size box, and scroll bar arrow box.desktop- Desktop background color.disabled-text- Grayed (disabled) text.highlight- Item(s) selected in a control.highlight-text- Text of item(s) selected in a control.hotlight- Color for a hyperlink or hot-tracked item.inactive-border- Inactive window border.inactive-caption- Inactive window caption. Specifies the left side color in the color gradient of an inactive window's title bar if the gradient effect is enabled.inactive-caption-gradient- Right side color in the color gradient of an inactive window's title bar.inactive-caption-text- Color of text in an inactive caption.info-background- Background color for tooltip controls.info-text- Text color for tooltip controls.menu- Menu background.menu-highlight- The color used to highlight menu items when the menu appears as a flat menu.menubar- The background color for the menu bar when menus appear as flat menus.menu-text- Text in menus.scrollbar- Scroll bar gray area.window- Window background.window-frame- Window frame.window-text- Text in windows.
- On macOS
alternate-selected-control-text- The text on a selected surface in a list or table. deprecatedcontrol-background- The background of a large interface element, such as a browser or table.control- The surface of a control.control-text-The text of a control that isn’t disabled.disabled-control-text- The text of a control that’s disabled.find-highlight- The color of a find indicator.grid- The gridlines of an interface element such as a table.header-text- The text of a header cell in a table.highlight- The virtual light source onscreen.keyboard-focus-indicator- The ring that appears around the currently focused control when using the keyboard for interface navigation.label- The text of a label containing primary content.link- A link to other content.placeholder-text- A placeholder string in a control or text view.quaternary-label- The text of a label of lesser importance than a tertiary label such as watermark text.scrubber-textured-background- The background of a scrubber in the Touch Bar.secondary-label- The text of a label of lesser importance than a normal label such as a label used to represent a subheading or additional information.selected-content-background- The background for selected content in a key window or view.selected-control- The surface of a selected control.selected-control-text- The text of a selected control.selected-menu-item-text- The text of a selected menu.selected-text-background- The background of selected text.selected-text- Selected text.separator- A separator between different sections of content.shadow- The virtual shadow cast by a raised object onscreen.tertiary-label- The text of a label of lesser importance than a secondary label such as a label used to represent disabled text.text-background- Text background.text- The text in a document.under-page-background- The background behind a document's content.unemphasized-selected-content-background- The selected content in a non-key window or view.unemphasized-selected-text-background- A background for selected text in a non-key window or view.unemphasized-selected-text- Selected text in a non-key window or view.window-background- The background of a window.window-frame-text- The text in the window's titlebar area.
- On Windows:
Returns String - The system color setting in RGB hexadecimal form (#ABCDEF).
See the Windows docs and the macOS docs for more details.
The following colors are only available on macOS 10.14: find-highlight, selected-content-background, separator, unemphasized-selected-content-background, unemphasized-selected-text-background, and unemphasized-selected-text.
systemPreferences.getSystemColor(color) macOS
colorString - One of the following values:bluebrowngraygreenorangepinkpurpleredyellow
Returns String - The standard system color formatted as #RRGGBBAA.
Returns one of several standard system colors that automatically adapt to vibrancy and changes in accessibility settings like 'Increase contrast' and 'Reduce transparency'. See Apple Documentation for more details.
systemPreferences.isInvertedColorScheme() Windows Deprecated
Returns Boolean - true if an inverted color scheme (a high contrast color scheme with light text and dark backgrounds) is active, false otherwise.
Deprecated: Should use the new nativeTheme.shouldUseInvertedColorScheme API.
systemPreferences.isHighContrastColorScheme() macOS Windows Deprecated
Returns Boolean - true if a high contrast theme is active, false otherwise.
Deprecated: Should use the new nativeTheme.shouldUseHighContrastColors API.
systemPreferences.getEffectiveAppearance() macOS
Returns String - Can be dark, light or unknown.
Gets the macOS appearance setting that is currently applied to your application, maps to NSApplication.effectiveAppearance
systemPreferences.getAppLevelAppearance() macOS Deprecated
Returns String | null - Can be dark, light or unknown.
Gets the macOS appearance setting that you have declared you want for
your application, maps to NSApplication.appearance.
You can use the setAppLevelAppearance API to set this value.
systemPreferences.setAppLevelAppearance(appearance) macOS Deprecated
appearanceString | null - Can bedarkorlight
Sets the appearance setting for your application, this should override the
system default and override the value of getEffectiveAppearance.
systemPreferences.canPromptTouchID() macOS
Returns Boolean - whether or not this device has the ability to use Touch ID.
NOTE: This API will return false on macOS systems older than Sierra 10.12.2.
systemPreferences.promptTouchID(reason) macOS
reasonString - The reason you are asking for Touch ID authentication
Returns Promise<void> - resolves if the user has successfully authenticated with Touch ID.
const { systemPreferences } = require('electron')
systemPreferences.promptTouchID('To get consent for a Security-Gated Thing').then(success => {
console.log('You have successfully authenticated with Touch ID!')
}).catch(err => {
console.log(err)
})
This API itself will not protect your user data; rather, it is a mechanism to allow you to do so. Native apps will need to set Access Control Constants like kSecAccessControlUserPresence on the their keychain entry so that reading it would auto-prompt for Touch ID biometric consent. This could be done with node-keytar, such that one would store an encryption key with node-keytar and only fetch it if promptTouchID() resolves.
NOTE: This API will return a rejected Promise on macOS systems older than Sierra 10.12.2.
systemPreferences.isTrustedAccessibilityClient(prompt) macOS
promptBoolean - whether or not the user will be informed via prompt if the current process is untrusted.
Returns Boolean - true if the current process is a trusted accessibility client and false if it is not.
systemPreferences.getMediaAccessStatus(mediaType) Windows macOS
mediaTypeString - Can bemicrophone,cameraorscreen.
Returns String - Can be not-determined, granted, denied, restricted or unknown.
This user consent was not required on macOS 10.13 High Sierra or lower so this method will always return granted.
macOS 10.14 Mojave or higher requires consent for microphone and camera access.
macOS 10.15 Catalina or higher requires consent for screen access.
Windows 10 has a global setting controlling microphone and camera access for all win32 applications.
It will always return granted for screen and for all media types on older versions of Windows.
systemPreferences.askForMediaAccess(mediaType) macOS
mediaTypeString - the type of media being requested; can bemicrophone,camera.
Returns Promise<Boolean> - A promise that resolves with true if consent was granted and false if it was denied. If an invalid mediaType is passed, the promise will be rejected. If an access request was denied and later is changed through the System Preferences pane, a restart of the app will be required for the new permissions to take effect. If access has already been requested and denied, it must be changed through the preference pane; an alert will not pop up and the promise will resolve with the existing access status.
Important: In order to properly leverage this API, you must set the NSMicrophoneUsageDescription and NSCameraUsageDescription strings in your app's Info.plist file. The values for these keys will be used to populate the permission dialogs so that the user will be properly informed as to the purpose of the permission request. See Electron Application Distribution for more information about how to set these in the context of Electron.
This user consent was not required until macOS 10.14 Mojave, so this method will always return true if your system is running 10.13 High Sierra or lower.
systemPreferences.getAnimationSettings()
Returns Object:
shouldRenderRichAnimationBoolean - Returns true if rich animations should be rendered. Looks at session type (e.g. remote desktop) and accessibility settings to give guidance for heavy animations.scrollAnimationsEnabledBySystemBoolean - Determines on a per-platform basis whether scroll animations (e.g. produced by home/end key) should be enabled.prefersReducedMotionBoolean - Determines whether the user desires reduced motion based on platform APIs.
Returns an object with system animation settings.
systemPreferences.appLevelAppearance macOS
A String property that can be dark, light or unknown. It determines the macOS appearance setting for
your application. This maps to values in: NSApplication.appearance. Setting this will override the
system default as well as the value of getEffectiveAppearance.
Possible values that can be set are dark and light, and possible return values are dark, light, and unknown.
This property is only available on macOS 10.14 Mojave or newer.
systemPreferences.effectiveAppearance macOS Readonly
A String property that can be dark, light or unknown.
Returns the macOS appearance setting that is currently applied to your application, maps to NSApplication.effectiveAppearance
Task Object
programString - Path of the program to execute, usually you should specifyprocess.execPathwhich opens the current program.argumentsString - The command line arguments whenprogramis executed.titleString - The string to be displayed in a JumpList.descriptionString - Description of this task.iconPathString - The absolute path to an icon to be displayed in a JumpList, which can be an arbitrary resource file that contains an icon. You can usually specifyprocess.execPathto show the icon of the program.iconIndexNumber - The icon index in the icon file. If an icon file consists of two or more icons, set this value to identify the icon. If an icon file consists of one icon, this value is 0.workingDirectoryString (optional) - The working directory. Default is empty.
Testing
We aim to keep the code coverage of Electron high. We ask that all pull request not only pass all existing tests, but ideally also add new tests to cover changed code and new scenarios. Ensuring that we capture as many code paths and use cases of Electron as possible ensures that we all ship apps with fewer bugs.
This repository comes with linting rules for both JavaScript and C++ – as well as unit and integration tests. To learn more about Electron's coding style, please see the coding-style document.
Linting
To ensure that your JavaScript is in compliance with the Electron coding
style, run npm run lint-js, which will run standard against both
Electron itself as well as the unit tests. If you are using an editor
with a plugin/addon system, you might want to use one of the many
StandardJS addons to be informed of coding style
violations before you ever commit them.
To run standard with parameters, run npm run lint-js -- followed by
arguments you want passed to standard.
To ensure that your C++ is in compliance with the Electron coding style,
run npm run lint-cpp, which runs a cpplint script. We recommend that
you use clang-format and prepared a short tutorial.
There is not a lot of Python in this repository, but it too is governed
by coding style rules. npm run lint-py will check all Python, using
pylint to do so.
Unit Tests
If you are not using build-tools,
ensure that that name you have configured for your
local build of Electron is one of Testing, Release, Default, Debug, or
you have set process.env.ELECTRON_OUT_DIR. Without these set, Electron will fail
to perform some pre-testing steps.
To run all unit tests, run npm run test. The unit tests are an Electron
app (surprise!) that can be found in the spec folder. Note that it has
its own package.json and that its dependencies are therefore not defined
in the top-level package.json.
To run only specific tests matching a pattern, run npm run test -- -g=PATTERN, replacing the PATTERN with a regex that matches the tests
you would like to run. As an example: If you want to run only IPC tests, you
would run npm run test -- -g ipc.
Extra steps to run the unit test:
- Visual Studio 2019 must be installed.
- Node headers have to be compiled for your configuration.
ninja -C out\Testing third_party\electron_node:headers - The electron.lib has to be copied as node.lib.
cd out\Testing mkdir gen\node_headers\Release copy electron.lib gen\node_headers\Release\node.lib
Missing fonts
Some Windows 10 devices do not ship with the Meiryo font installed, which may cause a font fallback test to fail. To install Meiryo:
- Push the Windows key and search for Manage optional features.
- Click Add a feature.
- Select Japanese Supplemental Fonts and click Install.
Pixel measurements
Some tests which rely on precise pixel measurements may not work correctly on devices with Hi-DPI screen settings due to floating point precision errors. To run these tests correctly, make sure the device is set to 100% scaling.
To configure display scaling:
- Push the Windows key and search for Display settings.
- Under Scale and layout, make sure that the device is set to 100%.
Testing on Headless CI Systems (Travis CI, Jenkins)
Being based on Chromium, Electron requires a display driver to function. If Chromium can't find a display driver, Electron will fail to launch - and therefore not executing any of your tests, regardless of how you are running them. Testing Electron-based apps on Travis, Circle, Jenkins or similar Systems requires therefore a little bit of configuration. In essence, we need to use a virtual display driver.
Configuring the Virtual Display Server
First, install Xvfb. It's a virtual framebuffer, implementing the X11 display server protocol - it performs all graphical operations in memory without showing any screen output, which is exactly what we need.
Then, create a virtual Xvfb screen and export an environment variable
called DISPLAY that points to it. Chromium in Electron will automatically look
for $DISPLAY, so no further configuration of your app is required.
This step can be automated with Anaïs Betts'
xvfb-maybe: Prepend your test
commands with xvfb-maybe and the little tool will automatically configure
Xvfb, if required by the current system. On Windows or macOS, it will
do nothing.
## On Windows or macOS, this invokes electron-mocha
## On Linux, if we are in a headless environment, this will be equivalent
## to xvfb-run electron-mocha ./test/*.js
xvfb-maybe electron-mocha ./test/*.js
Travis CI
On Travis, your .travis.yml should look roughly like this:
addons:
apt:
packages:
- xvfb
install:
- export DISPLAY=':99.0'
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
Jenkins
For Jenkins, a Xvfb plugin is available.
Circle CI
Circle CI is awesome and has Xvfb and $DISPLAY
already set up, so no further configuration is required.
AppVeyor
AppVeyor runs on Windows, supporting Selenium, Chromium, Electron and similar tools out of the box - no configuration is required.
Testing Widevine CDM
In Electron you can use the Widevine CDM library shipped with Chrome browser.
Widevine Content Decryption Modules (CDMs) are how streaming services protect content using HTML5 video to web browsers without relying on an NPAPI plugin like Flash or Silverlight. Widevine support is an alternative solution for streaming services that currently rely on Silverlight for playback of DRM-protected video content. It will allow websites to show DRM-protected video content in Firefox without the use of NPAPI plugins. The Widevine CDM runs in an open-source CDM sandbox providing better user security than NPAPI plugins.
Note on VMP
As of Electron v1.8.0 (Chrome v59),
the below steps are may only be some of the necessary steps to enable Widevine;
any app on or after that version intending to use the Widevine CDM may need to
be signed using a license obtained from Widevine
itself.
Per Widevine:
Chrome 59 (and later) includes support for Verified Media Path (VMP). VMP provides a method to verify the authenticity of a device platform. For browser deployments, this will provide an additional signal to determine if a browser-based implementation is reliable and secure.
The proxy integration guide has been updated with information about VMP and how to issue licenses.
Widevine recommends our browser-based integrations (vendors and browser-based applications) add support for VMP.
To enable video playback with this new restriction, castLabs has created a fork that has implemented the necessary changes to enable Widevine to be played in an Electron application if one has obtained the necessary licenses from widevine.
Getting the library
Open chrome://components/ in Chrome browser, find Widevine Content Decryption Module
and make sure it is up to date, then you can find the library files from the
application directory.
On Windows
The library file widevinecdm.dll will be under
Program Files(x86)/Google/Chrome/Application/CHROME_VERSION/WidevineCdm/_platform_specific/win_(x86|x64)/
directory.
On macOS
The library file libwidevinecdm.dylib will be under
/Applications/Google Chrome.app/Contents/Versions/CHROME_VERSION/Google Chrome Framework.framework/Versions/A/Libraries/WidevineCdm/_platform_specific/mac_(x86|x64)/
directory.
Note: Make sure that chrome version used by Electron is greater than or
equal to the min_chrome_version value of Chrome's widevine cdm component.
The value can be found in manifest.json under WidevineCdm directory.
Using the library
After getting the library files, you should pass the path to the file
with --widevine-cdm-path command line switch, and the library's version
with --widevine-cdm-version switch. The command line switches have to be
passed before the ready event of app module gets emitted.
Example code:
const { app, BrowserWindow } = require('electron')
// You have to pass the directory that contains widevine library here, it is
// * `libwidevinecdm.dylib` on macOS,
// * `widevinecdm.dll` on Windows.
app.commandLine.appendSwitch('widevine-cdm-path', '/path/to/widevine_library')
// The version of plugin can be got from `chrome://components` page in Chrome.
app.commandLine.appendSwitch('widevine-cdm-version', '1.4.8.866')
let win = null
app.whenReady().then(() => {
win = new BrowserWindow()
win.show()
})
Verifying Widevine CDM support
To verify whether widevine works, you can use following ways:
- Open https://shaka-player-demo.appspot.com/ and load a manifest that uses
Widevine. - Open http://www.dash-player.com/demo/drm-test-area/, check whether the page
says
bitdash uses Widevine in your browser, then play the video.
ThumbarButton Object
iconNativeImage - The icon showing in thumbnail toolbar.clickFunctiontooltipString (optional) - The text of the button's tooltip.flagsString[] (optional) - Control specific states and behaviors of the button. By default, it is['enabled'].
The flags is an array that can include following Strings:
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.
new TouchBar(options)
optionsObjectitems(TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer)[] (optional)escapeItem(TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer | null) (optional)
Creates a new touch bar with the specified items. Use
BrowserWindow.setTouchBar to add the TouchBar to a window.
Note: The TouchBar API is currently experimental and may change or be removed in future Electron releases.
Tip: If you don't have a MacBook with Touch Bar, you can use Touch Bar Simulator to test Touch Bar usage in your app.
TouchBarButton
A typeof TouchBarButton reference to the TouchBarButton class.
TouchBarColorPicker
A typeof TouchBarColorPicker reference to the TouchBarColorPicker class.
TouchBarGroup
A typeof TouchBarGroup reference to the TouchBarGroup class.
TouchBarLabel
A typeof TouchBarLabel reference to the TouchBarLabel class.
TouchBarPopover
A typeof TouchBarPopover reference to the TouchBarPopover class.
TouchBarScrubber
A typeof TouchBarScrubber reference to the TouchBarScrubber class.
TouchBarSegmentedControl
A typeof TouchBarSegmentedControl reference to the TouchBarSegmentedControl class.
TouchBarSlider
A typeof TouchBarSlider reference to the TouchBarSlider class.
TouchBarSpacer
A typeof TouchBarSpacer reference to the TouchBarSpacer class.
TouchBarOtherItemsProxy
A typeof TouchBarOtherItemsProxy reference to the TouchBarOtherItemsProxy class.
Instance Properties
The following properties are available on instances of TouchBar:
touchBar.escapeItem
A TouchBarItem that will replace the "esc" button on the touch bar when set.
Setting to null restores the default "esc" button. Changing this value
immediately updates the escape item in the touch bar.
Examples
Below is an example of a simple slot machine touch bar game with a button and some labels.
const { app, BrowserWindow, TouchBar } = require('electron')
const { TouchBarLabel, TouchBarButton, TouchBarSpacer } = TouchBar
let spinning = false
// Reel labels
const reel1 = new TouchBarLabel()
const reel2 = new TouchBarLabel()
const reel3 = new TouchBarLabel()
// Spin result label
const result = new TouchBarLabel()
// Spin button
const spin = new TouchBarButton({
label: '🎰 Spin',
backgroundColor: '#7851A9',
click: () => {
// Ignore clicks if already spinning
if (spinning) {
return
}
spinning = true
result.label = ''
let timeout = 10
const spinLength = 4 * 1000 // 4 seconds
const startTime = Date.now()
const spinReels = () => {
updateReels()
if ((Date.now() - startTime) >= spinLength) {
finishSpin()
} else {
// Slow down a bit on each spin
timeout *= 1.1
setTimeout(spinReels, timeout)
}
}
spinReels()
}
})
const getRandomValue = () => {
const values = ['🍒', '💎', '7️⃣', '🍊', '🔔', '⭐', '🍇', '🍀']
return values[Math.floor(Math.random() * values.length)]
}
const updateReels = () => {
reel1.label = getRandomValue()
reel2.label = getRandomValue()
reel3.label = getRandomValue()
}
const finishSpin = () => {
const uniqueValues = new Set([reel1.label, reel2.label, reel3.label]).size
if (uniqueValues === 1) {
// All 3 values are the same
result.label = '💰 Jackpot!'
result.textColor = '#FDFF00'
} else if (uniqueValues === 2) {
// 2 values are the same
result.label = '😍 Winner!'
result.textColor = '#FDFF00'
} else {
// No values are the same
result.label = '🙁 Spin Again'
result.textColor = null
}
spinning = false
}
const touchBar = new TouchBar({
items: [
spin,
new TouchBarSpacer({ size: 'large' }),
reel1,
new TouchBarSpacer({ size: 'small' }),
reel2,
new TouchBarSpacer({ size: 'small' }),
reel3,
new TouchBarSpacer({ size: 'large' }),
result
]
})
let window
app.whenReady().then(() => {
window = new BrowserWindow({
frame: false,
titleBarStyle: 'hiddenInset',
width: 200,
height: 200,
backgroundColor: '#000'
})
window.loadURL('about:blank')
window.setTouchBar(touchBar)
})
Running the above example
To run the example above, you'll need to (assuming you've got a terminal open in the directory you want to run the example):
- Save the above file to your computer as
touchbar.js - Install Electron via
npm install electron - Run the example inside Electron:
./node_modules/.bin/electron touchbar.js
You should then see a new Electron window and the app running in your touch bar (or touch bar emulator).
new TouchBarButton(options)
optionsObjectlabelString (optional) - Button text.accessibilityLabelString (optional) - A short description of the button for use by screenreaders like VoiceOver.backgroundColorString (optional) - Button background color in hex format, i.e#ABCDEF.iconNativeImage | String (optional) - Button icon.iconPositionString (optional) - Can beleft,rightoroverlay. Defaults tooverlay.clickFunction (optional) - Function to call when the button is clicked.enabledBoolean (optional) - Whether the button is in an enabled state. Default istrue.
When defining accessibilityLabel, ensure you have considered macOS best practices.
Instance Properties
The following properties are available on instances of TouchBarButton:
touchBarButton.accessibilityLabel
A String representing the description of the button to be read by a screen reader. Will only be read by screen readers if no label is set.
touchBarButton.label
A String representing the button's current text. Changing this value immediately updates the button
in the touch bar.
touchBarButton.backgroundColor
A String hex code representing the button's current background color. Changing this value immediately updates
the button in the touch bar.
touchBarButton.icon
A NativeImage representing the button's current icon. Changing this value immediately updates the button
in the touch bar.
touchBarButton.enabled
A Boolean representing whether the button is in an enabled state.
Class: TouchBarColorPicker
Create a color picker in the touch bar for native macOS applications
Process: Main
new TouchBarColorPicker(options)
optionsObjectavailableColorsString[] (optional) - Array of hex color strings to appear as possible colors to select.selectedColorString (optional) - The selected hex color in the picker, i.e#ABCDEF.changeFunction (optional) - Function to call when a color is selected.colorString - The color that the user selected from the picker.
Instance Properties
The following properties are available on instances of TouchBarColorPicker:
touchBarColorPicker.availableColors
A String[] array representing the color picker's available colors to select. Changing this value immediately
updates the color picker in the touch bar.
touchBarColorPicker.selectedColor
A String hex code representing the color picker's currently selected color. Changing this value immediately
updates the color picker in the touch bar.
new TouchBarGroup(options)
optionsObjectitemsTouchBar - Items to display as a group.
new TouchBarLabel(options)
optionsObjectlabelString (optional) - Text to display.accessibilityLabelString (optional) - A short description of the button for use by screenreaders like VoiceOver.textColorString (optional) - Hex color of text, i.e#ABCDEF.
When defining accessibilityLabel, ensure you have considered macOS best practices.
Instance Properties
The following properties are available on instances of TouchBarLabel:
touchBarLabel.label
A String representing the label's current text. Changing this value immediately updates the label in
the touch bar.
touchBarLabel.accessibilityLabel
A String representing the description of the label to be read by a screen reader.
touchBarLabel.textColor
A String hex code representing the label's current text color. Changing this value immediately updates the
label in the touch bar.
Class: TouchBarOtherItemsProxy
Instantiates a special "other items proxy", which nests TouchBar elements inherited from Chromium at the space indicated by the proxy. By default, this proxy is added to each TouchBar at the end of the input. For more information, see the AppKit docs on NSTouchBarItemIdentifierOtherItemsProxy
Note: Only one instance of this class can be added per TouchBar.
Process: Main
Class: TouchBarPopover
Create a popover in the touch bar for native macOS applications
Process: Main
new TouchBarPopover(options)
optionsObjectlabelString (optional) - Popover button text.iconNativeImage (optional) - Popover button icon.itemsTouchBar - Items to display in the popover.showCloseButtonBoolean (optional) -trueto display a close button on the left of the popover,falseto not show it. Default istrue.
Instance Properties
The following properties are available on instances of TouchBarPopover:
touchBarPopover.label
A String representing the popover's current button text. Changing this value immediately updates the
popover in the touch bar.
touchBarPopover.icon
A NativeImage representing the popover's current button icon. Changing this value immediately updates the
popover in the touch bar.
new TouchBarScrubber(options)
optionsObjectitemsScrubberItem[] - An array of items to place in this scrubber.selectFunction (optional) - Called when the user taps an item that was not the last tapped item.selectedIndexInteger - The index of the item the user selected.
highlightFunction (optional) - Called when the user taps any item.highlightedIndexInteger - The index of the item the user touched.
selectedStyleString (optional) - Selected item style. Can bebackground,outlineornone. Defaults tonone.overlayStyleString (optional) - Selected overlay item style. Can bebackground,outlineornone. Defaults tonone.showArrowButtonsBoolean (optional) - Defaults tofalse.modeString (optional) - Can befixedorfree. The default isfree.continuousBoolean (optional) - Defaults totrue.
Instance Properties
The following properties are available on instances of TouchBarScrubber:
touchBarScrubber.items
A ScrubberItem[] array representing the items in this scrubber. Updating this value immediately
updates the control in the touch bar. Updating deep properties inside this array does not update the touch bar.
touchBarScrubber.selectedStyle
A String representing the style that selected items in the scrubber should have. Updating this value immediately
updates the control in the touch bar. Possible values:
background- Maps to[NSScrubberSelectionStyle roundedBackgroundStyle].outline- Maps to[NSScrubberSelectionStyle outlineOverlayStyle].none- Removes all styles.
touchBarScrubber.overlayStyle
A String representing the style that selected items in the scrubber should have. This style is overlayed on top
of the scrubber item instead of being placed behind it. Updating this value immediately updates the control in the
touch bar. Possible values:
background- Maps to[NSScrubberSelectionStyle roundedBackgroundStyle].outline- Maps to[NSScrubberSelectionStyle outlineOverlayStyle].none- Removes all styles.
touchBarScrubber.showArrowButtons
A Boolean representing whether to show the left / right selection arrows in this scrubber. Updating this value
immediately updates the control in the touch bar.
touchBarScrubber.mode
A String representing the mode of this scrubber. Updating this value immediately
updates the control in the touch bar. Possible values:
fixed- Maps toNSScrubberModeFixed.free- Maps toNSScrubberModeFree.
touchBarScrubber.continuous
A Boolean representing whether this scrubber is continuous or not. Updating this value immediately
updates the control in the touch bar.
Class: TouchBarSegmentedControl
Create a segmented control (a button group) where one button has a selected state
Process: Main
new TouchBarSegmentedControl(options)
optionsObjectsegmentStyleString (optional) - Style of the segments:automatic- Default. The appearance of the segmented control is automatically determined based on the type of window in which the control is displayed and the position within the window. Maps toNSSegmentStyleAutomatic.rounded- The control is displayed using the rounded style. Maps toNSSegmentStyleRounded.textured-rounded- The control is displayed using the textured rounded style. Maps toNSSegmentStyleTexturedRounded.round-rect- The control is displayed using the round rect style. Maps toNSSegmentStyleRoundRect.textured-square- The control is displayed using the textured square style. Maps toNSSegmentStyleTexturedSquare.capsule- The control is displayed using the capsule style. Maps toNSSegmentStyleCapsule.small-square- The control is displayed using the small square style. Maps toNSSegmentStyleSmallSquare.separated- The segments in the control are displayed very close to each other but not touching. Maps toNSSegmentStyleSeparated.
modeString (optional) - The selection mode of the control:single- Default. One item selected at a time, selecting one deselects the previously selected item. Maps toNSSegmentSwitchTrackingSelectOne.multiple- Multiple items can be selected at a time. Maps toNSSegmentSwitchTrackingSelectAny.buttons- Make the segments act as buttons, each segment can be pressed and released but never marked as active. Maps toNSSegmentSwitchTrackingMomentary.
segmentsSegmentedControlSegment[] - An array of segments to place in this control.selectedIndexInteger (optional) - The index of the currently selected segment, will update automatically with user interaction. When the mode ismultipleit will be the last selected item.changeFunction (optional) - Called when the user selects a new segment.selectedIndexInteger - The index of the segment the user selected.isSelectedBoolean - Whether as a result of user selection the segment is selected or not.
Instance Properties
The following properties are available on instances of TouchBarSegmentedControl:
touchBarSegmentedControl.segmentStyle
A String representing the controls current segment style. Updating this value immediately updates the control
in the touch bar.
touchBarSegmentedControl.segments
A SegmentedControlSegment[] array representing the segments in this control. Updating this value immediately
updates the control in the touch bar. Updating deep properties inside this array does not update the touch bar.
touchBarSegmentedControl.selectedIndex
An Integer representing the currently selected segment. Changing this value immediately updates the control
in the touch bar. User interaction with the touch bar will update this value automatically.
new TouchBarSlider(options)
optionsObjectlabelString (optional) - Label text.valueInteger (optional) - Selected value.minValueInteger (optional) - Minimum value.maxValueInteger (optional) - Maximum value.changeFunction (optional) - Function to call when the slider is changed.newValueNumber - The value that the user selected on the Slider.
Instance Properties
The following properties are available on instances of TouchBarSlider:
touchBarSlider.label
A String representing the slider's current text. Changing this value immediately updates the slider
in the touch bar.
touchBarSlider.value
A Number representing the slider's current value. Changing this value immediately updates the slider
in the touch bar.
touchBarSlider.minValue
A Number representing the slider's current minimum value. Changing this value immediately updates the
slider in the touch bar.
touchBarSlider.maxValue
A Number representing the slider's current maximum value. Changing this value immediately updates the
slider in the touch bar.
Class: TouchBarSpacer
Create a spacer between two items in the touch bar for native macOS applications
Process: Main
new TouchBarSpacer(options)
optionsObjectsizeString (optional) - Size of spacer, possible values are:small- Small space between items. Maps toNSTouchBarItemIdentifierFixedSpaceSmall. This is the default.large- Large space between items. Maps toNSTouchBarItemIdentifierFixedSpaceLarge.flexible- Take up all available space. Maps toNSTouchBarItemIdentifierFlexibleSpace.
TraceCategoriesAndOptions Object
categoryFilterString - A filter to control what category groups should be traced. A filter can have an optional '-' prefix to exclude category groups that contain a matching category. Having both included and excluded category patterns in the same list is not supported. Examples:test_MyTest*,test_MyTest*,test_OtherStuff,-excluded_category1,-excluded_category2.traceOptionsString - Controls what kind of tracing is enabled, it is a comma-delimited sequence of the following strings:record-until-full,record-continuously,trace-to-console,enable-sampling,enable-systrace, e.g.'record-until-full,enable-sampling'. The first 3 options are trace recording modes and hence mutually exclusive. If more than one trace recording modes appear in thetraceOptionsstring, the last one takes precedence. If none of the trace recording modes are specified, recording mode isrecord-until-full. The trace option will first be reset to the default option (record_modeset torecord-until-full,enable_samplingandenable_systraceset tofalse) before options parsed fromtraceOptionsare applied on it.
TraceConfig Object
recording_modeString (optional) - Can berecord-until-full,record-continuously,record-as-much-as-possibleortrace-to-console. Defaults torecord-until-full.trace_buffer_size_in_kbnumber (optional) - maximum size of the trace recording buffer in kilobytes. Defaults to 100MB.trace_buffer_size_in_eventsnumber (optional) - maximum size of the trace recording buffer in events.enable_argument_filterboolean (optional) - if true, filter event data according to a whitelist of events that have been manually vetted to not include any PII. See the implementation in Chromium for specifics.included_categoriesString[] (optional) - a list of tracing categories to include. Can include glob-like patterns using*at the end of the category name. See tracing categories for the list of categories.excluded_categoriesString[] (optional) - a list of tracing categories to exclude. Can include glob-like patterns using*at the end of the category name. See tracing categories for the list of categories.included_process_idsnumber[] (optional) - a list of process IDs to include in the trace. If not specified, trace all processes.histogram_namesString[] (optional) - a list of histogram names to report with the trace.memory_dump_configRecord<String, any> (optional) - if thedisabled-by-default-memory-infracategory is enabled, this contains optional additional configuration for data collection. See the Chromium memory-infra docs for more information.
An example TraceConfig that roughly matches what Chrome DevTools records:
{
recording_mode: 'record-until-full',
included_categories: [
'devtools.timeline',
'disabled-by-default-devtools.timeline',
'disabled-by-default-devtools.timeline.frame',
'disabled-by-default-devtools.timeline.stack',
'v8.execute',
'blink.console',
'blink.user_timing',
'latencyInfo',
'disabled-by-default-v8.cpu_profiler',
'disabled-by-default-v8.cpu_profiler.hires'
],
excluded_categories: [ '*' ]
}
Transaction Object
transactionIdentifierString - A string that uniquely identifies a successful payment transaction.transactionDateString - The date the transaction was added to the App Store’s payment queue.originalTransactionIdentifierString - The identifier of the restored transaction by the App Store.transactionStateString - The transaction state, can bepurchasing,purchased,failed,restoredordeferred.errorCodeInteger - The error code if an error occurred while processing the transaction.errorMessageString - The error message if an error occurred while processing the transaction.paymentObjectproductIdentifierString - The identifier of the purchased product.quantityInteger - The quantity purchased.
Class: Tray
Add icons and context menus to the system's notification area.
Process: Main
Tray is an EventEmitter.
const { app, Menu, Tray } = require('electron')
let tray = null
app.whenReady().then(() => {
tray = new Tray('/path/to/my/icon')
const contextMenu = Menu.buildFromTemplate([
{ label: 'Item1', type: 'radio' },
{ label: 'Item2', type: 'radio' },
{ label: 'Item3', type: 'radio', checked: true },
{ label: 'Item4', type: 'radio' }
])
tray.setToolTip('This is my application.')
tray.setContextMenu(contextMenu)
})
Platform limitations:
- On Linux the app indicator will be used if it is supported, otherwise
GtkStatusIconwill be used instead. - On Linux distributions that only have app indicator support, you have to
install
libappindicator1to make the tray icon work. - App indicator will only be shown when it has a context menu.
- When app indicator is used on Linux, the
clickevent is ignored. - On Linux in order for changes made to individual
MenuItems to take effect, you have to callsetContextMenuagain. For example:
const { app, Menu, Tray } = require('electron')
let appIcon = null
app.whenReady().then(() => {
appIcon = new Tray('/path/to/my/icon')
const contextMenu = Menu.buildFromTemplate([
{ label: 'Item1', type: 'radio' },
{ label: 'Item2', type: 'radio' }
])
// Make a change to the context menu
contextMenu.items[1].checked = false
// Call this again for Linux because we modified the context menu
appIcon.setContextMenu(contextMenu)
})
- On Windows it is recommended to use
ICOicons to get best visual effects.
If you want to keep exact same behaviors on all platforms, you should not
rely on the click event and always attach a context menu to the tray icon.
new Tray(image, [guid])
image(NativeImage | String)guidString (optional) Windows - Assigns a GUID to the tray icon. If the executable is signed and the signature contains an organization in the subject line then the GUID is permanently associated with that signature. OS level settings like the position of the tray icon in the system tray will persist even if the path to the executable changes. If the executable is not code-signed then the GUID is permanently associated with the path to the executable. Changing the path to the executable will break the creation of the tray icon and a new GUID must be used. However, it is highly recommended to use the GUID parameter only in conjunction with code-signed executable. If an App defines multiple tray icons then each icon must use a separate GUID.
Creates a new tray icon associated with the image.
Instance Events
The Tray module emits the following events:
Event: 'click'
Returns:
eventKeyboardEventboundsRectangle - The bounds of tray icon.positionPoint - The position of the event.
Emitted when the tray icon is clicked.
Event: 'right-click' macOS Windows
Returns:
eventKeyboardEventboundsRectangle - The bounds of tray icon.
Emitted when the tray icon is right clicked.
Event: 'double-click' macOS Windows
Returns:
eventKeyboardEventboundsRectangle - The bounds of tray icon.
Emitted when the tray icon is double clicked.
Event: 'balloon-show' Windows
Emitted when the tray balloon shows.
Event: 'balloon-click' Windows
Emitted when the tray balloon is clicked.
Event: 'balloon-closed' Windows
Emitted when the tray balloon is closed because of timeout or user manually closes it.
Event: 'drop' macOS
Emitted when any dragged items are dropped on the tray icon.
Event: 'drop-files' macOS
Returns:
eventEventfilesString[] - The paths of the dropped files.
Emitted when dragged files are dropped in the tray icon.
Event: 'drop-text' macOS
Returns:
eventEventtextString - the dropped text string.
Emitted when dragged text is dropped in the tray icon.
Event: 'drag-enter' macOS
Emitted when a drag operation enters the tray icon.
Event: 'drag-leave' macOS
Emitted when a drag operation exits the tray icon.
Event: 'drag-end' macOS
Emitted when a drag operation ends on the tray or ends at another location.
Event: 'mouse-up' macOS
Returns:
eventKeyboardEventpositionPoint - The position of the event.
Emitted when the mouse is released from clicking the tray icon.
Note: This will not be emitted if you have set a context menu for your Tray using tray.setContextMenu, as a result of macOS-level constraints.
Event: 'mouse-down' macOS
Returns:
eventKeyboardEventpositionPoint - The position of the event.
Emitted when the mouse clicks the tray icon.
Event: 'mouse-enter' macOS
Returns:
eventKeyboardEventpositionPoint - The position of the event.
Emitted when the mouse enters the tray icon.
Event: 'mouse-leave' macOS
Returns:
eventKeyboardEventpositionPoint - The position of the event.
Emitted when the mouse exits the tray icon.
Event: 'mouse-move' macOS Windows
Returns:
eventKeyboardEventpositionPoint - The position of the event.
Emitted when the mouse moves in the tray icon.
Instance Methods
The Tray class has the following methods:
tray.destroy()
Destroys the tray icon immediately.
tray.setPressedImage(image) macOS
image(NativeImage | String)
Sets the image associated with this tray icon when pressed on macOS.
tray.setTitle(title) macOS
titleString
Sets the title displayed next to the tray icon in the status bar (Support ANSI colors).
tray.getTitle() macOS
Returns String - the title displayed next to the tray icon in the status bar
tray.setIgnoreDoubleClickEvents(ignore) macOS
ignoreBoolean
Sets the option to ignore double click events. Ignoring these events allows you to detect every individual click of the tray icon.
This value is set to false by default.
tray.getIgnoreDoubleClickEvents() macOS
Returns Boolean - Whether double click events will be ignored.
tray.displayBalloon(options) Windows
optionsObjecticon(NativeImage | String) (optional) - Icon to use wheniconTypeiscustom.iconTypeString (optional) - Can benone,info,warning,errororcustom. Default iscustom.titleStringcontentStringlargeIconBoolean (optional) - The large version of the icon should be used. Default istrue. Maps toNIIF_LARGE_ICON.noSoundBoolean (optional) - Do not play the associated sound. Default isfalse. Maps toNIIF_NOSOUND.respectQuietTimeBoolean (optional) - Do not display the balloon notification if the current user is in "quiet time". Default isfalse. Maps toNIIF_RESPECT_QUIET_TIME.
Displays a tray balloon.
tray.removeBalloon() Windows
Removes a tray balloon.
tray.focus() Windows
Returns focus to the taskbar notification area.
Notification area icons should use this message when they have completed their UI operation.
For example, if the icon displays a shortcut menu, but the user presses ESC to cancel it,
use tray.focus() to return focus to the notification area.
tray.popUpContextMenu([menu, position]) macOS Windows
menuMenu (optional)positionPoint (optional) - The pop up position.
Pops up the context menu of the tray icon. When menu is passed, the menu will
be shown instead of the tray icon's context menu.
The position is only available on Windows, and it is (0, 0) by default.
tray.closeContextMenu() macOS Windows
Closes an open context menu, as set by tray.setContextMenu().
tray.isDestroyed()
Returns Boolean - Whether the tray icon is destroyed.
Updating Applications
There are several ways to update an Electron application. The easiest and officially supported one is taking advantage of the built-in Squirrel framework and Electron's autoUpdater module.
Using update.electronjs.org
The Electron team maintains update.electronjs.org, a free and open-source webservice that Electron apps can use to self-update. The service is designed for Electron apps that meet the following criteria:
- App runs on macOS or Windows
- App has a public GitHub repository
- Builds are published to GitHub Releases
- Builds are code-signed
The easiest way to use this service is by installing update-electron-app, a Node.js module preconfigured for use with update.electronjs.org.
Install the module:
npm install update-electron-app
Invoke the updater from your app's main process file:
require('update-electron-app')()
By default, this module will check for updates at app startup, then every ten minutes. When an update is found, it will automatically be downloaded in the background. When the download completes, a dialog is displayed allowing the user to restart the app.
If you need to customize your configuration, you can
pass options to update-electron-app
or
use the update service directly.
Deploying an Update Server
If you're developing a private Electron application, or if you're not publishing releases to GitHub Releases, it may be necessary to run your own update server.
Depending on your needs, you can choose from one of these:
- Hazel – Update server for private or open-source apps which can be deployed for free on Now. It pulls from GitHub Releases and leverages the power of GitHub's CDN.
- Nuts – Also uses GitHub Releases, but caches app updates on disk and supports private repositories.
- electron-release-server – Provides a dashboard for handling releases and does not require releases to originate on GitHub.
- Nucleus – A complete update server for Electron apps maintained by Atlassian. Supports multiple applications and channels; uses a static file store to minify server cost.
Implementing Updates in Your App
Once you've deployed your update server, continue with importing the required modules in your code. The following code might vary for different server software, but it works like described when using Hazel.
Important: Please ensure that the code below will only be executed in your packaged app, and not in development. You can use electron-is-dev to check for the environment.
const { app, autoUpdater, dialog } = require('electron')
Next, construct the URL of the update server and tell autoUpdater about it:
const server = 'https://your-deployment-url.com'
const url = `${server}/update/${process.platform}/${app.getVersion()}`
autoUpdater.setFeedURL({ url })
As the final step, check for updates. The example below will check every minute:
setInterval(() => {
autoUpdater.checkForUpdates()
}, 60000)
Once your application is packaged, it will receive an update for each new GitHub Release that you publish.
Applying Updates
Now that you've configured the basic update mechanism for your application, you need to ensure that the user will get notified when there's an update. This can be achieved using the autoUpdater API events:
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Restart', 'Later'],
title: 'Application Update',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
}
dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
})
})
Also make sure that errors are
being handled. Here's an example
for logging them to stderr:
autoUpdater.on('error', message => {
console.error('There was a problem updating the application')
console.error(message)
})
Handling Updates Manually
Because the requests made by Auto Update aren't under your direct control, you may find situations that are difficult to handle (such as if the update server is behind authentication). The url field does support files, which means that with some effort, you can sidestep the server-communication aspect of the process. Here's an example of how this could work.
UploadBlob Object
typeString -blob.blobUUIDString - UUID of blob data to upload.
UploadData Object
bytesBuffer - Content being sent.fileString (optional) - Path of file being uploaded.blobUUIDString (optional) - UUID of blob data. Use ses.getBlobData method to retrieve the data.
UploadFile Object
typeString -file.filePathString - Path of file to be uploaded.offsetInteger - Defaults to0.lengthInteger - Number of bytes to read fromoffset. Defaults to0.modificationTimeDouble - Last Modification time in number of seconds since the UNIX epoch.
UploadRawData Object
typeString -rawData.bytesBuffer - Data to be uploaded.
Using Native Node Modules
Native Node modules are supported by Electron, but since Electron is very likely to use a different V8 version from the Node binary installed on your system, the modules you use will need to be recompiled for Electron. Otherwise, you will get the following class of error when you try to run your app:
Error: The module '/path/to/native/module.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION $XYZ. This version of Node.js requires
NODE_MODULE_VERSION $ABC. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or `npm install`).
How to install native modules
There are several different ways to install native modules:
Installing modules and rebuilding for Electron
You can install modules like other Node projects, and then rebuild the modules
for Electron with the electron-rebuild package. This
module can automatically determine the version of Electron and handle the
manual steps of downloading headers and rebuilding native modules for your app.
For example, to install electron-rebuild and then rebuild modules with it
via the command line:
npm install --save-dev electron-rebuild
# Every time you run "npm install", run this:
./node_modules/.bin/electron-rebuild
# On Windows if you have trouble, try:
.\node_modules\.bin\electron-rebuild.cmd
For more information on usage and integration with other tools, consult the project's README.
Using npm
By setting a few environment variables, you can use npm to install modules
directly.
For example, to install all dependencies for Electron:
# Electron's version.
export npm_config_target=1.2.3
# The architecture of Electron, see https://electronjs.org/docs/tutorial/support#supported-platforms
# for supported architectures.
export npm_config_arch=x64
export npm_config_target_arch=x64
# Download headers for Electron.
export npm_config_disturl=https://electronjs.org/headers
# Tell node-pre-gyp that we are building for Electron.
export npm_config_runtime=electron
# Tell node-pre-gyp to build module from source code.
export npm_config_build_from_source=true
# Install all dependencies, and store cache to ~/.electron-gyp.
HOME=~/.electron-gyp npm install
Manually building for Electron
If you are a developer developing a native module and want to test it against
Electron, you might want to rebuild the module for Electron manually. You can
use node-gyp directly to build for Electron:
cd /path-to-module/
HOME=~/.electron-gyp node-gyp rebuild --target=1.2.3 --arch=x64 --dist-url=https://electronjs.org/headers
HOME=~/.electron-gypchanges where to find development headers.--target=1.2.3is the version of Electron.--dist-url=...specifies where to download the headers.--arch=x64says the module is built for a 64-bit system.
Manually building for a custom build of Electron
To compile native Node modules against a custom build of Electron that doesn't
match a public release, instruct npm to use the version of Node you have bundled
with your custom build.
npm rebuild --nodedir=/path/to/electron/vendor/node
Troubleshooting
If you installed a native module and found it was not working, you need to check the following things:
- When in doubt, run
electron-rebuildfirst. - Make sure the native module is compatible with the target platform and architecture for your Electron app.
- Make sure
win_delay_load_hookis not set tofalsein the module'sbinding.gyp. - After you upgrade Electron, you usually need to rebuild the modules.
A note about win_delay_load_hook
On Windows, by default, node-gyp links native modules against node.dll.
However, in Electron 4.x and higher, the symbols needed by native modules are
exported by electron.exe, and there is no node.dll. In order to load native
modules on Windows, node-gyp installs a delay-load
hook that triggers
when the native module is loaded, and redirects the node.dll reference to use
the loading executable instead of looking for node.dll in the library search
path (which would turn up nothing). As such, on Electron 4.x and higher,
'win_delay_load_hook': 'true' is required to load native modules.
If you get an error like Module did not self-register, or The specified procedure could not be found, it may mean that the module you're trying to use
did not correctly include the delay-load hook. If the module is built with
node-gyp, ensure that the win_delay_load_hook variable is set to true in
the binding.gyp file, and isn't getting overridden anywhere. If the module
is built with another system, you'll need to ensure that you build with a
delay-load hook installed in the main .node file. Your link.exe invocation
should look like this:
link.exe /OUT:"foo.node" "...\node.lib" delayimp.lib /DELAYLOAD:node.exe /DLL
"my_addon.obj" "win_delay_load_hook.obj"
In particular, it's important that:
- you link against
node.libfrom Electron and not Node. If you link against the wrongnode.libyou will get load-time errors when you require the module in Electron. - you include the flag
/DELAYLOAD:node.exe. If thenode.exelink is not delayed, then the delay-load hook won't get a chance to fire and the node symbols won't be correctly resolved. win_delay_load_hook.objis linked directly into the final DLL. If the hook is set up in a dependent DLL, it won't fire at the right time.
See node-gyp
for an example delay-load hook if you're implementing your own.
Modules that rely on prebuild
prebuild provides a way to publish
native Node modules with prebuilt binaries for multiple versions of Node
and Electron.
If modules provide binaries for the usage in Electron, make sure to omit
--build-from-source and the npm_config_build_from_source environment
variable in order to take full advantage of the prebuilt binaries.
Modules that rely on node-pre-gyp
The node-pre-gyp tool provides a way to deploy native Node
modules with prebuilt binaries, and many popular modules are using it.
Usually those modules work fine under Electron, but sometimes when Electron uses
a newer version of V8 than Node and/or there are ABI changes, bad things may
happen. So in general, it is recommended to always build native modules from
source code. electron-rebuild handles this for you automatically.
If you are following the npm way of installing modules, then this is done
by default, if not, you have to pass --build-from-source to npm, or set the
npm_config_build_from_source environment variable.
Using Pepper Flash Plugin
Electron no longer supports the Pepper Flash plugin, as Chrome has removed support.
See Chromium's Flash Roadmap for more details.
Using Selenium and WebDriver
From ChromeDriver - WebDriver for Chrome:
WebDriver is an open source tool for automated testing of web apps across many browsers. It provides capabilities for navigating to web pages, user input, JavaScript execution, and more. ChromeDriver is a standalone server which implements WebDriver's wire protocol for Chromium. It is being developed by members of the Chromium and WebDriver teams.
Setting up Spectron
Spectron is the officially supported ChromeDriver testing framework for Electron. It is built on top of WebdriverIO and has helpers to access Electron APIs in your tests and bundles ChromeDriver.
$ npm install --save-dev spectron
// A simple test to verify a visible window is opened with a title
const Application = require('spectron').Application
const assert = require('assert')
const myApp = new Application({
path: '/Applications/MyApp.app/Contents/MacOS/MyApp'
})
const verifyWindowIsVisibleWithTitle = async (app) => {
await app.start()
try {
// Check if the window is visible
const isVisible = await app.browserWindow.isVisible()
// Verify the window is visible
assert.strictEqual(isVisible, true)
// Get the window's title
const title = await app.client.getTitle()
// Verify the window's title
assert.strictEqual(title, 'My App')
} catch (error) {
// Log any failures
console.error('Test failed', error.message)
}
// Stop the application
await app.stop()
}
verifyWindowIsVisibleWithTitle(myApp)
Setting up with WebDriverJs
WebDriverJs provides a Node package for testing with web driver, we will use it as an example.
1. Start ChromeDriver
First you need to download the chromedriver binary, and run it:
$ npm install electron-chromedriver
$ ./node_modules/.bin/chromedriver
Starting ChromeDriver (v2.10.291558) on port 9515
Only local connections are allowed.
Remember the port number 9515, which will be used later
2. Install WebDriverJS
$ npm install selenium-webdriver
3. Connect to ChromeDriver
The usage of selenium-webdriver with Electron is the same with
upstream, except that you have to manually specify how to connect
chrome driver and where to find Electron's binary:
const webdriver = require('selenium-webdriver')
const driver = new webdriver.Builder()
// The "9515" is the port opened by chrome driver.
.usingServer('http://localhost:9515')
.withCapabilities({
chromeOptions: {
// Here is the path to your Electron binary.
binary: '/Path-to-Your-App.app/Contents/MacOS/Electron'
}
})
.forBrowser('electron')
.build()
driver.get('http://www.google.com')
driver.findElement(webdriver.By.name('q')).sendKeys('webdriver')
driver.findElement(webdriver.By.name('btnG')).click()
driver.wait(() => {
return driver.getTitle().then((title) => {
return title === 'webdriver - Google Search'
})
}, 1000)
driver.quit()
Setting up with WebdriverIO
WebdriverIO provides a Node package for testing with web driver.
1. Start ChromeDriver
First you need to download the chromedriver binary, and run it:
$ npm install electron-chromedriver
$ ./node_modules/.bin/chromedriver --url-base=wd/hub --port=9515
Starting ChromeDriver (v2.10.291558) on port 9515
Only local connections are allowed.
Remember the port number 9515, which will be used later
2. Install WebdriverIO
$ npm install webdriverio
3. Connect to chrome driver
const webdriverio = require('webdriverio')
const options = {
host: 'localhost', // Use localhost as chrome driver server
port: 9515, // "9515" is the port opened by chrome driver.
desiredCapabilities: {
browserName: 'chrome',
'goog:chromeOptions': {
binary: '/Path-to-Your-App/electron', // Path to your Electron binary.
args: [/* cli arguments */] // Optional, perhaps 'app=' + /path/to/your/app/
}
}
}
const client = webdriverio.remote(options)
client
.init()
.url('http://google.com')
.setValue('#q', 'webdriverio')
.click('#btnG')
.getTitle().then((title) => {
console.log('Title was: ' + title)
})
.end()
Workflow
To test your application without rebuilding Electron, place your app source into Electron's resource directory.
Alternatively, pass an argument to run with your Electron binary that points to your app's folder. This eliminates the need to copy-paste your app into Electron's resource directory.
V8 Development
A collection of resources for learning and using V8
- V8 Tracing
- V8 Profiler - Profiler combinations which are useful for profiling:
--prof,--trace-ic,--trace-opt,--trace-deopt,--print-bytecode,--print-opt-code - V8 Interpreter Design
- Optimizing compiler
- V8 GDB Debugging
See also Chromium Development
webContents
Render and control web pages.
Process: Main
webContents is an EventEmitter.
It is responsible for rendering and controlling a web page and is a property of
the BrowserWindow object. An example of accessing the
webContents object:
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 1500 })
win.loadURL('http://github.com')
let contents = win.webContents
console.log(contents)
Methods
These methods can be accessed from the webContents module:
const { webContents } = require('electron')
console.log(webContents)
webContents.getAllWebContents()
Returns WebContents[] - An array of all WebContents instances. This will contain web contents
for all windows, webviews, opened devtools, and devtools extension background pages.
webContents.getFocusedWebContents()
Returns WebContents - The web contents that is focused in this application, otherwise
returns null.
Event: 'did-finish-load'
Emitted when the navigation is done, i.e. the spinner of the tab has stopped
spinning, and the onload event was dispatched.
Event: 'did-fail-load'
Returns:
eventEventerrorCodeIntegererrorDescriptionStringvalidatedURLStringisMainFrameBooleanframeProcessIdIntegerframeRoutingIdInteger
This event is like did-finish-load but emitted when the load failed.
The full list of error codes and their meaning is available here.
Event: 'did-fail-provisional-load'
Returns:
eventEventerrorCodeIntegererrorDescriptionStringvalidatedURLStringisMainFrameBooleanframeProcessIdIntegerframeRoutingIdInteger
This event is like did-fail-load but emitted when the load was cancelled
(e.g. window.stop() was invoked).
Event: 'did-frame-finish-load'
Returns:
eventEventisMainFrameBooleanframeProcessIdIntegerframeRoutingIdInteger
Emitted when a frame has done navigation.
Event: 'did-start-loading'
Corresponds to the points in time when the spinner of the tab started spinning.
Event: 'did-stop-loading'
Corresponds to the points in time when the spinner of the tab stopped spinning.
Event: 'page-title-updated'
Returns:
eventEventtitleStringexplicitSetBoolean
Fired when page title is set during navigation. explicitSet is false when
title is synthesized from file url.
Event: 'page-favicon-updated'
Returns:
eventEventfaviconsString[] - Array of URLs.
Emitted when page receives favicon urls.
Event: 'new-window'
Returns:
eventNewWindowWebContentsEventurlStringframeNameStringdispositionString - Can bedefault,foreground-tab,background-tab,new-window,save-to-diskandother.optionsBrowserWindowConstructorOptions - The options which will be used for creating the newBrowserWindow.additionalFeaturesString[] - The non-standard features (features not handled by Chromium or Electron) given towindow.open().referrerReferrer - The referrer that will be passed to the new window. May or may not result in theRefererheader being sent, depending on the referrer policy.postBodyPostBody (optional) - The post data that will be sent to the new window, along with the appropriate headers that will be set. If no post data is to be sent, the value will benull. Only defined when the window is being created by a form that settarget=_blank.
Emitted when the page requests to open a new window for a url. It could be
requested by window.open or an external link like <a target='_blank'>.
By default a new BrowserWindow will be created for the url.
Calling event.preventDefault() will prevent Electron from automatically creating a
new BrowserWindow. If you call event.preventDefault() and manually create a new
BrowserWindow then you must set event.newGuest to reference the new BrowserWindow
instance, failing to do so may result in unexpected behavior. For example:
myBrowserWindow.webContents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures, referrer, postBody) => {
event.preventDefault()
const win = new BrowserWindow({
webContents: options.webContents, // use existing webContents if provided
show: false
})
win.once('ready-to-show', () => win.show())
if (!options.webContents) {
const loadOptions = {
httpReferrer: referrer
}
if (postBody != null) {
const { data, contentType, boundary } = postBody
loadOptions.postData = postBody.data
loadOptions.extraHeaders = `content-type: ${contentType}; boundary=${boundary}`
}
win.loadURL(url, loadOptions) // existing webContents will be navigated automatically
}
event.newGuest = win
})
Event: 'will-navigate'
Returns:
eventEventurlString
Emitted when a user or the page wants to start navigation. It can happen when
the window.location object is changed or a user clicks a link in the page.
This event will not emit when the navigation is started programmatically with
APIs like webContents.loadURL and webContents.back.
It is also not emitted for in-page navigations, such as clicking anchor links
or updating the window.location.hash. Use did-navigate-in-page event for
this purpose.
Calling event.preventDefault() will prevent the navigation.
Event: 'did-start-navigation'
Returns:
eventEventurlStringisInPlaceBooleanisMainFrameBooleanframeProcessIdIntegerframeRoutingIdInteger
Emitted when any frame (including main) starts navigating. isInplace will be
true for in-page navigations.
Event: 'will-redirect'
Returns:
eventEventurlStringisInPlaceBooleanisMainFrameBooleanframeProcessIdIntegerframeRoutingIdInteger
Emitted as a server side redirect occurs during navigation. For example a 302 redirect.
This event will be emitted after did-start-navigation and always before the
did-redirect-navigation event for the same navigation.
Calling event.preventDefault() will prevent the navigation (not just the
redirect).
Event: 'did-redirect-navigation'
Returns:
eventEventurlStringisInPlaceBooleanisMainFrameBooleanframeProcessIdIntegerframeRoutingIdInteger
Emitted after a server side redirect occurs during navigation. For example a 302 redirect.
This event can not be prevented, if you want to prevent redirects you should
checkout out the will-redirect event above.
Event: 'did-navigate'
Returns:
eventEventurlStringhttpResponseCodeInteger - -1 for non HTTP navigationshttpStatusTextString - empty for non HTTP navigations
Emitted when a main frame navigation is done.
This event is not emitted for in-page navigations, such as clicking anchor links
or updating the window.location.hash. Use did-navigate-in-page event for
this purpose.
Event: 'did-frame-navigate'
Returns:
eventEventurlStringhttpResponseCodeInteger - -1 for non HTTP navigationshttpStatusTextString - empty for non HTTP navigations,isMainFrameBooleanframeProcessIdIntegerframeRoutingIdInteger
Emitted when any frame navigation is done.
This event is not emitted for in-page navigations, such as clicking anchor links
or updating the window.location.hash. Use did-navigate-in-page event for
this purpose.
Event: 'did-navigate-in-page'
Returns:
eventEventurlStringisMainFrameBooleanframeProcessIdIntegerframeRoutingIdInteger
Emitted when an in-page navigation happened in any frame.
When in-page navigation happens, the page URL changes but does not cause
navigation outside of the page. Examples of this occurring are when anchor links
are clicked or when the DOM hashchange event is triggered.
Event: 'will-prevent-unload'
Returns:
eventEvent
Emitted when a beforeunload event handler is attempting to cancel a page unload.
Calling event.preventDefault() will ignore the beforeunload event handler
and allow the page to be unloaded.
const { BrowserWindow, dialog } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('will-prevent-unload', (event) => {
const choice = dialog.showMessageBoxSync(win, {
type: 'question',
buttons: ['Leave', 'Stay'],
title: 'Do you want to leave this site?',
message: 'Changes you made may not be saved.',
defaultId: 0,
cancelId: 1
})
const leave = (choice === 0)
if (leave) {
event.preventDefault()
}
})
Event: 'crashed' Deprecated
Returns:
eventEventkilledBoolean
Emitted when the renderer process crashes or is killed.
Deprecated: This event is superceded by the render-process-gone event
which contains more information about why the render process dissapeared. 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:
eventEventdetailsObjectreasonString - 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 dissapears. This is normally because it was crashed or killed.
Event: 'unresponsive'
Emitted when the web page becomes unresponsive.
Event: 'responsive'
Emitted when the unresponsive web page becomes responsive again.
Event: 'plugin-crashed'
Returns:
eventEventnameStringversionString
Emitted when a plugin process has crashed.
Event: 'destroyed'
Emitted when webContents is destroyed.
Event: 'before-input-event'
Returns:
eventEventinputObject - Input properties.typeString - EitherkeyUporkeyDown.keyString - Equivalent to KeyboardEvent.key.codeString - Equivalent to KeyboardEvent.code.isAutoRepeatBoolean - Equivalent to KeyboardEvent.repeat.isComposingBoolean - Equivalent to KeyboardEvent.isComposing.shiftBoolean - Equivalent to KeyboardEvent.shiftKey.controlBoolean - Equivalent to KeyboardEvent.controlKey.altBoolean - Equivalent to KeyboardEvent.altKey.metaBoolean - Equivalent to KeyboardEvent.metaKey.
Emitted before dispatching the keydown and keyup events in the page.
Calling event.preventDefault will prevent the page keydown/keyup events
and the menu shortcuts.
To only prevent the menu shortcuts, use
setIgnoreMenuShortcuts:
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('before-input-event', (event, input) => {
// For example, only enable application menu keyboard shortcuts when
// Ctrl/Cmd are down.
win.webContents.setIgnoreMenuShortcuts(!input.control && !input.meta)
})
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: 'zoom-changed'
Returns:
eventEventzoomDirectionString - Can beinorout.
Emitted when the user is requesting to change the zoom level using the mouse wheel.
Event: 'devtools-opened'
Emitted when DevTools is opened.
Event: 'devtools-closed'
Emitted when DevTools is closed.
Event: 'devtools-focused'
Emitted when DevTools is focused / opened.
Event: 'certificate-error'
Returns:
eventEventurlStringerrorString - The error code.certificateCertificatecallbackFunctionisTrustedBoolean - Indicates whether the certificate can be considered trusted.
Emitted when failed to verify the certificate for url.
The usage is the same with the certificate-error event of
app.
Event: 'select-client-certificate'
Returns:
eventEventurlURLcertificateListCertificate[]callbackFunctioncertificateCertificate - Must be a certificate from the given list.
Emitted when a client certificate is requested.
The usage is the same with the select-client-certificate event of
app.
Event: 'login'
Returns:
eventEventauthenticationResponseDetailsObjecturlURL
authInfoObjectisProxyBooleanschemeStringhostStringportIntegerrealmString
callbackFunctionusernameString (optional)passwordString (optional)
Emitted when webContents wants to do basic auth.
The usage is the same with the login event of app.
Event: 'found-in-page'
Returns:
eventEventresultObjectrequestIdIntegeractiveMatchOrdinalInteger - Position of the active match.matchesInteger - Number of Matches.selectionAreaRectangle - Coordinates of first match region.finalUpdateBoolean
Emitted when a result is available for
[webContents.findInPage] request.
Event: 'media-started-playing'
Emitted when media starts playing.
Event: 'media-paused'
Emitted when media is paused or done playing.
Event: 'did-change-theme-color'
Returns:
eventEventcolor(String | null) - Theme color is in format of '#rrggbb'. It isnullwhen no theme color is set.
Emitted when a page's theme color changes. This is usually due to encountering a meta tag:
<meta name='theme-color' content='#ff0000'>
Event: 'update-target-url'
Returns:
eventEventurlString
Emitted when mouse moves over a link or the keyboard moves the focus to a link.
Event: 'cursor-changed'
Returns:
eventEventtypeStringimageNativeImage (optional)scaleFloat (optional) - scaling factor for the custom cursor.sizeSize (optional) - the size of theimage.hotspotPoint (optional) - coordinates of the custom cursor's hotspot.
Emitted when the cursor's type changes. The type parameter can be default,
crosshair, pointer, text, wait, help, e-resize, n-resize,
ne-resize, nw-resize, s-resize, se-resize, sw-resize, w-resize,
ns-resize, ew-resize, nesw-resize, nwse-resize, col-resize,
row-resize, m-panning, e-panning, n-panning, ne-panning, nw-panning,
s-panning, se-panning, sw-panning, w-panning, move, vertical-text,
cell, context-menu, alias, progress, nodrop, copy, none,
not-allowed, zoom-in, zoom-out, grab, grabbing or custom.
If the type parameter is custom, the image parameter will hold the custom
cursor image in a NativeImage, and scale, size and hotspot will hold
additional information about the custom cursor.
Event: 'context-menu'
Returns:
eventEventparamsObjectxInteger - x coordinate.yInteger - y coordinate.linkURLString - URL of the link that encloses the node the context menu was invoked on.linkTextString - Text associated with the link. May be an empty string if the contents of the link are an image.pageURLString - URL of the top level page that the context menu was invoked on.frameURLString - URL of the subframe that the context menu was invoked on.srcURLString - Source URL for the element that the context menu was invoked on. Elements with source URLs are images, audio and video.mediaTypeString - Type of the node the context menu was invoked on. Can benone,image,audio,video,canvas,fileorplugin.hasImageContentsBoolean - Whether the context menu was invoked on an image which has non-empty contents.isEditableBoolean - Whether the context is editable.selectionTextString - Text of the selection that the context menu was invoked on.titleTextString - Title or alt text of the selection that the context was invoked on.misspelledWordString - The misspelled word under the cursor, if any.dictionarySuggestionsString[] - An array of suggested words to show the user to replace themisspelledWord. Only available if there is a misspelled word and spellchecker is enabled.frameCharsetString - The character encoding of the frame on which the menu was invoked.inputFieldTypeString - If the context menu was invoked on an input field, the type of that field. Possible values arenone,plainText,password,other.menuSourceTypeString - Input source that invoked the context menu. Can benone,mouse,keyboard,touchortouchMenu.mediaFlagsObject - The flags for the media element the context menu was invoked on.inErrorBoolean - Whether the media element has crashed.isPausedBoolean - Whether the media element is paused.isMutedBoolean - Whether the media element is muted.hasAudioBoolean - Whether the media element has audio.isLoopingBoolean - Whether the media element is looping.isControlsVisibleBoolean - Whether the media element's controls are visible.canToggleControlsBoolean - Whether the media element's controls are toggleable.canRotateBoolean - Whether the media element can be rotated.
editFlagsObject - These flags indicate whether the renderer believes it is able to perform the corresponding action.canUndoBoolean - Whether the renderer believes it can undo.canRedoBoolean - Whether the renderer believes it can redo.canCutBoolean - Whether the renderer believes it can cut.canCopyBoolean - Whether the renderer believes it can copycanPasteBoolean - Whether the renderer believes it can paste.canDeleteBoolean - Whether the renderer believes it can delete.canSelectAllBoolean - Whether the renderer believes it can select all.
Emitted when there is a new context menu that needs to be handled.
Event: 'select-bluetooth-device'
Returns:
eventEventdevicesBluetoothDevice[]callbackFunctiondeviceIdString
Emitted when bluetooth device needs to be selected on call to
navigator.bluetooth.requestDevice. To use navigator.bluetooth api
webBluetooth should be enabled. If event.preventDefault is not called,
first available device will be selected. callback should be called with
deviceId to be selected, passing empty string to callback will
cancel the request.
const { app, BrowserWindow } = require('electron')
let win = null
app.commandLine.appendSwitch('enable-experimental-web-platform-features')
app.whenReady().then(() => {
win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
event.preventDefault()
let result = deviceList.find((device) => {
return device.deviceName === 'test'
})
if (!result) {
callback('')
} else {
callback(result.deviceId)
}
})
})
Event: 'paint'
Returns:
eventEventdirtyRectRectangleimageNativeImage - The image data of the whole frame.
Emitted when a new frame is generated. Only the dirty area is passed in the buffer.
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ webPreferences: { offscreen: true } })
win.webContents.on('paint', (event, dirty, image) => {
// updateBitmap(dirty, image.getBitmap())
})
win.loadURL('http://github.com')
Event: 'devtools-reload-page'
Emitted when the devtools window instructs the webContents to reload
Event: 'will-attach-webview'
Returns:
eventEventwebPreferencesWebPreferences - The web preferences that will be used by the guest page. This object can be modified to adjust the preferences for the guest page.paramsRecord<string, string> - The other<webview>parameters such as thesrcURL. This object can be modified to adjust the parameters of the guest page.
Emitted when a <webview>'s web contents is being attached to this web
contents. Calling event.preventDefault() will destroy the guest page.
This event can be used to configure webPreferences for the webContents
of a <webview> before it's loaded, and provides the ability to set settings
that can't be set via <webview> attributes.
Note: The specified preload script option will be appear as preloadURL
(not preload) in the webPreferences object emitted with this event.
Event: 'did-attach-webview'
Returns:
eventEventwebContentsWebContents - The guest web contents that is used by the<webview>.
Emitted when a <webview> has been attached to this web contents.
Event: 'console-message'
Returns:
eventEventlevelIntegermessageStringlineIntegersourceIdString
Emitted when the associated window logs a console message.
Event: 'preload-error'
Returns:
eventEventpreloadPathStringerrorError
Emitted when the preload script preloadPath throws an unhandled exception error.
Event: 'ipc-message'
Returns:
eventEventchannelString...argsany[]
Emitted when the renderer process sends an asynchronous message via ipcRenderer.send().
Event: 'ipc-message-sync'
Returns:
eventEventchannelString...argsany[]
Emitted when the renderer process sends a synchronous message via ipcRenderer.sendSync().
Event: 'desktop-capturer-get-sources'
Returns:
eventEvent
Emitted when desktopCapturer.getSources() is called in the renderer process.
Calling event.preventDefault() will make it return empty sources.
Event: 'remote-require'
Returns:
eventIpcMainEventmoduleNameString
Emitted when remote.require() is called in the renderer process.
Calling event.preventDefault() will prevent the module from being returned.
Custom value can be returned by setting event.returnValue.
Event: 'remote-get-global'
Returns:
eventIpcMainEventglobalNameString
Emitted when remote.getGlobal() is called in the renderer process.
Calling event.preventDefault() will prevent the global from being returned.
Custom value can be returned by setting event.returnValue.
Event: 'remote-get-builtin'
Returns:
eventIpcMainEventmoduleNameString
Emitted when remote.getBuiltin() is called in the renderer process.
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:
eventIpcMainEvent
Emitted when remote.getCurrentWindow() is called in the renderer process.
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:
eventIpcMainEvent
Emitted when remote.getCurrentWebContents() is called in the renderer process.
Calling event.preventDefault() will prevent the object from being returned.
Custom value can be returned by setting event.returnValue.
contents.loadURL(url[, options])
urlStringoptionsObject (optional)httpReferrer(String | Referrer) (optional) - An HTTP Referrer url.userAgentString (optional) - A user agent originating the request.extraHeadersString (optional) - Extra headers separated by "\n".postData(UploadRawData[] | UploadFile[] | UploadBlob[]) (optional)baseURLForDataURLString (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specifiedurlis 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). A noop rejection handler is already attached, which avoids unhandled rejection errors.
Loads the url in the window. The url must contain the protocol prefix,
e.g. the http:// or file://. If the load should bypass http cache then
use the pragma header to achieve it.
const { webContents } = require('electron')
const options = { extraHeaders: 'pragma: no-cache\n' }
webContents.loadURL('https://github.com', options)
contents.loadFile(filePath[, options])
filePathStringoptionsObject (optional)queryRecord<String, String> (optional) - Passed tourl.format().searchString (optional) - Passed tourl.format().hashString (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).
Loads the given file in the window, filePath should be a path to
an HTML file relative to the root of your application. For instance
an app structure like this:
| root
| - package.json
| - src
| - main.js
| - index.html
Would require code like this
win.loadFile('src/index.html')
contents.downloadURL(url)
urlString
Initiates a download of the resource at url without navigating. The
will-download event of session will be triggered.
contents.getURL()
Returns String - The URL of the current web page.
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com').then(() => {
const currentURL = win.webContents.getURL()
console.log(currentURL)
})
contents.getTitle()
Returns String - The title of the current web page.
contents.isDestroyed()
Returns Boolean - Whether the web page is destroyed.
contents.focus()
Focuses the web page.
contents.isFocused()
Returns Boolean - Whether the web page is focused.
contents.isLoading()
Returns Boolean - Whether web page is still loading resources.
contents.isLoadingMainFrame()
Returns Boolean - Whether the main frame (and not just iframes or frames within it) is
still loading.
contents.isWaitingForResponse()
Returns Boolean - Whether the web page is waiting for a first-response from the main
resource of the page.
contents.stop()
Stops any pending navigation.
contents.reload()
Reloads the current web page.
contents.reloadIgnoringCache()
Reloads current page and ignores cache.
contents.canGoBack()
Returns Boolean - Whether the browser can go back to previous web page.
contents.canGoForward()
Returns Boolean - Whether the browser can go forward to next web page.
contents.canGoToOffset(offset)
offsetInteger
Returns Boolean - Whether the web page can go to offset.
contents.clearHistory()
Clears the navigation history.
contents.goBack()
Makes the browser go back a web page.
contents.goForward()
Makes the browser go forward a web page.
contents.goToOffset(offset)
offsetInteger
Navigates to the specified offset from the "current entry".
contents.isCrashed()
Returns Boolean - Whether the renderer process has crashed.
contents.getUserAgent()
Returns String - The user agent for this web page.
contents.insertCSS(css[, options])
cssStringoptionsObject (optional)cssOriginString (optional) - Can be either 'user' or 'author'; Specifying 'user' enables you to prevent websites from overriding the CSS you insert. Default is 'author'.
Returns Promise<String> - A promise that resolves with a key for the inserted CSS that can later be used to remove the CSS via contents.removeInsertedCSS(key).
Injects CSS into the current web page and returns a unique key for the inserted stylesheet.
contents.on('did-finish-load', () => {
contents.insertCSS('html, body { background-color: #f00; }')
})
contents.removeInsertedCSS(key)
keyString
Returns Promise<void> - Resolves if the removal was successful.
Removes the inserted CSS from the current web page. The stylesheet is identified
by its key, which is returned from contents.insertCSS(css).
contents.on('did-finish-load', async () => {
const key = await contents.insertCSS('html, body { background-color: #f00; }')
contents.removeInsertedCSS(key)
})
contents.executeJavaScript(code[, userGesture])
codeStringuserGestureBoolean (optional) - Default isfalse.
Returns Promise<any> - A promise that resolves with the result of the executed code
or is rejected if the result of the code is a rejected promise.
Evaluates code in page.
In the browser window some HTML APIs like requestFullScreen can only be
invoked by a gesture from the user. Setting userGesture to true will remove
this limitation.
Code execution will be suspended until web page stop loading.
contents.executeJavaScript('fetch("https://jsonplaceholder.typicode.com/users/1").then(resp => resp.json())', true)
.then((result) => {
console.log(result) // Will be the JSON object from the fetch call
})
contents.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture])
worldIdInteger - The ID of the world to run the javascript in,0is the default world,999is the world used by Electron'scontextIsolationfeature. You can provide any integer here.scriptsWebSource[]userGestureBoolean (optional) - Default isfalse.
Returns Promise<any> - A promise that resolves with the result of the executed code
or is rejected if the result of the code is a rejected promise.
Works like executeJavaScript but evaluates scripts in an isolated context.
contents.setIgnoreMenuShortcuts(ignore)
ignoreBoolean
Ignore application menu shortcuts while this web contents is focused.
contents.isAudioMuted()
Returns Boolean - Whether this page has been muted.
contents.isCurrentlyAudible()
Returns Boolean - Whether audio is currently playing.
contents.setZoomFactor(factor)
factorDouble - Zoom factor; default is 1.0.
Changes the zoom factor to the specified factor. Zoom factor is zoom percent divided by 100, so 300% = 3.0.
The factor must be greater than 0.0.
contents.getZoomFactor()
Returns Number - the current zoom factor.
contents.setZoomLevel(level)
levelNumber - Zoom level.
Changes the zoom level to the specified level. The original size is 0 and each
increment above or below represents zooming 20% larger or smaller to default
limits of 300% and 50% of original size, respectively. The formula for this is
scale := 1.2 ^ level.
contents.getZoomLevel()
Returns Number - the current zoom level.
contents.setVisualZoomLevelLimits(minimumLevel, maximumLevel)
minimumLevelNumbermaximumLevelNumber
Returns Promise<void>
Sets the maximum and minimum pinch-to-zoom level.
NOTE: Visual zoom is disabled by default in Electron. To re-enable it, call:
contents.setVisualZoomLevelLimits(1, 3)
contents.undo()
Executes the editing command undo in web page.
contents.redo()
Executes the editing command redo in web page.
contents.cut()
Executes the editing command cut in web page.
contents.copy()
Executes the editing command copy in web page.
contents.copyImageAt(x, y)
xIntegeryInteger
Copy the image at the given position to the clipboard.
contents.paste()
Executes the editing command paste in web page.
contents.pasteAndMatchStyle()
Executes the editing command pasteAndMatchStyle in web page.
contents.delete()
Executes the editing command delete in web page.
contents.selectAll()
Executes the editing command selectAll in web page.
contents.unselect()
Executes the editing command unselect in web page.
contents.replaceMisspelling(text)
textString
Executes the editing command replaceMisspelling in web page.
contents.findInPage(text[, options])
textString - Content to be searched, must not be empty.optionsObject (optional)forwardBoolean (optional) - Whether to search forward or backward, defaults totrue.findNextBoolean (optional) - Whether the operation is first request or a follow up, defaults tofalse.matchCaseBoolean (optional) - Whether search should be case-sensitive, defaults tofalse.wordStartBoolean (optional) - Whether to look only at the start of words. defaults tofalse.medialCapitalAsWordStartBoolean (optional) - When combined withwordStart, accepts a match in the middle of a word if the match begins with an uppercase letter followed by a lowercase or non-letter. Accepts several other intra-word matches, defaults tofalse.
Returns Integer - The request id used for the request.
Starts a request to find all matches for the text in the web page. The result of the request
can be obtained by subscribing to found-in-page event.
contents.stopFindInPage(action)
actionString - Specifies the action to take place when ending [webContents.findInPage] request.clearSelection- Clear the selection.keepSelection- Translate the selection into a normal selection.activateSelection- Focus and click the selection node.
Stops any findInPage request for the webContents with the provided action.
const { webContents } = require('electron')
webContents.on('found-in-page', (event, result) => {
if (result.finalUpdate) webContents.stopFindInPage('clearSelection')
})
const requestId = webContents.findInPage('api')
console.log(requestId)
contents.capturePage([rect])
rectRectangle (optional) - The area of the page to be captured.
Returns Promise<NativeImage> - Resolves with a NativeImage
Captures a snapshot of the page within rect. Omitting rect will capture the whole visible page.
contents.isBeingCaptured()
Returns Boolean - Whether this page is being captured. It returns true when the capturer count
is large then 0.
contents.incrementCapturerCount([size, stayHidden])
sizeSize (optional) - The perferred size for the capturer.stayHiddenBoolean (optional) - Keep the page hidden instead of visible.
Increase the capturer count by one. The page is considered visible when its browser window is
hidden and the capturer count is non-zero. If you would like the page to stay hidden, you should ensure that stayHidden is set to true.
This also affects the Page Visibility API.
contents.decrementCapturerCount([stayHidden])
stayHiddenBoolean (optional) - Keep the page in hidden state instead of visible.
Decrease the capturer count by one. The page will be set to hidden or occluded state when its
browser window is hidden or occluded and the capturer count reaches zero. If you want to
decrease the hidden capturer count instead you should set stayHidden to true.
contents.print([options], [callback])
optionsObject (optional)silentBoolean (optional) - Don't ask user for print settings. Default isfalse.printBackgroundBoolean (optional) - Prints the background color and image of the web page. Default isfalse.deviceNameString (optional) - Set the printer device name to use. Must be the system-defined name and not the 'friendly' name, e.g 'Brother_QL_820NWB' and not 'Brother QL-820NWB'.colorBoolean (optional) - Set whether the printed web page will be in color or grayscale. Default istrue.marginsObject (optional)marginTypeString (optional) - Can bedefault,none,printableArea, orcustom. Ifcustomis chosen, you will also need to specifytop,bottom,left, andright.topNumber (optional) - The top margin of the printed web page, in pixels.bottomNumber (optional) - The bottom margin of the printed web page, in pixels.leftNumber (optional) - The left margin of the printed web page, in pixels.rightNumber (optional) - The right margin of the printed web page, in pixels.
landscapeBoolean (optional) - Whether the web page should be printed in landscape mode. Default isfalse.scaleFactorNumber (optional) - The scale factor of the web page.pagesPerSheetNumber (optional) - The number of pages to print per page sheet.collateBoolean (optional) - Whether the web page should be collated.copiesNumber (optional) - The number of copies of the web page to print.pageRangesObject[] (optional) - The page range to print. On macOS, only one range is honored.fromNumber - Index of the first page to print (0-based).toNumber - Index of the last page to print (inclusive) (0-based).
duplexModeString (optional) - Set the duplex mode of the printed web page. Can besimplex,shortEdge, orlongEdge.dpiRecord<string, number> (optional)horizontalNumber (optional) - The horizontal dpi.verticalNumber (optional) - The vertical dpi.
headerString (optional) - String to be printed as page header.footerString (optional) - String to be printed as page footer.pageSizeString | Size (optional) - Specify page size of the printed document. Can beA3,A4,A5,Legal,Letter,Tabloidor an Object containingheight.
callbackFunction (optional)successBoolean - Indicates success of the print call.failureReasonString - Error description called back if the print fails.
When a custom pageSize is passed, Chromium attempts to validate platform specific minumum values for width_microns and height_microns. Width and height must both be minimum 353 microns but may be higher on some operating systems.
Prints window's web page. When silent is set to true, Electron will pick
the system's default printer if deviceName is empty and the default settings for printing.
Use page-break-before: always; CSS style to force to print to a new page.
Example usage:
const options = { silent: true, deviceName: 'My-Printer' }
win.webContents.print(options, (success, errorType) => {
if (!success) console.log(errorType)
})
contents.printToPDF(options)
optionsObjectheaderFooterRecord<string, string> (optional) - the header and footer for the PDF.titleString - The title for the PDF header.urlString - the url for the PDF footer.
landscapeBoolean (optional) -truefor landscape,falsefor portrait.marginsTypeInteger (optional) - Specifies the type of margins to use. Uses 0 for default margin, 1 for no margin, and 2 for minimum margin.scaleFactorNumber (optional) - The scale factor of the web page. Can range from 0 to 100.pageRangesRecord<string, number> (optional) - The page range to print.fromNumber - Index of the first page to print (0-based).toNumber - Index of the last page to print (inclusive) (0-based).
pageSizeString | Size (optional) - Specify page size of the generated PDF. Can beA3,A4,A5,Legal,Letter,Tabloidor an Object containingheightandwidthin microns.printBackgroundBoolean (optional) - Whether to print CSS backgrounds.printSelectionOnlyBoolean (optional) - Whether to print selection only.
Returns Promise<Buffer> - Resolves with the generated PDF data.
Prints window's web page as PDF with Chromium's preview printing custom settings.
The landscape will be ignored if @page CSS at-rule is used in the web page.
By default, an empty options will be regarded as:
{
marginsType: 0,
printBackground: false,
printSelectionOnly: false,
landscape: false,
pageSize: 'A4',
scaleFactor: 100
}
Use page-break-before: always; CSS style to force to print to a new page.
An example of webContents.printToPDF:
const { BrowserWindow } = require('electron')
const fs = require('fs')
const path = require('path')
const os = require('os')
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
win.webContents.on('did-finish-load', () => {
// Use default printing options
win.webContents.printToPDF({}).then(data => {
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
fs.writeFile(pdfPath, data, (error) => {
if (error) throw error
console.log(`Wrote PDF successfully to ${pdfPath}`)
})
}).catch(error => {
console.log(`Failed to write PDF to ${pdfPath}: `, error)
})
})
contents.addWorkSpace(path)
pathString
Adds the specified path to DevTools workspace. Must be used after DevTools creation:
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
win.webContents.on('devtools-opened', () => {
win.webContents.addWorkSpace(__dirname)
})
contents.setDevToolsWebContents(devToolsWebContents)
devToolsWebContentsWebContents
Uses the devToolsWebContents as the target WebContents to show devtools.
The devToolsWebContents must not have done any navigation, and it should not
be used for other purposes after the call.
By default Electron manages the devtools by creating an internal WebContents
with native view, which developers have very limited control of. With the
setDevToolsWebContents method, developers can use any WebContents to show
the devtools in it, including BrowserWindow, BrowserView and <webview>
tag.
Note that closing the devtools does not destroy the devToolsWebContents, it
is caller's responsibility to destroy devToolsWebContents.
An example of showing devtools in a <webview> tag:
<html>
<head>
<style type="text/css">
* { margin: 0; }
#browser { height: 70%; }
#devtools { height: 30%; }
</style>
</head>
<body>
<webview id="browser" src="https://github.com"></webview>
<webview id="devtools" src="about:blank"></webview>
<script>
const { webContents } = require('electron').remote
const emittedOnce = (element, eventName) => new Promise(resolve => {
element.addEventListener(eventName, event => resolve(event), { once: true })
})
const browserView = document.getElementById('browser')
const devtoolsView = document.getElementById('devtools')
const browserReady = emittedOnce(browserView, 'dom-ready')
const devtoolsReady = emittedOnce(devtoolsView, 'dom-ready')
Promise.all([browserReady, devtoolsReady]).then(() => {
const browser = webContents.fromId(browserView.getWebContentsId())
const devtools = webContents.fromId(devtoolsView.getWebContentsId())
browser.setDevToolsWebContents(devtools)
browser.openDevTools()
})
</script>
</body>
</html>
An example of showing devtools in a BrowserWindow:
const { app, BrowserWindow } = require('electron')
let win = null
let devtools = null
app.whenReady().then(() => {
win = new BrowserWindow()
devtools = new BrowserWindow()
win.loadURL('https://github.com')
win.webContents.setDevToolsWebContents(devtools.webContents)
win.webContents.openDevTools({ mode: 'detach' })
})
contents.openDevTools([options])
optionsObject (optional)modeString - Opens the devtools with specified dock state, can beright,bottom,undocked,detach. Defaults to last used dock state. Inundockedmode it's possible to dock back. Indetachmode it's not.activateBoolean (optional) - Whether to bring the opened devtools window to the foreground. The default istrue.
Opens the devtools.
When contents is a <webview> tag, the mode would be detach by default,
explicitly passing an empty mode can force using last used dock state.
contents.closeDevTools()
Closes the devtools.
contents.isDevToolsOpened()
Returns Boolean - Whether the devtools is opened.
contents.isDevToolsFocused()
Returns Boolean - Whether the devtools view is focused .
contents.toggleDevTools()
Toggles the developer tools.
contents.inspectSharedWorker()
Opens the developer tools for the shared worker context.
contents.inspectSharedWorkerById(workerId)
workerIdString
Inspects the shared worker based on its ID.
contents.getAllSharedWorkers()
Returns SharedWorkerInfo[] - Information about all Shared Workers.
contents.inspectServiceWorker()
Opens the developer tools for the service worker context.
contents.send(channel, ...args)
channelString...argsany[]
Send an asynchronous message to the renderer process via channel, along with
arguments. Arguments will be serialized with the Structured Clone
Algorithm, just like 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 renderer process can handle the message by listening to channel with the
ipcRenderer module.
An example of sending messages from the main process to the renderer process:
// In the main process.
const { app, BrowserWindow } = require('electron')
let win = null
app.whenReady().then(() => {
win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL(`file://${__dirname}/index.html`)
win.webContents.on('did-finish-load', () => {
win.webContents.send('ping', 'whoooooooh!')
})
})
<!-- index.html -->
<html>
<body>
<script>
require('electron').ipcRenderer.on('ping', (event, message) => {
console.log(message) // Prints 'whoooooooh!'
})
</script>
</body>
</html>
contents.sendToFrame(frameId, channel, ...args)
frameIdIntegerchannelString...argsany[]
Send an asynchronous message to a specific frame in a renderer process via
channel, along with arguments. Arguments will be serialized with the
Structured Clone Algorithm, just like 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 renderer process can handle the message by listening to channel with the
ipcRenderer module.
If you want to get the frameId of a given renderer context you should use
the webFrame.routingId value. E.g.
// In a renderer process
console.log('My frameId is:', require('electron').webFrame.routingId)
You can also read frameId from all incoming IPC messages in the main process.
// In the main process
ipcMain.on('ping', (event) => {
console.info('Message came from frameId:', event.frameId)
})
contents.postMessage(channel, message, [transfer])
channelStringmessageanytransferMessagePortMain[] (optional)
Send a message to the renderer process, optionally transferring ownership of
zero or more [MessagePortMain][] objects.
The transferred MessagePortMain objects will be available in the renderer
process by accessing the ports property of the emitted event. When they
arrive in the renderer, they will be native DOM MessagePort objects.
For example:
// Main process
const { port1, port2 } = new MessageChannelMain()
webContents.postMessage('port', { message: 'hello' }, [port1])
// Renderer process
ipcRenderer.on('port', (e, msg) => {
const [port] = e.ports
// ...
})
contents.enableDeviceEmulation(parameters)
parametersObjectscreenPositionString - Specify the screen type to emulate (default:desktop):desktop- Desktop screen type.mobile- Mobile screen type.
screenSizeSize - Set the emulated screen size (screenPosition == mobile).viewPositionPoint - Position the view on the screen (screenPosition == mobile) (default:{ x: 0, y: 0 }).deviceScaleFactorInteger - Set the device scale factor (if zero defaults to original device scale factor) (default:0).viewSizeSize - Set the emulated view size (empty means no override)scaleFloat - Scale of emulated view inside available space (not in fit to view mode) (default:1).
Enable device emulation with the given parameters.
contents.disableDeviceEmulation()
Disable device emulation enabled by webContents.enableDeviceEmulation.
contents.sendInputEvent(inputEvent)
inputEventMouseInputEvent | MouseWheelInputEvent | KeyboardInputEvent
Sends an input event to the page.
Note: The BrowserWindow containing the contents needs to be focused for
sendInputEvent() to work.
contents.beginFrameSubscription([onlyDirty ,]callback)
onlyDirtyBoolean (optional) - Defaults tofalse.callbackFunctionimageNativeImagedirtyRectRectangle
Begin subscribing for presentation events and captured frames, the callback
will be called with callback(image, dirtyRect) when there is a presentation
event.
The image is an instance of NativeImage that stores the
captured frame.
The dirtyRect is an object with x, y, width, height properties that
describes which part of the page was repainted. If onlyDirty is set to
true, image will only contain the repainted area. onlyDirty defaults to
false.
contents.endFrameSubscription()
End subscribing for frame presentation events.
contents.startDrag(item)
itemObjectfileString[] | String - The path(s) to the file(s) being dragged.iconNativeImage | String - The image must be non-empty on macOS.
Sets the item as dragging item for current drag-drop operation, file is the
absolute path of the file to be dragged, and icon is the image showing under
the cursor when dragging.
contents.savePage(fullPath, saveType)
fullPathString - The full file path.saveTypeString - Specify the save type.HTMLOnly- Save only the HTML of the page.HTMLComplete- Save complete-html page.MHTML- Save complete-html page as MHTML.
Returns Promise<void> - resolves if the page is saved.
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
win.loadURL('https://github.com')
win.webContents.on('did-finish-load', async () => {
win.webContents.savePage('/tmp/test.html', 'HTMLComplete').then(() => {
console.log('Page was saved successfully.')
}).catch(err => {
console.log(err)
})
})
contents.showDefinitionForSelection() macOS
Shows pop-up dictionary that searches the selected word on the page.
contents.isOffscreen()
Returns Boolean - Indicates whether offscreen rendering is enabled.
contents.startPainting()
If offscreen rendering is enabled and not painting, start painting.
contents.stopPainting()
If offscreen rendering is enabled and painting, stop painting.
contents.isPainting()
Returns Boolean - If offscreen rendering is enabled returns whether it is currently painting.
contents.setFrameRate(fps)
fpsInteger
If offscreen rendering is enabled sets the frame rate to the specified number. Only values between 1 and 60 are accepted.
contents.getFrameRate()
Returns Integer - If offscreen rendering is enabled returns the current frame rate.
contents.invalidate()
Schedules a full repaint of the window this web contents is in.
If offscreen rendering is enabled invalidates the frame and generates a new
one through the 'paint' event.
contents.getWebRTCIPHandlingPolicy()
Returns String - Returns the WebRTC IP Handling Policy.
contents.setWebRTCIPHandlingPolicy(policy)
policyString - Specify the WebRTC IP Handling Policy.default- Exposes user's public and local IPs. This is the default behavior. When this policy is used, WebRTC has the right to enumerate all interfaces and bind them to discover public interfaces.default_public_interface_only- Exposes user's public IP, but does not expose user's local IP. When this policy is used, WebRTC should only use the default route used by http. This doesn't expose any local addresses.default_public_and_private_interfaces- Exposes user's public and local IPs. When this policy is used, WebRTC should only use the default route used by http. This also exposes the associated default private address. Default route is the route chosen by the OS on a multi-homed endpoint.disable_non_proxied_udp- Does not expose public or local IPs. When this policy is used, WebRTC should only use TCP to contact peers or servers unless the proxy server supports UDP.
Setting the WebRTC IP handling policy allows you to control which IPs are exposed via WebRTC. See BrowserLeaks for more details.
contents.getOSProcessId()
Returns Integer - The operating system pid of the associated renderer
process.
contents.getProcessId()
Returns Integer - The Chromium internal pid of the associated renderer. Can
be compared to the frameProcessId passed by frame specific navigation events
(e.g. did-frame-navigate)
contents.takeHeapSnapshot(filePath)
filePathString - Path to the output file.
Returns Promise<void> - Indicates whether the snapshot has been created successfully.
Takes a V8 heap snapshot and saves it to filePath.
contents.getBackgroundThrottling()
Returns Boolean - whether or not this WebContents will throttle animations and timers
when the page becomes backgrounded. This also affects the Page Visibility API.
contents.setBackgroundThrottling(allowed)
allowedBoolean
Controls whether or not this WebContents will throttle animations and timers when the page becomes backgrounded. This also affects the Page Visibility API.
contents.getType()
Returns String - the type of the webContent. Can be backgroundPage, window, browserView, remote, webview or offscreen.
contents.audioMuted
A Boolean property that determines whether this page is muted.
contents.userAgent
A String property that determines the user agent for this web page.
contents.zoomLevel
A Number property that determines the zoom level for this web contents.
The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively. The formula for this is scale := 1.2 ^ level.
contents.zoomFactor
A Number property that determines the zoom factor for this web contents.
The zoom factor is the zoom percent divided by 100, so 300% = 3.0.
contents.frameRate
An Integer property that sets the frame rate of the web contents to the specified number.
Only values between 1 and 60 are accepted.
Only applicable if offscreen rendering is enabled.
contents.id Readonly
A Integer representing the unique ID of this WebContents. Each ID is unique among all WebContents instances of the entire Electron application.
contents.session Readonly
A Session used by this webContents.
contents.hostWebContents Readonly
A WebContents instance that might own this WebContents.
contents.devToolsWebContents Readonly
A WebContents | null property that represents the of DevTools WebContents associated with a given WebContents.
Note: Users should never store this object because it may become null
when the DevTools has been closed.
contents.debugger Readonly
A Debugger instance for this webContents.
contents.backgroundThrottling
A Boolean property that determines whether or not this WebContents will throttle animations and timers
when the page becomes backgrounded. This also affects the Page Visibility API.
Overview
If you want to embed (third-party) web content in an Electron BrowserWindow,
there are three options available to you: <iframe> tags, <webview> tags,
and BrowserViews. Each one offers slightly different functionality and is
useful in different situations. To help you choose between these, this guide
explains the differences and capabilities of each option.
Iframes
Iframes in Electron behave like iframes in regular browsers. An <iframe>
element in your page can show external web pages, provided that their
Content Security Policy
allows it. To limit the number of capabilities of a site in an <iframe> tag,
it is recommended to use the sandbox attribute
and only allow the capabilities you want to support.
WebViews
Important Note: we do not recommend you to use use WebViews, as this tag undergoes dramatic architectural changes that may affect stability of your application. Consider switching to alternatives, like
iframeand Electron'sBrowserView, or an architecture that avoids embedded content by design.
WebViews are based on Chromium's WebViews and are not
explicitly supported by Electron. We do not guarantee that the WebView API will
remain available in future versions of Electron. To use <webview> tags, you
will need to set webviewTag to true in the webPreferences of your
BrowserWindow.
WebView is a custom element (<webview>) that will only work inside Electron.
They are implemented as an "out-of-process iframe". This means that all
communication with the <webview> is done asynchronously using IPC. The
<webview> element has many custom methods and events, similar to
webContents, that provide you with greater control over the content.
Compared to an <iframe>, <webview> tends to be slightly slower but offers
much greater control in loading and communicating with the third-party content
and handling various events.
BrowserViews
BrowserViews are not a part of the DOM - instead,
they are created in and controlled by your Main process. They are simply
another layer of web content on top of your existing window. This means
that they are completely separate from your own BrowserWindow content and
their position is not controlled by the DOM or CSS. Instead, it is controlled
by setting the bounds in the Main process.
BrowserViews offer the greatest control over their contents, since they
implement the webContents similarly to how the BrowserWindow does it.
However, as BrowserViews are not a part of your DOM, but are rather overlaid
on top of them, you will have to manage their position manually.
webFrame
Customize the rendering of the current web page.
Process: Renderer
webFrame export of the Electron module is an instance of the WebFrame
class representing the top frame of the current BrowserWindow. Sub-frames can
be retrieved by certain properties and methods (e.g. webFrame.firstChild).
An example of zooming current page to 200%.
const { webFrame } = require('electron')
webFrame.setZoomFactor(2)
Methods
The WebFrame class has the following instance methods:
webFrame.setZoomFactor(factor)
factorDouble - Zoom factor; default is 1.0.
Changes the zoom factor to the specified factor. Zoom factor is zoom percent divided by 100, so 300% = 3.0.
The factor must be greater than 0.0.
webFrame.getZoomFactor()
Returns Number - The current zoom factor.
webFrame.setZoomLevel(level)
levelNumber - Zoom level.
Changes the zoom level to the specified level. The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively.
webFrame.getZoomLevel()
Returns Number - The current zoom level.
webFrame.setVisualZoomLevelLimits(minimumLevel, maximumLevel)
minimumLevelNumbermaximumLevelNumber
Sets the maximum and minimum pinch-to-zoom level.
NOTE: Visual zoom is disabled by default in Electron. To re-enable it, call:
webFrame.setVisualZoomLevelLimits(1, 3)
webFrame.setSpellCheckProvider(language, provider)
languageStringproviderObjectspellCheckFunctionwordsString[]callbackFunctionmisspeltWordsString[]
Sets a provider for spell checking in input fields and text areas.
If you want to use this method you must disable the builtin spellchecker when you construct the window.
const mainWindow = new BrowserWindow({
webPreferences: {
spellcheck: false
}
})
The provider must be an object that has a spellCheck method that accepts
an array of individual words for spellchecking.
The spellCheck function runs asynchronously and calls the callback function
with an array of misspelt words when complete.
An example of using node-spellchecker as provider:
const { webFrame } = require('electron')
const spellChecker = require('spellchecker')
webFrame.setSpellCheckProvider('en-US', {
spellCheck (words, callback) {
setTimeout(() => {
const spellchecker = require('spellchecker')
const misspelled = words.filter(x => spellchecker.isMisspelled(x))
callback(misspelled)
}, 0)
}
})
webFrame.insertCSS(css)
cssString - CSS source code.
Returns String - A key for the inserted CSS that can later be used to remove
the CSS via webFrame.removeInsertedCSS(key).
Injects CSS into the current web page and returns a unique key for the inserted stylesheet.
webFrame.removeInsertedCSS(key)
keyString
Removes the inserted CSS from the current web page. The stylesheet is identified
by its key, which is returned from webFrame.insertCSS(css).
webFrame.executeJavaScript(code[, userGesture, callback])
codeStringuserGestureBoolean (optional) - Default isfalse.callbackFunction (optional) - Called after script has been executed. Unless the frame is suspended (e.g. showing a modal alert), execution will be synchronous and the callback will be invoked before the method returns. For compatibility with an older version of this method, the error parameter is second.resultAnyerrorError
Returns Promise<any> - A promise that resolves with the result of the executed
code or is rejected if execution throws or results in a rejected promise.
Evaluates code in page.
In the browser window some HTML APIs like requestFullScreen can only be
invoked by a gesture from the user. Setting userGesture to true will remove
this limitation.
webFrame.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture, callback])
worldIdInteger - The ID of the world to run the javascript in,0is the default main world (where content runs),999is the world used by Electron'scontextIsolationfeature. Accepts values in the range 1..536870911.scriptsWebSource[]userGestureBoolean (optional) - Default isfalse.callbackFunction (optional) - Called after script has been executed. Unless the frame is suspended (e.g. showing a modal alert), execution will be synchronous and the callback will be invoked before the method returns. For compatibility with an older version of this method, the error parameter is second.resultAnyerrorError
Returns Promise<any> - A promise that resolves with the result of the executed
code or is rejected if execution could not start.
Works like executeJavaScript but evaluates scripts in an isolated context.
Note that when the execution of script fails, the returned promise will not
reject and the result would be undefined. This is because Chromium does not
dispatch errors of isolated worlds to foreign worlds.
webFrame.setIsolatedWorldInfo(worldId, info)
worldIdInteger - The ID of the world to run the javascript in,0is the default world,999is the world used by ElectronscontextIsolationfeature. Chrome extensions reserve the range of IDs in[1 << 20, 1 << 29). You can provide any integer here.infoObjectsecurityOriginString (optional) - Security origin for the isolated world.cspString (optional) - Content Security Policy for the isolated world.nameString (optional) - Name for isolated world. Useful in devtools.
Set the security origin, content security policy and name of the isolated world.
Note: If the csp is specified, then the securityOrigin also has to be specified.
webFrame.getResourceUsage()
Returns Object:
imagesMemoryUsageDetailsscriptsMemoryUsageDetailscssStyleSheetsMemoryUsageDetailsxslStyleSheetsMemoryUsageDetailsfontsMemoryUsageDetailsotherMemoryUsageDetails
Returns an object describing usage information of Blink's internal memory caches.
const { webFrame } = require('electron')
console.log(webFrame.getResourceUsage())
This will generate:
{
images: {
count: 22,
size: 2549,
liveSize: 2542
},
cssStyleSheets: { /* same with "images" */ },
xslStyleSheets: { /* same with "images" */ },
fonts: { /* same with "images" */ },
other: { /* same with "images" */ }
}
webFrame.clearCache()
Attempts to free memory that is no longer being used (like images from a previous navigation).
Note that blindly calling this method probably makes Electron slower since it will have to refill these emptied caches, you should only call it if an event in your app has occurred that makes you think your page is actually using less memory (i.e. you have navigated from a super heavy page to a mostly empty one, and intend to stay there).
webFrame.getFrameForSelector(selector)
selectorString - CSS selector for a frame element.
Returns WebFrame - The frame element in webFrame's document selected by
selector, null would be returned if selector does not select a frame or
if the frame is not in the current renderer process.
webFrame.findFrameByName(name)
nameString
Returns WebFrame - A child of webFrame with the supplied name, null
would be returned if there's no such frame or if the frame is not in the current
renderer process.
webFrame.findFrameByRoutingId(routingId)
routingIdInteger - AnIntegerrepresenting the unique frame id in the current renderer process. Routing IDs can be retrieved fromWebFrameinstances (webFrame.routingId) and are also passed by frame specificWebContentsnavigation events (e.g.did-frame-navigate)
Returns WebFrame - that has the supplied routingId, null if not found.
webFrame.top Readonly
A WebFrame | null representing top frame in frame hierarchy to which webFrame
belongs, the property would be null if top frame is not in the current
renderer process.
webFrame.opener Readonly
A WebFrame | null representing the frame which opened webFrame, the property would
be null if there's no opener or opener is not in the current renderer process.
webFrame.parent Readonly
A WebFrame | null representing parent frame of webFrame, the property would be
null if webFrame is top or parent is not in the current renderer process.
webFrame.firstChild Readonly
A WebFrame | null representing the first child frame of webFrame, the property
would be null if webFrame has no children or if first child is not in the
current renderer process.
webFrame.nextSibling Readonly
A WebFrame | null representing next sibling frame, the property would be null if
webFrame is the last frame in its parent or if the next sibling is not in the
current renderer process.
webFrame.routingId Readonly
An Integer representing the unique frame id in the current renderer process.
Distinct WebFrame instances that refer to the same underlying frame will have
the same routingId.
Class: WebRequest
Intercept and modify the contents of a request at various stages of its lifetime.
Process: Main
Instances of the WebRequest class are accessed by using the webRequest
property of a Session.
The methods of WebRequest accept an optional filter and a listener. The
listener will be called with listener(details) when the API's event has
happened. The details object describes the request.
⚠️ Only the last attached listener will be used. Passing null as listener will unsubscribe from the event.
The filter object has a urls property which is an Array of URL
patterns that will be used to filter out the requests that do not match the URL
patterns. If the filter is omitted then all requests will be matched.
For certain events the listener is passed with a callback, which should be
called with a response object when listener has done its work.
An example of adding User-Agent header for requests:
const { session } = require('electron')
// Modify the user agent for all requests to the following urls.
const filter = {
urls: ['https://*.github.com/*', '*://electron.github.io']
}
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
details.requestHeaders['User-Agent'] = 'MyAgent'
callback({ requestHeaders: details.requestHeaders })
})
Instance Methods
The following methods are available on instances of WebRequest:
webRequest.onBeforeRequest([filter, ]listener)
filterObject (optional)urlsString[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.
listenerFunction | nulldetailsObjectidIntegerurlStringmethodStringwebContentsIdInteger (optional)resourceTypeStringreferrerStringtimestampDoubleuploadDataUploadData[]
callbackFunctionresponseObjectcancelBoolean (optional)redirectURLString (optional) - The original request is prevented from being sent or completed and is instead redirected to the given URL.
The listener will be called with listener(details, callback) when a request
is about to occur.
The uploadData is an array of UploadData objects.
The callback has to be called with an response object.
Some examples of valid urls:
'http://foo:1234/'
'http://foo.com/'
'http://foo:1234/bar'
'*://*/*'
'*://example.com/*'
'*://example.com/foo/*'
'http://*.foo:1234/'
'file://foo:1234/bar'
'http://foo:*/'
'*://www.foo.com/'
webRequest.onBeforeSendHeaders([filter, ]listener)
filterObject (optional)urlsString[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.
listenerFunction | nulldetailsObjectidIntegerurlStringmethodStringwebContentsIdInteger (optional)resourceTypeStringreferrerStringtimestampDoublerequestHeadersRecord<string, string>
callbackFunctionbeforeSendResponseObjectcancelBoolean (optional)requestHeadersRecord<string, string | string[]> (optional) - When provided, request will be made with these headers.
The listener will be called with listener(details, callback) before sending
an HTTP request, once the request headers are available. This may occur after a
TCP connection is made to the server, but before any http data is sent.
The callback has to be called with a response object.
webRequest.onSendHeaders([filter, ]listener)
filterObject (optional)urlsString[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.
listenerFunction | nulldetailsObjectidIntegerurlStringmethodStringwebContentsIdInteger (optional)resourceTypeStringreferrerStringtimestampDoublerequestHeadersRecord<string, string>
The listener will be called with listener(details) just before a request is
going to be sent to the server, modifications of previous onBeforeSendHeaders
response are visible by the time this listener is fired.
webRequest.onHeadersReceived([filter, ]listener)
filterObject (optional)urlsString[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.
listenerFunction | nulldetailsObjectidIntegerurlStringmethodStringwebContentsIdInteger (optional)resourceTypeStringreferrerStringtimestampDoublestatusLineStringstatusCodeIntegerrequestHeadersRecord<string, string>responseHeadersRecord<string, string[]> (optional)
callbackFunctionheadersReceivedResponseObjectcancelBoolean (optional)responseHeadersRecord<string, string | string[]> (optional) - When provided, the server is assumed to have responded with these headers.statusLineString (optional) - Should be provided when overridingresponseHeadersto change header status otherwise original response header's status will be used.
The listener will be called with listener(details, callback) when HTTP
response headers of a request have been received.
The callback has to be called with a response object.
webRequest.onResponseStarted([filter, ]listener)
filterObject (optional)urlsString[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.
listenerFunction | nulldetailsObjectidIntegerurlStringmethodStringwebContentsIdInteger (optional)resourceTypeStringreferrerStringtimestampDoubleresponseHeadersRecord<string, string[]> (optional)fromCacheBoolean - Indicates whether the response was fetched from disk cache.statusCodeIntegerstatusLineString
The listener will be called with listener(details) when first byte of the
response body is received. For HTTP requests, this means that the status line
and response headers are available.
webRequest.onBeforeRedirect([filter, ]listener)
filterObject (optional)urlsString[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.
listenerFunction | nulldetailsObjectidIntegerurlStringmethodStringwebContentsIdInteger (optional)resourceTypeStringreferrerStringtimestampDoubleredirectURLStringstatusCodeIntegerstatusLineStringipString (optional) - The server IP address that the request was actually sent to.fromCacheBooleanresponseHeadersRecord<string, string[]> (optional)
The listener will be called with listener(details) when a server initiated
redirect is about to occur.
webRequest.onCompleted([filter, ]listener)
filterObject (optional)urlsString[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.
listenerFunction | nulldetailsObjectidIntegerurlStringmethodStringwebContentsIdInteger (optional)resourceTypeStringreferrerStringtimestampDoubleresponseHeadersRecord<string, string[]> (optional)fromCacheBooleanstatusCodeIntegerstatusLineStringerrorString
The listener will be called with listener(details) when a request is
completed.
webRequest.onErrorOccurred([filter, ]listener)
filterObject (optional)urlsString[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.
listenerFunction | nulldetailsObjectidIntegerurlStringmethodStringwebContentsIdInteger (optional)resourceTypeStringreferrerStringtimestampDoublefromCacheBooleanerrorString - The error description.
The listener will be called with listener(details) when an error occurs.
WebSource Object
codeStringurlString (optional)startLineInteger (optional) - Default is 1.
Warning
Electron's webview tag is based on Chromium's webview, which
is undergoing dramatic architectural changes. This impacts the stability of webviews,
including rendering, navigation, and event routing. We currently recommend to not
use the webview tag and to consider alternatives, like iframe, Electron's BrowserView,
or an architecture that avoids embedded content altogether.
Enabling
By default the webview tag is disabled in Electron >= 5. You need to enable the tag by
setting the webviewTag webPreferences option when constructing your BrowserWindow. For
more information see the BrowserWindow constructor docs.
Overview
Display external web content in an isolated frame and process.
Process: Renderer
Use the webview tag to embed 'guest' content (such as web pages) in your
Electron app. The guest content is contained within the webview container.
An embedded page within your app controls how the guest content is laid out and
rendered.
Unlike an iframe, the webview runs in a separate process than your
app. 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. Note: Most methods called on the
webview from the host page require a synchronous call to the main process.
Example
To embed a web page in your app, add the webview tag to your app's embedder
page (this is the app page that will display the guest content). In its simplest
form, the webview tag includes the src of the web page and css styles that
control the appearance of the webview container:
<webview id="foo" src="https://www.github.com/" style="display:inline-flex; width:640px; height:480px"></webview>
If you want to control the guest content in any way, you can write JavaScript
that listens for webview events and responds to those events using the
webview methods. Here's sample code with two event listeners: one that listens
for the web page to start loading, the other for the web page to stop loading,
and displays a "loading..." message during the load time:
<script>
onload = () => {
const webview = document.querySelector('webview')
const indicator = document.querySelector('.indicator')
const loadstart = () => {
indicator.innerText = 'loading...'
}
const loadstop = () => {
indicator.innerText = ''
}
webview.addEventListener('did-start-loading', loadstart)
webview.addEventListener('did-stop-loading', loadstop)
}
</script>
Internal implementation
Under the hood webview is implemented with Out-of-Process iframes (OOPIFs).
The webview tag is essentially a custom element using shadow DOM to wrap an
iframe element inside it.
So the behavior of webview is very similar to a cross-domain iframe, as
examples:
- When clicking into a
webview, the page focus will move from the embedder frame towebview. - You can not add keyboard, mouse, and scroll event listeners to
webview. - All reactions between the embedder frame and
webvieware asynchronous.
CSS Styling Notes
Please note that the webview tag's style uses display:flex; internally to
ensure the child iframe element fills the full height and width of its webview
container when used with traditional and flexbox layouts. Please do not
overwrite the default display:flex; CSS property, unless specifying
display:inline-flex; for inline layout.
Tag Attributes
The webview tag has the following attributes:
src
<webview src="https://www.github.com/"></webview>
A String representing the visible URL. Writing to this attribute initiates top-level
navigation.
Assigning src its own value will reload the current page.
The src attribute can also accept data URLs, such as
data:text/plain,Hello, world!.
nodeintegration
<webview src="http://www.google.com/" nodeintegration></webview>
A Boolean. When this attribute is present the guest page in webview will have node
integration and can use node APIs like require and process to access low
level system resources. Node integration is disabled by default in the guest
page.
nodeintegrationinsubframes
<webview src="http://www.google.com/" nodeintegrationinsubframes></webview>
A Boolean for the experimental option for enabling NodeJS support in sub-frames such as iframes
inside the webview. All your preloads will load for every iframe, you can
use process.isMainFrame to determine if you are in the main frame or not.
This option is disabled by default in the guest page.
enableremotemodule
<webview src="http://www.google.com/" enableremotemodule="false"></webview>
A Boolean. When this attribute is false the guest page in webview will not have access
to the remote module. The remote module is available by default.
plugins
<webview src="https://www.github.com/" plugins></webview>
A Boolean. When this attribute is present the guest page in webview will be able to use
browser plugins. Plugins are disabled by default.
preload
<webview src="https://www.github.com/" preload="./test.js"></webview>
A String that specifies a script that will be loaded before other scripts run in the guest
page. The protocol of script's URL must be either file: or asar:, because it
will be loaded by require in guest page under the hood.
When the guest page doesn't have node integration this script will still have access to all Node APIs, but global objects injected by Node will be deleted after this script has finished executing.
Note: This option will appear as preloadURL (not preload) in
the webPreferences specified to the will-attach-webview event.
httpreferrer
<webview src="https://www.github.com/" httpreferrer="http://cheng.guru"></webview>
A String that sets the referrer URL for the guest page.
useragent
<webview src="https://www.github.com/" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"></webview>
A String that sets the user agent for the guest page before the page is navigated to. Once the
page is loaded, use the setUserAgent method to change the user agent.
disablewebsecurity
<webview src="https://www.github.com/" disablewebsecurity></webview>
A Boolean. When this attribute is present the guest page will have web security disabled.
Web security is enabled by default.
partition
<webview src="https://github.com" partition="persist:github"></webview>
<webview src="https://electronjs.org" partition="electron"></webview>
A String that sets the session used by the page. If partition starts with persist:, the
page will use a persistent session available to all pages in the app with the
same partition. if there is no persist: prefix, the page will use an
in-memory session. By assigning the same partition, multiple pages can share
the same session. If the partition is unset then default session of the app
will be used.
This value can only be modified before the first navigation, since the session of an active renderer process cannot change. Subsequent attempts to modify the value will fail with a DOM exception.
allowpopups
<webview src="https://www.github.com/" allowpopups></webview>
A Boolean. When this attribute is present the guest page will be allowed to open new
windows. Popups are disabled by default.
webpreferences
<webview src="https://github.com" webpreferences="allowRunningInsecureContent, javascript=no"></webview>
A String which is a comma separated list of strings which specifies the web preferences to be set on the webview.
The full list of supported preference strings can be found in BrowserWindow.
The string follows the same format as the features string in window.open.
A name by itself is given a true boolean value.
A preference can be set to another value by including an =, followed by the value.
Special values yes and 1 are interpreted as true, while no and 0 are interpreted as false.
enableblinkfeatures
<webview src="https://www.github.com/" enableblinkfeatures="PreciseMemoryInfo, CSSVariables"></webview>
A String which is a list of strings which specifies the blink features to be enabled separated by ,.
The full list of supported feature strings can be found in the
RuntimeEnabledFeatures.json5 file.
disableblinkfeatures
<webview src="https://www.github.com/" disableblinkfeatures="PreciseMemoryInfo, CSSVariables"></webview>
A String which is a list of strings which specifies the blink features to be disabled separated by ,.
The full list of supported feature strings can be found in the
RuntimeEnabledFeatures.json5 file.
Methods
The webview tag has the following methods:
Note: The webview element must be loaded before using the methods.
Example
const webview = document.querySelector('webview')
webview.addEventListener('dom-ready', () => {
webview.openDevTools()
})
<webview>.loadURL(url[, options])
urlURLoptionsObject (optional)httpReferrer(String | Referrer) (optional) - An HTTP Referrer url.userAgentString (optional) - A user agent originating the request.extraHeadersString (optional) - Extra headers separated by "\n"postData(UploadRawData[] | UploadFile[] | UploadBlob[]) (optional)baseURLForDataURLString (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specifiedurlis 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).
Loads the url in the webview, the url must contain the protocol prefix,
e.g. the http:// or file://.
<webview>.downloadURL(url)
urlString
Initiates a download of the resource at url without navigating.
<webview>.getURL()
Returns String - The URL of guest page.
<webview>.getTitle()
Returns String - The title of guest page.
<webview>.isLoading()
Returns Boolean - Whether guest page is still loading resources.
<webview>.isLoadingMainFrame()
Returns Boolean - Whether the main frame (and not just iframes or frames within it) is
still loading.
<webview>.isWaitingForResponse()
Returns Boolean - Whether the guest page is waiting for a first-response for the
main resource of the page.
<webview>.stop()
Stops any pending navigation.
<webview>.reload()
Reloads the guest page.
<webview>.reloadIgnoringCache()
Reloads the guest page and ignores cache.
<webview>.canGoBack()
Returns Boolean - Whether the guest page can go back.
<webview>.canGoForward()
Returns Boolean - Whether the guest page can go forward.
<webview>.canGoToOffset(offset)
offsetInteger
Returns Boolean - Whether the guest page can go to offset.
<webview>.clearHistory()
Clears the navigation history.
<webview>.goBack()
Makes the guest page go back.
<webview>.goForward()
Makes the guest page go forward.
<webview>.goToOffset(offset)
offsetInteger
Navigates to the specified offset from the "current entry".
<webview>.isCrashed()
Returns Boolean - Whether the renderer process has crashed.
<webview>.getUserAgent()
Returns String - The user agent for guest page.
<webview>.insertCSS(css)
cssString
Returns Promise<String> - A promise that resolves with a key for the inserted
CSS that can later be used to remove the CSS via
<webview>.removeInsertedCSS(key).
Injects CSS into the current web page and returns a unique key for the inserted stylesheet.
<webview>.removeInsertedCSS(key)
keyString
Returns Promise<void> - Resolves if the removal was successful.
Removes the inserted CSS from the current web page. The stylesheet is identified
by its key, which is returned from <webview>.insertCSS(css).
<webview>.executeJavaScript(code[, userGesture])
codeStringuserGestureBoolean (optional) - Defaultfalse.
Returns Promise<any> - A promise that resolves with the result of the executed code
or is rejected if the result of the code is a rejected promise.
Evaluates code in page. If userGesture is set, it will create the user
gesture context in the page. HTML APIs like requestFullScreen, which require
user action, can take advantage of this option for automation.
<webview>.openDevTools()
Opens a DevTools window for guest page.
<webview>.closeDevTools()
Closes the DevTools window of guest page.
<webview>.isDevToolsOpened()
Returns Boolean - Whether guest page has a DevTools window attached.
<webview>.isDevToolsFocused()
Returns Boolean - Whether DevTools window of guest page is focused.
<webview>.inspectElement(x, y)
xIntegeryInteger
Starts inspecting element at position (x, y) of guest page.
<webview>.inspectSharedWorker()
Opens the DevTools for the shared worker context present in the guest page.
<webview>.inspectServiceWorker()
Opens the DevTools for the service worker context present in the guest page.
<webview>.isAudioMuted()
Returns Boolean - Whether guest page has been muted.
<webview>.isCurrentlyAudible()
Returns Boolean - Whether audio is currently playing.
<webview>.undo()
Executes editing command undo in page.
<webview>.redo()
Executes editing command redo in page.
<webview>.cut()
Executes editing command cut in page.
<webview>.copy()
Executes editing command copy in page.
<webview>.paste()
Executes editing command paste in page.
<webview>.pasteAndMatchStyle()
Executes editing command pasteAndMatchStyle in page.
<webview>.delete()
Executes editing command delete in page.
<webview>.selectAll()
Executes editing command selectAll in page.
<webview>.unselect()
Executes editing command unselect in page.
<webview>.findInPage(text[, options])
textString - Content to be searched, must not be empty.optionsObject (optional)forwardBoolean (optional) - Whether to search forward or backward, defaults totrue.findNextBoolean (optional) - Whether the operation is first request or a follow up, defaults tofalse.matchCaseBoolean (optional) - Whether search should be case-sensitive, defaults tofalse.wordStartBoolean (optional) - Whether to look only at the start of words. defaults tofalse.medialCapitalAsWordStartBoolean (optional) - When combined withwordStart, accepts a match in the middle of a word if the match begins with an uppercase letter followed by a lowercase or non-letter. Accepts several other intra-word matches, defaults tofalse.
Returns Integer - The request id used for the request.
Starts a request to find all matches for the text in the web page. The result of the request
can be obtained by subscribing to found-in-page event.
<webview>.stopFindInPage(action)
actionString - Specifies the action to take place when ending<webview>.findInPagerequest.clearSelection- Clear the selection.keepSelection- Translate the selection into a normal selection.activateSelection- Focus and click the selection node.
Stops any findInPage request for the webview with the provided action.
<webview>.print([options])
optionsObject (optional)silentBoolean (optional) - Don't ask user for print settings. Default isfalse.printBackgroundBoolean (optional) - Prints the background color and image of the web page. Default isfalse.deviceNameString (optional) - Set the printer device name to use. Must be the system-defined name and not the 'friendly' name, e.g 'Brother_QL_820NWB' and not 'Brother QL-820NWB'.colorBoolean (optional) - Set whether the printed web page will be in color or grayscale. Default istrue.marginsObject (optional)marginTypeString (optional) - Can bedefault,none,printableArea, orcustom. Ifcustomis chosen, you will also need to specifytop,bottom,left, andright.topNumber (optional) - The top margin of the printed web page, in pixels.bottomNumber (optional) - The bottom margin of the printed web page, in pixels.leftNumber (optional) - The left margin of the printed web page, in pixels.rightNumber (optional) - The right margin of the printed web page, in pixels.
landscapeBoolean (optional) - Whether the web page should be printed in landscape mode. Default isfalse.scaleFactorNumber (optional) - The scale factor of the web page.pagesPerSheetNumber (optional) - The number of pages to print per page sheet.collateBoolean (optional) - Whether the web page should be collated.copiesNumber (optional) - The number of copies of the web page to print.pageRangesObject[] (optional) - The page range to print. On macOS, only the first range is honored.fromNumber - Index of the first page to print (0-based).toNumber - Index of the last page to print (inclusive) (0-based).
duplexModeString (optional) - Set the duplex mode of the printed web page. Can besimplex,shortEdge, orlongEdge.dpiRecord<string, number> (optional)horizontalNumber (optional) - The horizontal dpi.verticalNumber (optional) - The vertical dpi.
headerString (optional) - String to be printed as page header.footerString (optional) - String to be printed as page footer.pageSizeString | Size (optional) - Specify page size of the printed document. Can beA3,A4,A5,Legal,Letter,Tabloidor an Object containingheight.
Returns Promise<void>
Prints webview's web page. Same as webContents.print([options]).
<webview>.printToPDF(options)
optionsObjectheaderFooterRecord<string, string> (optional) - the header and footer for the PDF.titleString - The title for the PDF header.urlString - the url for the PDF footer.
landscapeBoolean (optional) -truefor landscape,falsefor portrait.marginsTypeInteger (optional) - Specifies the type of margins to use. Uses 0 for default margin, 1 for no margin, and 2 for minimum margin. andwidthin microns.scaleFactorNumber (optional) - The scale factor of the web page. Can range from 0 to 100.pageRangesRecord<string, number> (optional) - The page range to print.fromNumber - Index of the first page to print (0-based).toNumber - Index of the last page to print (inclusive) (0-based).
pageSizeString | Size (optional) - Specify page size of the generated PDF. Can beA3,A4,A5,Legal,Letter,Tabloidor an Object containingheightprintBackgroundBoolean (optional) - Whether to print CSS backgrounds.printSelectionOnlyBoolean (optional) - Whether to print selection only.
Returns Promise<Uint8Array> - Resolves with the generated PDF data.
Prints webview's web page as PDF, Same as webContents.printToPDF(options).
<webview>.capturePage([rect])
rectRectangle (optional) - The area of the page to be captured.
Returns Promise<NativeImage> - Resolves with a NativeImage
Captures a snapshot of the page within rect. Omitting rect will capture the whole visible page.
<webview>.send(channel, ...args)
channelString...argsany[]
Returns Promise<void>
Send an asynchronous message to renderer process via channel, you can also
send arbitrary arguments. The renderer process can handle the message by
listening to the channel event with the ipcRenderer module.
See webContents.send for examples.
<webview>.sendInputEvent(event)
Returns Promise<void>
Sends an input event to the page.
See webContents.sendInputEvent
for detailed description of event object.
<webview>.setZoomFactor(factor)
factorNumber - Zoom factor.
Changes the zoom factor to the specified factor. Zoom factor is zoom percent divided by 100, so 300% = 3.0.
<webview>.setZoomLevel(level)
levelNumber - Zoom level.
Changes the zoom level to the specified level. The original size is 0 and each
increment above or below represents zooming 20% larger or smaller to default
limits of 300% and 50% of original size, respectively. The formula for this is
scale := 1.2 ^ level.
<webview>.getZoomFactor()
Returns Number - the current zoom factor.
<webview>.getZoomLevel()
Returns Number - the current zoom level.
<webview>.setVisualZoomLevelLimits(minimumLevel, maximumLevel)
minimumLevelNumbermaximumLevelNumber
Returns Promise<void>
Sets the maximum and minimum pinch-to-zoom level.
<webview>.showDefinitionForSelection() macOS
Shows pop-up dictionary that searches the selected word on the page.
<webview>.getWebContentsId()
Returns Number - The WebContents ID of this webview.
DOM Events
The following DOM events are available to the webview tag:
Event: 'load-commit'
Returns:
urlStringisMainFrameBoolean
Fired when a load has committed. This includes navigation within the current document as well as subframe document-level loads, but does not include asynchronous resource loads.
Event: 'did-finish-load'
Fired when the navigation is done, i.e. the spinner of the tab will stop
spinning, and the onload event is dispatched.
Event: 'did-fail-load'
Returns:
errorCodeIntegererrorDescriptionStringvalidatedURLStringisMainFrameBoolean
This event is like did-finish-load, but fired when the load failed or was
cancelled, e.g. window.stop() is invoked.
Event: 'did-start-loading'
Corresponds to the points in time when the spinner of the tab starts spinning.
Event: 'did-stop-loading'
Corresponds to the points in time when the spinner of the tab stops spinning.
Event: 'dom-ready'
Fired when document in the given frame is loaded.
Event: 'page-title-updated'
Returns:
titleStringexplicitSetBoolean
Fired when page title is set during navigation. explicitSet is false when
title is synthesized from file url.
Event: 'page-favicon-updated'
Returns:
faviconsString[] - Array of URLs.
Fired when page receives favicon urls.
Event: 'enter-html-full-screen'
Fired when page enters fullscreen triggered by HTML API.
Event: 'leave-html-full-screen'
Fired when page leaves fullscreen triggered by HTML API.
Event: 'console-message'
Returns:
levelIntegermessageStringlineIntegersourceIdString
Fired when the guest window logs a console message.
The following example code forwards all log messages to the embedder's console without regard for log level or other properties.
const webview = document.querySelector('webview')
webview.addEventListener('console-message', (e) => {
console.log('Guest page logged a message:', e.message)
})
Event: 'found-in-page'
Returns:
resultObjectrequestIdIntegeractiveMatchOrdinalInteger - Position of the active match.matchesInteger - Number of Matches.selectionAreaRectangle - Coordinates of first match region.finalUpdateBoolean
Fired when a result is available for
webview.findInPage request.
const webview = document.querySelector('webview')
webview.addEventListener('found-in-page', (e) => {
webview.stopFindInPage('keepSelection')
})
const requestId = webview.findInPage('test')
console.log(requestId)
Event: 'new-window'
Returns:
urlStringframeNameStringdispositionString - Can bedefault,foreground-tab,background-tab,new-window,save-to-diskandother.optionsBrowserWindowConstructorOptions - The options which should be used for creating the newBrowserWindow.
Fired when the guest page attempts to open a new browser window.
The following example code opens the new url in system's default browser.
const { shell } = require('electron')
const webview = document.querySelector('webview')
webview.addEventListener('new-window', async (e) => {
const protocol = require('url').parse(e.url).protocol
if (protocol === 'http:' || protocol === 'https:') {
await shell.openExternal(e.url)
}
})
Event: 'will-navigate'
Returns:
urlString
Emitted when a user or the page wants to start navigation. It can happen when
the window.location object is changed or a user clicks a link in the page.
This event will not emit when the navigation is started programmatically with
APIs like <webview>.loadURL and <webview>.back.
It is also not emitted during in-page navigation, such as clicking anchor links
or updating the window.location.hash. Use did-navigate-in-page event for
this purpose.
Calling event.preventDefault() does NOT have any effect.
Event: 'did-navigate'
Returns:
urlString
Emitted when a navigation is done.
This event is not emitted for in-page navigations, such as clicking anchor links
or updating the window.location.hash. Use did-navigate-in-page event for
this purpose.
Event: 'did-navigate-in-page'
Returns:
isMainFrameBooleanurlString
Emitted when an in-page navigation happened.
When in-page navigation happens, the page URL changes but does not cause
navigation outside of the page. Examples of this occurring are when anchor links
are clicked or when the DOM hashchange event is triggered.
Event: 'close'
Fired when the guest page attempts to close itself.
The following example code navigates the webview to about:blank when the
guest attempts to close itself.
const webview = document.querySelector('webview')
webview.addEventListener('close', () => {
webview.src = 'about:blank'
})
Event: 'ipc-message'
Returns:
channelStringargsany[]
Fired when the guest page has sent an asynchronous message to embedder page.
With sendToHost method and ipc-message event you can communicate
between guest page and embedder page:
// In embedder page.
const webview = document.querySelector('webview')
webview.addEventListener('ipc-message', (event) => {
console.log(event.channel)
// Prints "pong"
})
webview.send('ping')
// In guest page.
const { ipcRenderer } = require('electron')
ipcRenderer.on('ping', () => {
ipcRenderer.sendToHost('pong')
})
Event: 'crashed'
Fired when the renderer process is crashed.
Event: 'destroyed'
Fired when the WebContents is destroyed.
Event: 'media-started-playing'
Emitted when media starts playing.
Event: 'media-paused'
Emitted when media is paused or done playing.
Event: 'did-change-theme-color'
Returns:
themeColorString
Emitted when a page's theme color changes. This is usually due to encountering a meta tag:
<meta name='theme-color' content='#ff0000'>
Event: 'update-target-url'
Returns:
urlString
Emitted when mouse moves over a link or the keyboard moves the focus to a link.
Event: 'devtools-opened'
Emitted when DevTools is opened.
Event: 'devtools-closed'
Emitted when DevTools is closed.
Event: 'devtools-focused'
Emitted when DevTools is focused / opened.
window.open Function
Open a new window and load a URL.
When window.open is called to create a new window in a web page, a new instance
of BrowserWindow will be created for the url and a proxy will be returned
to window.open to let the page have limited control over it.
The proxy has limited standard functionality implemented to be
compatible with traditional web pages. For full control of the new window
you should create a BrowserWindow directly.
The newly created BrowserWindow will inherit the parent window's options by
default. To override inherited options you can set them in the features
string.
window.open(url[, frameName][, features])
urlStringframeNameString (optional)featuresString (optional)
Returns BrowserWindowProxy - Creates a new window
and returns an instance of BrowserWindowProxy class.
The features string follows the format of standard browser, but each feature
has to be a field of BrowserWindow's options. These are the features you can set via features string: zoomFactor, nodeIntegration, preload, javascript, contextIsolation, webviewTag.
For example:
window.open('https://github.com', '_blank', 'nodeIntegration=no')
Notes:
- Node integration will always be disabled in the opened
windowif it is disabled on the parent window. - Context isolation will always be enabled in the opened
windowif it is enabled on the parent window. - JavaScript will always be disabled in the opened
windowif it is disabled on the parent window. - Non-standard features (that are not handled by Chromium or Electron) given in
featureswill be passed to any registeredwebContent'snew-windowevent handler in theadditionalFeaturesargument.
window.opener.postMessage(message, targetOrigin)
messageStringtargetOriginString
Sends a message to the parent window with the specified origin or * for no
origin preference.
Using Chrome's window.open() implementation
If you want to use Chrome's built-in window.open() implementation, set
nativeWindowOpen to true in the webPreferences options object.
Native window.open() allows synchronous access to opened windows so it is
convenient choice if you need to open a dialog or a preferences window.
This option can also be set on <webview> tags as well:
<webview webpreferences="nativeWindowOpen=yes"></webview>
The creation of the BrowserWindow is customizable via WebContents's
new-window event.
// main process
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nativeWindowOpen: true
}
})
mainWindow.webContents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures) => {
if (frameName === 'modal') {
// open window as modal
event.preventDefault()
Object.assign(options, {
modal: true,
parent: mainWindow,
width: 100,
height: 100
})
event.newGuest = new BrowserWindow(options)
}
})
// renderer process (mainWindow)
let modal = window.open('', 'modal')
modal.document.write('<h1>Hello</h1>')
Windows 10 on Arm
If your app runs with Electron 6.0.8 or later, you can now build it for Windows 10 on Arm. This considerably improves performance, but requires recompilation of any native modules used in your app. It may also require small fixups to your build and packaging scripts.
Running a basic app
If your app doesn't use any native modules, then it's really easy to create an Arm version of your app.
- Make sure that your app's
node_modulesdirectory is empty. - Using a Command Prompt, run
set npm_config_arch=arm64before runningnpm install/yarn installas usual. - If you have Electron installed as a development dependency, npm will download and unpack the arm64 version. You can then package and distribute your app as normal.
Architecture-specific code
Lots of Windows-specific code contains if... else logic that selects between either the x64 or x86 architectures.
if (process.arch === 'x64') {
// Do 64-bit thing...
} else {
// Do 32-bit thing...
}
If you want to target arm64, logic like this will typically select the wrong architecture, so carefully check your application and build scripts for conditions like this. In custom build and packaging scripts, you should always check the value of npm_config_arch in the environment, rather than relying on the current process arch.
Native modules
If you use native modules, you must make sure that they compile against v142 of the MSVC compiler (provided in Visual Studio 2017). You must also check that any pre-built .dll or .lib files provided or referenced by the native module are available for Windows on Arm.
Testing your app
To test your app, use a Windows on Arm device running Windows 10 (version 1903 or later). Make sure that you copy your application over to the target device - Chromium's sandbox will not work correctly when loading your application assets from a network location.
Node.js/node-gyp
Node.js v12.9.0 or later is recommended. If updating to a new version of Node is undesirable, you can instead update npm's copy of node-gyp manually to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
Visual Studio 2017
Visual Studio 2017 (any edition) is required for cross-compiling native modules. You can download Visual Studio Community 2017 via Microsoft's Visual Studio Dev Essentials program. After installation, you can add the Arm-specific components by running the following from a Command Prompt:
vs_installer.exe ^
--add Microsoft.VisualStudio.Workload.NativeDesktop ^
--add Microsoft.VisualStudio.Component.VC.ATLMFC ^
--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ^
--add Microsoft.VisualStudio.Component.VC.MFC.ARM64 ^
--includeRecommended
Creating a cross-compilation command prompt
Setting npm_config_arch=arm64 in the environment creates the correct arm64 .obj files, but the standard Developer Command Prompt for VS 2017 will use the x64 linker. To fix this:
- Duplicate the x64_x86 Cross Tools Command Prompt for VS 2017 shortcut (e.g. by locating it in the start menu, right clicking, selecting Open File Location, copying and pasting) to somewhere convenient.
- Right click the new shortcut and choose Properties.
- Change the Target field to read
vcvarsamd64_arm64.batat the end instead ofvcvarsamd64_x86.bat.
If done successfully, the command prompt should print something similar to this on startup:
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.15
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64_arm64'
If you want to develop your application directly on a Windows on Arm device, substitute vcvarsx86_arm64.bat in Target so that cross-compilation can happen with the device's x86 emulation.
Linking against the correct node.lib
By default, node-gyp unpacks Electron's node headers and downloads the x86 and x64 versions of node.lib into %APPDATA%\..\Local\node-gyp\Cache, but it does not download the arm64 version (a fix for this is in development.) To fix this:
- Download the arm64
node.libfrom https://electronjs.org/headers/v6.0.9/win-arm64/node.lib - Move it to
%APPDATA%\..\Local\node-gyp\Cache\6.0.9\arm64\node.lib
Substitute 6.0.9 for the version you're using.
Cross-compiling native modules
After completing all of the above, open your cross-compilation command prompt and run set npm_config_arch=arm64. Then use npm install to build your project as normal. As with cross-compiling x86 modules, you may need to remove node_modules to force recompilation of native modules if they were previously compiled for another architecture.
Debugging native modules
Debugging native modules can be done with Visual Studio 2017 (running on your development machine) and corresponding Visual Studio Remote Debugger running on the target device. To debug:
- Launch your app
.exeon the target device via the Command Prompt (passing--inspect-brkto pause it before any native modules are loaded). - Launch Visual Studio 2017 on your development machine.
- Connect to the target device by selecting Debug > Attach to Process... and enter the device's IP address and the port number displayed by the Visual Studio Remote Debugger tool.
- Click Refresh and select the appropriate Electron process to attach.
- You may need to make sure that any symbols for native modules in your app are loaded correctly. To configure this, head to Debug > Options... in Visual Studio 2017, and add the folders containing your
.pdbsymbols under Debugging > Symbols. - Once attached, set any appropriate breakpoints and resume JavaScript execution using Chrome's remote tools for Node.
Getting additional help
If you encounter a problem with this documentation, or if your app works when compiled for x86 but not for arm64, please file an issue with "Windows on Arm" in the title.
Windows Store Guide
With Windows 10, the good old win32 executable got a new sibling: The Universal
Windows Platform. The new .appx format does not only enable a number of new
powerful APIs like Cortana or Push Notifications, but through the Windows Store,
also simplifies installation and updating.
Microsoft developed a tool that compiles Electron apps as .appx packages,
enabling developers to use some of the goodies found in the new application
model. This guide explains how to use it - and what the capabilities and
limitations of an Electron AppX package are.
Background and Requirements
Windows 10 "Anniversary Update" is able to run win32 .exe binaries by
launching them together with a virtualized filesystem and registry. Both are
created during compilation by running app and installer inside a Windows
Container, allowing Windows to identify exactly which modifications to the
operating system are done during installation. Pairing the executable with a
virtual filesystem and a virtual registry allows Windows to enable one-click
installation and uninstallation.
In addition, the exe is launched inside the appx model - meaning that it can use
many of the APIs available to the Universal Windows Platform. To gain even more
capabilities, an Electron app can pair up with an invisible UWP background task
launched together with the exe - sort of launched as a sidekick to run tasks
in the background, receive push notifications, or to communicate with other UWP
applications.
To compile any existing Electron app, ensure that you have the following requirements:
- Windows 10 with Anniversary Update (released August 2nd, 2016)
- The Windows 10 SDK, downloadable here
- At least Node 4 (to check, run
node -v)
Then, go and install the electron-windows-store CLI:
npm install -g electron-windows-store
Step 1: Package Your Electron Application
Package the application using electron-packager (or a similar tool).
Make sure to remove node_modules that you don't need in your final application, since
any module you don't actually need will increase your application's size.
The output should look roughly like this:
├── Ghost.exe
├── LICENSE
├── content_resources_200_percent.pak
├── content_shell.pak
├── d3dcompiler_47.dll
├── ffmpeg.dll
├── icudtl.dat
├── libEGL.dll
├── libGLESv2.dll
├── locales
│ ├── am.pak
│ ├── ar.pak
│ ├── [...]
├── node.dll
├── resources
│ └── app.asar
├── v8_context_snapshot.bin
├── squirrel.exe
└── ui_resources_200_percent.pak
Step 2: Running electron-windows-store
From an elevated PowerShell (run it "as Administrator"), run
electron-windows-store with the required parameters, passing both the input
and output directories, the app's name and version, and confirmation that
node_modules should be flattened.
electron-windows-store `
--input-directory C:\myelectronapp `
--output-directory C:\output\myelectronapp `
--package-version 1.0.0.0 `
--package-name myelectronapp
Once executed, the tool goes to work: It accepts your Electron app as an input,
flattening the node_modules. Then, it archives your application as app.zip.
Using an installer and a Windows Container, the tool creates an "expanded" AppX
package - including the Windows Application Manifest (AppXManifest.xml) as
well as the virtual file system and the virtual registry inside your output
folder.
Once the expanded AppX files are created, the tool uses the Windows App Packager
(MakeAppx.exe) to create a single-file AppX package from those files on disk.
Finally, the tool can be used to create a trusted certificate on your computer
to sign the new AppX package. With the signed AppX package, the CLI can also
automatically install the package on your machine.
Step 3: Using the AppX Package
In order to run your package, your users will need Windows 10 with the so-called "Anniversary Update" - details on how to update Windows can be found here.
In opposition to traditional UWP apps, packaged apps currently need to undergo a
manual verification process, for which you can apply here.
In the meantime, all users will be able to install your package by double-clicking it,
so a submission to the store might not be necessary if you're looking for an
easier installation method. In managed environments (usually enterprises), the
Add-AppxPackage PowerShell Cmdlet can be used to install it in an automated fashion.
Another important limitation is that the compiled AppX package still contains a win32 executable - and will therefore not run on Xbox, HoloLens, or Phones.
Optional: Add UWP Features using a BackgroundTask
You can pair your Electron app up with an invisible UWP background task that gets to make full use of Windows 10 features - like push notifications, Cortana integration, or live tiles.
To check out how an Electron app that uses a background task to send toast notifications and live tiles, check out the Microsoft-provided sample.
Optional: Convert using Container Virtualization
To generate the AppX package, the electron-windows-store CLI uses a template
that should work for most Electron apps. However, if you are using a custom
installer, or should you experience any trouble with the generated package, you
can attempt to create a package using compilation with a Windows Container - in
that mode, the CLI will install and run your application in blank Windows Container
to determine what modifications your application is exactly doing to the operating
system.
Before running the CLI for the first time, you will have to setup the "Windows Desktop App
Converter". This will take a few minutes, but don't worry - you only have to do
this once. Download and Desktop App Converter from here.
You will receive two files: DesktopAppConverter.zip and BaseImage-14316.wim.
- Unzip
DesktopAppConverter.zip. From an elevated PowerShell (opened with "run as Administrator", ensure that your systems execution policy allows us to run everything we intend to run by callingSet-ExecutionPolicy bypass. - Then, run the installation of the Desktop App Converter, passing in the
location of the Windows base Image (downloaded as
BaseImage-14316.wim), by calling.\DesktopAppConverter.ps1 -Setup -BaseImage .\BaseImage-14316.wim. - If running the above command prompts you for a reboot, please restart your machine and run the above command again after a successful restart.
Once installation succeeded, you can move on to compiling your Electron app.
Windows Taskbar
Electron has APIs to configure the app's icon in the Windows taskbar. Supported
are the creation of a JumpList,
custom thumbnails and toolbars,
icon overlays, and the so-called
"Flash Frame" effect, but
Electron also uses the app's dock icon to implement cross-platform features
like recent documents and
application progress.
JumpList
Windows allows apps to define a custom context menu that shows up when users
right-click the app's icon in the task bar. That context menu is called
JumpList. You specify custom actions in the Tasks category of JumpList,
as quoted from MSDN:
Applications define tasks based on both the program's features and the key things a user is expected to do with them. Tasks should be context-free, in that the application does not need to be running for them to work. They should also be the statistically most common actions that a normal user would perform in an application, such as compose an email message or open the calendar in a mail program, create a new document in a word processor, launch an application in a certain mode, or launch one of its subcommands. An application should not clutter the menu with advanced features that standard users won't need or one-time actions such as registration. Do not use tasks for promotional items such as upgrades or special offers.
It is strongly recommended that the task list be static. It should remain the same regardless of the state or status of the application. While it is possible to vary the list dynamically, you should consider that this could confuse the user who does not expect that portion of the destination list to change.
Tasks of Internet Explorer:

Unlike the dock menu in macOS which is a real menu, user tasks in Windows work like application shortcuts such that when user clicks a task, a program will be executed with specified arguments.
To set user tasks for your application, you can use app.setUserTasks API:
const { app } = require('electron')
app.setUserTasks([
{
program: process.execPath,
arguments: '--new-window',
iconPath: process.execPath,
iconIndex: 0,
title: 'New Window',
description: 'Create a new window'
}
])
To clean your tasks list, call app.setUserTasks with an empty array:
const { app } = require('electron')
app.setUserTasks([])
The user tasks will still show even after your application closes, so the icon and program path specified for a task should exist until your application is uninstalled.
Thumbnail Toolbars
On Windows you can add a thumbnail toolbar with specified buttons in a taskbar layout of an application window. It provides users a way to access to a particular window's command without restoring or activating the window.
From MSDN, it's illustrated:
This toolbar is the familiar standard toolbar common control. It has a maximum of seven buttons. Each button's ID, image, tooltip, and state are defined in a structure, which is then passed to the taskbar. The application can show, enable, disable, or hide buttons from the thumbnail toolbar as required by its current state.
For example, Windows Media Player might offer standard media transport controls such as play, pause, mute, and stop.
Thumbnail toolbar of Windows Media Player:

You can use BrowserWindow.setThumbarButtons to set thumbnail toolbar in your application:
const { BrowserWindow } = require('electron')
const path = require('path')
const win = new BrowserWindow()
win.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'button1.png'),
click () { console.log('button1 clicked') }
}, {
tooltip: 'button2',
icon: path.join(__dirname, 'button2.png'),
flags: ['enabled', 'dismissonclick'],
click () { console.log('button2 clicked.') }
}
])
To clean thumbnail toolbar buttons, just call BrowserWindow.setThumbarButtons
with an empty array:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.setThumbarButtons([])
Icon Overlays in Taskbar
On Windows a taskbar button can use a small overlay to display application status, as quoted from MSDN:
Icon overlays serve as a contextual notification of status, and are intended to negate the need for a separate notification area status icon to communicate that information to the user. For instance, the new mail status in Microsoft Outlook, currently shown in the notification area, can now be indicated through an overlay on the taskbar button. Again, you must decide during your development cycle which method is best for your application. Overlay icons are intended to supply important, long-standing status or notifications such as network status, messenger status, or new mail. The user should not be presented with constantly changing overlays or animations.
Overlay on taskbar button:

To set the overlay icon for a window, you can use the BrowserWindow.setOverlayIcon API:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.setOverlayIcon('path/to/overlay.png', 'Description for overlay')
Flash Frame
On Windows you can highlight the taskbar button to get the user's attention. This is similar to bouncing the dock icon on macOS. From the MSDN reference documentation:
Typically, a window is flashed to inform the user that the window requires attention but that it does not currently have the keyboard focus.
To flash the BrowserWindow taskbar button, you can use the BrowserWindow.flashFrame API:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.once('focus', () => win.flashFrame(false))
win.flashFrame(true)
Don't forget to call the flashFrame method with false to turn off the flash. In
the above example, it is called when the window comes into focus, but you might
use a timeout or some other event to disable it.
