W3cubDocs

/Electron

Accelerator

Define keyboard shortcuts.

Accelerators are Strings that can contain multiple modifiers and a single key code, combined by the + character, and are used to define keyboard shortcuts throughout your application.

Examples:

  • CommandOrControl+A
  • CommandOrControl+Shift+Z

Shortcuts are registered with the globalShortcut module using the register method, i.e.

const { app, globalShortcut } = require('electron')

app.whenReady().then(() => {
  // Register a 'CommandOrControl+Y' shortcut listener.
  globalShortcut.register('CommandOrControl+Y', () => {
    // Do stuff when Y and either Command/Control is pressed.
  })
})

Platform notice

On Linux and Windows, the Command key does not have any effect so use CommandOrControl which represents Command on macOS and Control on Linux and Windows to define some accelerators.

Use Alt instead of Option. The Option key only exists on macOS, whereas the Alt key is available on all platforms.

The Super key is mapped to the Windows key on Windows and Linux and Cmd on macOS.

Available modifiers

  • Command (or Cmd for short)
  • Control (or Ctrl for short)
  • CommandOrControl (or CmdOrCtrl for short)
  • Alt
  • Option
  • AltGr
  • Shift
  • Super

Available key codes

  • 0 to 9
  • A to Z
  • F1 to F24
  • Punctuation like ~, !, @, #, $, etc.
  • Plus
  • Space
  • Tab
  • Capslock
  • Numlock
  • Scrolllock
  • Backspace
  • Delete
  • Insert
  • Return (or Enter as alias)
  • Up, Down, Left and Right
  • Home and End
  • PageUp and PageDown
  • Escape (or Esc for short)
  • VolumeUp, VolumeDown and VolumeMute
  • MediaNextTrack, MediaPreviousTrack, MediaStop and MediaPlayPause
  • PrintScreen
  • NumPad Keys
    • num0 - num9
    • numdec - decimal key
    • numadd - numpad + key
    • numsub - numpad - key
    • nummult - numpad * key
    • numdiv - 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.

devtron screenshot

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.

Within third-party software

macOS

On macOS, third-party assistive technology can toggle accessibility features inside Electron applications by setting the AXManualAccessibility attribute programmatically:

CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility");

+ (void)enableAccessibility:(BOOL)enable inElectronApplication:(NSRunningApplication *)app
{
    AXUIElementRef appRef = AXUIElementCreateApplication(app.processIdentifier);
    if (appRef == nil)
        return;

    CFBooleanRef value = enable ? kCFBooleanTrue : kCFBooleanFalse;
    AXUIElementSetAttributeValue(appRef, kAXManualAccessibility, value);
    CFRelease(appRef);
}

app

Control your application's event lifecycle.

Process: Main

The following example shows how to quit the application when the last window is closed:

const { app } = require('electron')
app.on('window-all-closed', () => {
  app.quit()
})

Events

The app object emits the following events:

Event: 'will-finish-launching'

Emitted when the application has finished basic startup. On Windows and Linux, the will-finish-launching event is the same as the ready event; on macOS, this event represents the applicationWillFinishLaunching notification of NSApplication. You would usually set up listeners for the open-file and open-url events here, and start the crash reporter and auto updater.

In most cases, you should do everything in the ready event handler.

Event: 'ready'

Returns:

  • event Event
  • launchInfo Record<string, any> macOS

Emitted once, when Electron has finished initializing. On macOS, launchInfo holds the userInfo of the NSUserNotification that was used to open the application, if it was launched from Notification Center. You can also call app.isReady() to check if this event has already fired and app.whenReady() to get a Promise that is fulfilled when Electron is initialized.

Event: 'window-all-closed'

Emitted when all windows have been closed.

If you do not subscribe to this event and all windows are closed, the default behavior is to quit the app; however, if you subscribe, you control whether the app quits or not. If the user pressed Cmd + Q, or the developer called app.quit(), Electron will first try to close all the windows and then emit the will-quit event, and in this case the window-all-closed event would not be emitted.

Event: 'before-quit'

Returns:

  • event Event

Emitted before the application starts closing its windows. Calling event.preventDefault() will prevent the default behavior, which is terminating the application.

Note: If application quit was initiated by autoUpdater.quitAndInstall(), then before-quit is emitted after emitting close event on all windows and closing them.

Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.

Event: 'will-quit'

Returns:

  • event Event

Emitted when all windows have been closed and the application will quit. Calling event.preventDefault() will prevent the default behavior, which is terminating the application.

See the description of the window-all-closed event for the differences between the will-quit and window-all-closed events.

Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.

Event: 'quit'

Returns:

  • event Event
  • exitCode Integer

Emitted when the application is quitting.

Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.

Event: 'open-file' macOS

Returns:

  • event Event
  • path String

Emitted when the user wants to open a file with the application. The open-file event is usually emitted when the application is already open and the OS wants to reuse the application to open the file. open-file is also emitted when a file is dropped onto the dock and the application is not yet running. Make sure to listen for the open-file event very early in your application startup to handle this case (even before the ready event is emitted).

You should call event.preventDefault() if you want to handle this event.

On Windows, you have to parse process.argv (in the main process) to get the filepath.

Event: 'open-url' macOS

Returns:

  • event Event
  • url String

Emitted when the user wants to open a URL with the application. Your application's Info.plist file must define the URL scheme within the CFBundleURLTypes key, and set NSPrincipalClass to AtomApplication.

You should call event.preventDefault() if you want to handle this event.

Event: 'activate' macOS

Returns:

  • event Event
  • hasVisibleWindows Boolean

Emitted when the application is activated. Various actions can trigger this event, such as launching the application for the first time, attempting to re-launch the application when it's already running, or clicking on the application's dock or taskbar icon.

Event: 'did-become-active' macOS

Returns:

  • event Event

Emitted when mac application become active. Difference from activate event is that did-become-active is emitted every time the app becomes active, not only when Dock icon is clicked or application is re-launched.

Event: 'continue-activity' macOS

Returns:

  • event Event
  • type String - A string identifying the activity. Maps to NSUserActivity.activityType.
  • userInfo unknown - Contains app-specific state stored by the activity on another device.

Emitted during Handoff when an activity from a different device wants to be resumed. You should call event.preventDefault() if you want to handle this event.

A user activity can be continued only in an app that has the same developer Team ID as the activity's source app and that supports the activity's type. Supported activity types are specified in the app's Info.plist under the NSUserActivityTypes key.

Event: 'will-continue-activity' macOS

Returns:

Emitted during Handoff before an activity from a different device wants to be resumed. You should call event.preventDefault() if you want to handle this event.

Event: 'continue-activity-error' macOS

Returns:

  • event Event
  • type String - A string identifying the activity. Maps to NSUserActivity.activityType.
  • error String - A string with the error's localized description.

Emitted during Handoff when an activity from a different device fails to be resumed.

Event: 'activity-was-continued' macOS

Returns:

  • event Event
  • type String - A string identifying the activity. Maps to NSUserActivity.activityType.
  • userInfo unknown - Contains app-specific state stored by the activity.

Emitted during Handoff after an activity from this device was successfully resumed on another one.

Event: 'update-activity-state' macOS

Returns:

  • event Event
  • type String - A string identifying the activity. Maps to NSUserActivity.activityType.
  • userInfo unknown - Contains app-specific state stored by the activity.

Emitted when Handoff is about to be resumed on another device. If you need to update the state to be transferred, you should call event.preventDefault() immediately, construct a new userInfo dictionary and call app.updateCurrentActivity() in a timely manner. Otherwise, the operation will fail and continue-activity-error will be called.

Event: 'new-window-for-tab' macOS

Returns:

  • event Event

Emitted when the user clicks the native macOS new tab button. The new tab button is only visible if the current BrowserWindow has a tabbingIdentifier

Event: 'browser-window-blur'

Returns:

Emitted when a browserWindow gets blurred.

Event: 'browser-window-focus'

Returns:

Emitted when a browserWindow gets focused.

Event: 'browser-window-created'

Returns:

Emitted when a new browserWindow is created.

Event: 'web-contents-created'

Returns:

Emitted when a new webContents is created.

Event: 'certificate-error'

Returns:

  • event Event
  • webContents WebContents
  • url String
  • error String - The error code
  • certificate Certificate
  • callback Function
    • isTrusted Boolean - Whether to consider the certificate as trusted

Emitted when failed to verify the certificate for url, to trust the certificate you should prevent the default behavior with event.preventDefault() and call callback(true).

const { app } = require('electron')

app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
  if (url === 'https://github.com') {
    // Verification logic.
    event.preventDefault()
    callback(true)
  } else {
    callback(false)
  }
})

Event: 'select-client-certificate'

Returns:

Emitted when a client certificate is requested.

The url corresponds to the navigation entry requesting the client certificate and callback can be called with an entry filtered from the list. Using event.preventDefault() prevents the application from using the first certificate from the store.

const { app } = require('electron')

app.on('select-client-certificate', (event, webContents, url, list, callback) => {
  event.preventDefault()
  callback(list[0])
})

Event: 'login'

Returns:

  • event Event
  • webContents WebContents
  • authenticationResponseDetails Object
    • url URL
  • authInfo Object
    • isProxy Boolean
    • scheme String
    • host String
    • port Integer
    • realm String
  • callback Function
    • username String (optional)
    • password String (optional)

Emitted when webContents wants to do basic auth.

The default behavior is to cancel all authentications. To override this you should prevent the default behavior with event.preventDefault() and call callback(username, password) with the credentials.

const { app } = require('electron')

app.on('login', (event, webContents, details, authInfo, callback) => {
  event.preventDefault()
  callback('username', 'secret')
})

If callback is called without a username or password, the authentication request will be cancelled and the authentication error will be returned to the page.

Event: 'gpu-info-update'

Emitted whenever there is a GPU info update.

Event: 'gpu-process-crashed' Deprecated

Returns:

  • event Event
  • killed Boolean

Emitted when the GPU process crashes or is killed.

Deprecated: This event is superceded by the child-process-gone event which contains more information about why the child process disappeared. It isn't always because it crashed. The killed boolean can be replaced by checking reason === 'killed' when you switch to that event.

Event: 'renderer-process-crashed' Deprecated

Returns:

Emitted when the renderer process of webContents crashes or is killed.

Deprecated: This event is superceded by the render-process-gone event which contains more information about why the render process disappeared. It isn't always because it crashed. The killed boolean can be replaced by checking reason === 'killed' when you switch to that event.

Event: 'render-process-gone'

Returns:

  • event Event
  • webContents WebContents
  • details Object
    • reason String - The reason the render process is gone. Possible values:
      • clean-exit - Process exited with an exit code of zero
      • abnormal-exit - Process exited with a non-zero exit code
      • killed - Process was sent a SIGTERM or otherwise killed externally
      • crashed - Process crashed
      • oom - Process ran out of memory
      • launch-failed - Process never successfully launched
      • integrity-failure - Windows code integrity checks failed

Emitted when the renderer process unexpectedly disappears. This is normally because it was crashed or killed.

Event: 'child-process-gone'

Returns:

  • event Event
  • details Object
    • type String - Process type. One of the following values:
      • Utility
      • Zygote
      • Sandbox helper
      • GPU
      • Pepper Plugin
      • Pepper Plugin Broker
      • Unknown
    • reason String - The reason the child process is gone. Possible values:
      • clean-exit - Process exited with an exit code of zero
      • abnormal-exit - Process exited with a non-zero exit code
      • killed - Process was sent a SIGTERM or otherwise killed externally
      • crashed - Process crashed
      • oom - Process ran out of memory
      • launch-failed - Process never successfully launched
      • integrity-failure - Windows code integrity checks failed
    • exitCode Number - The exit code for the process (e.g. status from waitpid if on posix, from GetExitCodeProcess on Windows).
    • name String (optional) - The name of the process. i.e. for plugins it might be Flash. Examples for utility: Audio Service, Content Decryption Module Service, Network Service, Video Capture, etc.

Emitted when the child process unexpectedly disappears. This is normally because it was crashed or killed. It does not include renderer processes.

Event: 'accessibility-support-changed' macOS Windows

Returns:

  • event Event
  • accessibilitySupportEnabled Boolean - true when Chrome's accessibility support is enabled, false otherwise.

Emitted when Chrome's accessibility support changes. This event fires when assistive technologies, such as screen readers, are enabled or disabled. See https://www.chromium.org/developers/design-documents/accessibility for more details.

Event: 'session-created'

Returns:

Emitted when Electron has created a new session.

const { app } = require('electron')

app.on('session-created', (session) => {
  console.log(session)
})

Event: 'second-instance'

Returns:

  • event Event
  • argv String[] - An array of the second instance's command line arguments
  • workingDirectory String - The second instance's working directory

This event will be emitted inside the primary instance of your application when a second instance has been executed and calls app.requestSingleInstanceLock().

argv is an Array of the second instance's command line arguments, and workingDirectory is its current working directory. Usually applications respond to this by making their primary window focused and non-minimized.

Note: If the second instance is started by a different user than the first, the argv array will not include the arguments.

This event is guaranteed to be emitted after the ready event of app gets emitted.

Note: Extra command line arguments might be added by Chromium, such as --original-process-start-time.

Event: 'desktop-capturer-get-sources'

Returns:

Emitted when desktopCapturer.getSources() is called in the renderer process of webContents. Calling event.preventDefault() will make it return empty sources.

Event: 'remote-require'

Returns:

  • event Event
  • webContents WebContents
  • moduleName String

Emitted when remote.require() is called in the renderer process of webContents. Calling event.preventDefault() will prevent the module from being returned. Custom value can be returned by setting event.returnValue.

Event: 'remote-get-global'

Returns:

  • event Event
  • webContents WebContents
  • globalName String

Emitted when remote.getGlobal() is called in the renderer process of webContents. Calling event.preventDefault() will prevent the global from being returned. Custom value can be returned by setting event.returnValue.

Event: 'remote-get-builtin'

Returns:

  • event Event
  • webContents WebContents
  • moduleName String

Emitted when remote.getBuiltin() is called in the renderer process of webContents. Calling event.preventDefault() will prevent the module from being returned. Custom value can be returned by setting event.returnValue.

Event: 'remote-get-current-window'

Returns:

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:

Emitted when remote.getCurrentWebContents() is called in the renderer process of webContents. Calling event.preventDefault() will prevent the object from being returned. Custom value can be returned by setting event.returnValue.

Methods

The app object has the following methods:

Note: Some methods are only available on specific operating systems and are labeled as such.

app.quit()

Try to close all windows. The before-quit event will be emitted first. If all windows are successfully closed, the will-quit event will be emitted and by default the application will terminate.

This method guarantees that all beforeunload and unload event handlers are correctly executed. It is possible that a window cancels the quitting by returning false in the beforeunload event handler.

app.exit([exitCode])

  • exitCode Integer (optional)

Exits immediately with exitCode. exitCode defaults to 0.

All windows will be closed immediately without asking the user, and the before-quit and will-quit events will not be emitted.

app.relaunch([options])

  • options Object (optional)
    • args String[] (optional)
    • execPath String (optional)

Relaunches the app when current instance exits.

By default, the new instance will use the same working directory and command line arguments with current instance. When args is specified, the args will be passed as command line arguments instead. When execPath is specified, the execPath will be executed for relaunch instead of current app.

Note that this method does not quit the app when executed, you have to call app.quit or app.exit after calling app.relaunch to make the app restart.

When app.relaunch is called for multiple times, multiple instances will be started after current instance exited.

An example of restarting current instance immediately and adding a new command line argument to the new instance:

const { app } = require('electron')

app.relaunch({ args: process.argv.slice(1).concat(['--relaunch']) })
app.exit(0)

app.isReady()

Returns Boolean - true if Electron has finished initializing, false otherwise. See also app.whenReady().

app.whenReady()

Returns Promise<void> - fulfilled when Electron is initialized. May be used as a convenient alternative to checking app.isReady() and subscribing to the ready event if the app is not ready yet.

app.focus([options])

  • options Object (optional)
    • steal Boolean macOS - Make the receiver the active app even if another app is currently active.

On Linux, focuses on the first visible window. On macOS, makes the application the active app. On Windows, focuses on the application's first window.

You should seek to use the steal option as sparingly as possible.

app.hide() macOS

Hides all application windows without minimizing them.

app.show() macOS

Shows application windows after they were hidden. Does not automatically focus them.

app.setAppLogsPath([path])

  • path String (optional) - A custom path for your logs. Must be absolute.

Sets or creates a directory your app's logs which can then be manipulated with app.getPath() or app.setPath(pathName, newPath).

Calling app.setAppLogsPath() without a path parameter will result in this directory being set to ~/Library/Logs/YourAppName on macOS, and inside the userData directory on Linux and Windows.

app.getAppPath()

Returns String - The current application directory.

app.getPath(name)

  • name String - You can request the following paths by the name:
    • home User's home directory.
    • appData Per-user application data directory, which by default points to:
      • %APPDATA% on Windows
      • $XDG_CONFIG_HOME or ~/.config on Linux
      • ~/Library/Application Support on macOS
    • userData The directory for storing your app's configuration files, which by default it is the appData directory appended with your app's name.
    • cache
    • temp Temporary directory.
    • exe The current executable file.
    • module The libchromiumcontent library.
    • desktop The current user's Desktop directory.
    • documents Directory for a user's "My Documents".
    • downloads Directory for a user's downloads.
    • music Directory for a user's music.
    • pictures Directory for a user's pictures.
    • videos Directory for a user's videos.
    • recent Directory for the user's recent files (Windows only).
    • logs Directory for your app's log folder.
    • pepperFlashSystemPlugin Full path to the system version of the Pepper Flash plugin.
    • crashDumps Directory where crash dumps are stored.

Returns String - A path to a special directory or file associated with name. On failure, an Error is thrown.

If app.getPath('logs') is called without called app.setAppLogsPath() being called first, a default log directory will be created equivalent to calling app.setAppLogsPath() without a path parameter.

app.getFileIcon(path[, options])

  • path String
  • options Object (optional)
    • size String
      • small - 16x16
      • normal - 32x32
      • large - 48x48 on Linux, 32x32 on Windows, unsupported on macOS.

Returns Promise<NativeImage> - fulfilled with the app's icon, which is a NativeImage.

Fetches a path's associated icon.

On Windows, there a 2 kinds of icons:

  • Icons associated with certain file extensions, like .mp3, .png, etc.
  • Icons inside the file itself, like .exe, .dll, .ico.

On Linux and macOS, icons depend on the application associated with file mime type.

app.setPath(name, path)

  • name String
  • path String

Overrides the path to a special directory or file associated with name. If the path specifies a directory that does not exist, an Error is thrown. In that case, the directory should be created with fs.mkdirSync or similar.

You can only override paths of a name defined in app.getPath.

By default, web pages' cookies and caches will be stored under the userData directory. If you want to change this location, you have to override the userData path before the ready event of the app module is emitted.

app.getVersion()

Returns String - The version of the loaded application. If no version is found in the application's package.json file, the version of the current bundle or executable is returned.

app.getName()

Returns String - The current application's name, which is the name in the application's package.json file.

Usually the name field of package.json is a short lowercase name, according to the npm modules spec. You should usually also specify a productName field, which is your application's full capitalized name, and which will be preferred over name by Electron.

app.setName(name)

  • name String

Overrides the current application's name.

Note: This function overrides the name used internally by Electron; it does not affect the name that the OS uses.

app.getLocale()

Returns String - The current application locale. Possible return values are documented here.

To set the locale, you'll want to use a command line switch at app startup, which may be found here.

Note: When distributing your packaged app, you have to also ship the locales folder.

Note: On Windows, you have to call it after the ready events gets emitted.

app.getLocaleCountryCode()

Returns String - User operating system's locale two-letter ISO 3166 country code. The value is taken from native OS APIs.

Note: When unable to detect locale country code, it returns empty string.

app.addRecentDocument(path) macOS Windows

  • path String

Adds path to the recent documents list.

This list is managed by the OS. On Windows, you can visit the list from the task bar, and on macOS, you can visit it from dock menu.

app.clearRecentDocuments() macOS Windows

Clears the recent documents list.

app.setAsDefaultProtocolClient(protocol[, path, args])

  • protocol String - The name of your protocol, without ://. For example, if you want your app to handle electron:// links, call this method with electron as the parameter.
  • path String (optional) Windows - The path to the Electron executable. Defaults to process.execPath
  • args String[] (optional) Windows - Arguments passed to the executable. Defaults to an empty array

Returns Boolean - Whether the call succeeded.

Sets the current executable as the default handler for a protocol (aka URI scheme). It allows you to integrate your app deeper into the operating system. Once registered, all links with your-protocol:// will be opened with the current executable. The whole link, including protocol, will be passed to your application as a parameter.

Note: On macOS, you can only register protocols that have been added to your app's info.plist, which cannot be modified at runtime. However, you can change the file during build time via Electron Forge, Electron Packager, or by editing info.plist with a text editor. Please refer to Apple's documentation for details.

Note: In a Windows Store environment (when packaged as an appx) this API will return true for all calls but the registry key it sets won't be accessible by other applications. In order to register your Windows Store application as a default protocol handler you must declare the protocol in your manifest.

The API uses the Windows Registry and LSSetDefaultHandlerForURLScheme internally.

app.removeAsDefaultProtocolClient(protocol[, path, args]) macOS Windows

  • protocol String - The name of your protocol, without ://.
  • path String (optional) Windows - Defaults to process.execPath
  • args String[] (optional) Windows - Defaults to an empty array

Returns Boolean - Whether the call succeeded.

This method checks if the current executable as the default handler for a protocol (aka URI scheme). If so, it will remove the app as the default handler.

app.isDefaultProtocolClient(protocol[, path, args])

  • protocol String - The name of your protocol, without ://.
  • path String (optional) Windows - Defaults to process.execPath
  • args String[] (optional) Windows - Defaults to an empty array

Returns Boolean - Whether the current executable is the default handler for a protocol (aka URI scheme).

Note: On macOS, you can use this method to check if the app has been registered as the default protocol handler for a protocol. You can also verify this by checking ~/Library/Preferences/com.apple.LaunchServices.plist on the macOS machine. Please refer to Apple's documentation for details.

The API uses the Windows Registry and LSCopyDefaultHandlerForURLScheme internally.

app.getApplicationNameForProtocol(url)

  • url String - a URL with the protocol name to check. Unlike the other methods in this family, this accepts an entire URL, including :// at a minimum (e.g. https://).

Returns String - Name of the application handling the protocol, or an empty string if there is no handler. For instance, if Electron is the default handler of the URL, this could be Electron on Windows and Mac. However, don't rely on the precise format which is not guaranteed to remain unchanged. Expect a different format on Linux, possibly with a .desktop suffix.

This method returns the application name of the default handler for the protocol (aka URI scheme) of a URL.

app.getApplicationInfoForProtocol(url) macOS Windows

  • url String - a URL with the protocol name to check. Unlike the other methods in this family, this accepts an entire URL, including :// at a minimum (e.g. https://).

Returns Promise<Object> - Resolve with an object containing the following:

  • icon NativeImage - the display icon of the app handling the protocol.
  • path String - installation path of the app handling the protocol.
  • name String - display name of the app handling the protocol.

This method returns a promise that contains the application name, icon and path of the default handler for the protocol (aka URI scheme) of a URL.

app.setUserTasks(tasks) Windows

  • tasks Task[] - Array of Task objects

Adds tasks to the Tasks category of the Jump List on Windows.

tasks is an array of Task objects.

Returns Boolean - Whether the call succeeded.

Note: If you'd like to customize the Jump List even more use app.setJumpList(categories) instead.

app.getJumpListSettings() Windows

Returns Object:

  • minItems Integer - The minimum number of items that will be shown in the Jump List (for a more detailed description of this value see the MSDN docs).
  • removedItems JumpListItem[] - Array of JumpListItem objects that correspond to items that the user has explicitly removed from custom categories in the Jump List. These items must not be re-added to the Jump List in the next call to app.setJumpList(), Windows will not display any custom category that contains any of the removed items.

app.setJumpList(categories) Windows

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 standard Tasks category.
  • fileTypeRegistrationError - An attempt was made to add a file link to the Jump List for a file type the app isn't registered to handle.
  • customCategoryAccessDeniedError - Custom categories can't be added to the Jump List due to user privacy or group policy settings.

If categories is null the previously set custom Jump List (if any) will be replaced by the standard Jump List for the app (managed by Windows).

Note: If a JumpListCategory object has neither the type nor the name property set then its type is assumed to be tasks. If the name property is set but the type property is omitted then the type is assumed to be custom.

Note: Users can remove items from custom categories, and Windows will not allow a removed item to be added back into a custom category until after the next successful call to app.setJumpList(categories). Any attempt to re-add a removed item to a custom category earlier than that will result in the entire custom category being omitted from the Jump List. The list of removed items can be obtained using app.getJumpListSettings().

Here's a very simple example of creating a custom Jump List:

const { app } = require('electron')

app.setJumpList([
  {
    type: 'custom',
    name: 'Recent Projects',
    items: [
      { type: 'file', path: 'C:\\Projects\\project1.proj' },
      { type: 'file', path: 'C:\\Projects\\project2.proj' }
    ]
  },
  { // has a name so `type` is assumed to be "custom"
    name: 'Tools',
    items: [
      {
        type: 'task',
        title: 'Tool A',
        program: process.execPath,
        args: '--run-tool-a',
        icon: process.execPath,
        iconIndex: 0,
        description: 'Runs Tool A'
      },
      {
        type: 'task',
        title: 'Tool B',
        program: process.execPath,
        args: '--run-tool-b',
        icon: process.execPath,
        iconIndex: 0,
        description: 'Runs Tool B'
      }
    ]
  },
  { type: 'frequent' },
  { // has no name and no type so `type` is assumed to be "tasks"
    items: [
      {
        type: 'task',
        title: 'New Project',
        program: process.execPath,
        args: '--new-project',
        description: 'Create a new project.'
      },
      { type: 'separator' },
      {
        type: 'task',
        title: 'Recover Project',
        program: process.execPath,
        args: '--recover-project',
        description: 'Recover Project'
      }
    ]
  }
])

app.requestSingleInstanceLock()

Returns Boolean

The return value of this method indicates whether or not this instance of your application successfully obtained the lock. If it failed to obtain the lock, you can assume that another instance of your application is already running with the lock and exit immediately.

I.e. This method returns true if your process is the primary instance of your application and your app should continue loading. It returns false if your process should immediately quit as it has sent its parameters to another instance that has already acquired the lock.

On macOS, the system enforces single instance automatically when users try to open a second instance of your app in Finder, and the open-file and open-url events will be emitted for that. However when users start your app in command line, the system's single instance mechanism will be bypassed, and you have to use this method to ensure single instance.

An example of activating the window of primary instance when a second instance starts:

const { app } = require('electron')
let myWindow = null

const gotTheLock = app.requestSingleInstanceLock()

if (!gotTheLock) {
  app.quit()
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // Someone tried to run a second instance, we should focus our window.
    if (myWindow) {
      if (myWindow.isMinimized()) myWindow.restore()
      myWindow.focus()
    }
  })

  // Create myWindow, load the rest of the app, etc...
  app.whenReady().then(() => {
    myWindow = createWindow()
  })
}

app.hasSingleInstanceLock()

Returns Boolean

This method returns whether or not this instance of your app is currently holding the single instance lock. You can request the lock with app.requestSingleInstanceLock() and release with app.releaseSingleInstanceLock()

app.releaseSingleInstanceLock()

Releases all locks that were created by requestSingleInstanceLock. This will allow multiple instances of the application to once again run side by side.

app.setUserActivity(type, userInfo[, webpageURL]) macOS

  • type String - Uniquely identifies the activity. Maps to NSUserActivity.activityType.
  • userInfo any - App-specific state to store for use by another device.
  • webpageURL String (optional) - The webpage to load in a browser if no suitable app is installed on the resuming device. The scheme must be http or https.

Creates an NSUserActivity and sets it as the current activity. The activity is eligible for Handoff to another device afterward.

app.getCurrentActivityType() macOS

Returns String - The type of the currently running activity.

app.invalidateCurrentActivity() macOS

Invalidates the current Handoff user activity.

app.resignCurrentActivity() macOS

Marks the current Handoff user activity as inactive without invalidating it.

app.updateCurrentActivity(type, userInfo) macOS

  • type String - Uniquely identifies the activity. Maps to NSUserActivity.activityType.
  • userInfo any - App-specific state to store for use by another device.

Updates the current activity if its type matches type, merging the entries from userInfo into its current userInfo dictionary.

app.setAppUserModelId(id) Windows

  • id String

Changes the Application User Model ID to id.

app.setActivationPolicy(policy) macOS

  • policy String - Can be 'regular', 'accessory', or 'prohibited'.

Sets the activation policy for a given app.

Activation policy types:

  • 'regular' - The application is an ordinary app that appears in the Dock and may have a user interface.
  • 'accessory' - The application doesn’t appear in the Dock and doesn’t have a menu bar, but it may be activated programmatically or by clicking on one of its windows.
  • 'prohibited' - The application doesn’t appear in the Dock and may not create windows or be activated.

app.importCertificate(options, callback) Linux

  • options Object
    • certificate String - Path for the pkcs12 file.
    • password String - Passphrase for the certificate.
  • callback Function
    • result Integer - Result of import.

Imports the certificate in pkcs12 format into the platform certificate store. callback is called with the result of import operation, a value of 0 indicates success while any other value indicates failure according to Chromium net_error_list.

app.disableHardwareAcceleration()

Disables hardware acceleration for current app.

This method can only be called before app is ready.

app.disableDomainBlockingFor3DAPIs()

By default, Chromium disables 3D APIs (e.g. WebGL) until restart on a per domain basis if the GPU processes crashes too frequently. This function disables that behavior.

This method can only be called before app is ready.

app.getAppMetrics()

Returns ProcessMetric[]: Array of ProcessMetric objects that correspond to memory and CPU usage statistics of all the processes associated with the app.

app.getGPUFeatureStatus()

Returns GPUFeatureStatus - The Graphics Feature Status from chrome://gpu/.

Note: This information is only usable after the gpu-info-update event is emitted.

app.getGPUInfo(infoType)

  • infoType String - Can be basic or complete.

Returns Promise<unknown>

For infoType equal to complete: Promise is fulfilled with Object containing all the GPU Information as in chromium's GPUInfo object. This includes the version and driver information that's shown on chrome://gpu page.

For infoType equal to basic: Promise is fulfilled with Object containing fewer attributes than when requested with complete. Here's an example of basic response:

{
  auxAttributes:
   {
     amdSwitchable: true,
     canSupportThreadedTextureMailbox: false,
     directComposition: false,
     directRendering: true,
     glResetNotificationStrategy: 0,
     inProcessGpu: true,
     initializationTime: 0,
     jpegDecodeAcceleratorSupported: false,
     optimus: false,
     passthroughCmdDecoder: false,
     sandboxed: false,
     softwareRendering: false,
     supportsOverlays: false,
     videoDecodeAcceleratorFlags: 0
   },
  gpuDevice:
   [{ active: true, deviceId: 26657, vendorId: 4098 },
     { active: false, deviceId: 3366, vendorId: 32902 }],
  machineModelName: 'MacBookPro',
  machineModelVersion: '11.5'
}

Using basic should be preferred if only basic information like vendorId or driverId is needed.

app.setBadgeCount(count) Linux macOS

  • count Integer

Returns Boolean - Whether the call succeeded.

Sets the counter badge for current app. Setting the count to 0 will hide the badge.

On macOS, it shows on the dock icon. On Linux, it only works for Unity launcher.

Note: Unity launcher requires the existence of a .desktop file to work, for more information please read Desktop Environment Integration.

app.getBadgeCount() Linux macOS

Returns Integer - The current value displayed in the counter badge.

app.isUnityRunning() Linux

Returns Boolean - Whether the current desktop environment is Unity launcher.

app.getLoginItemSettings([options]) macOS Windows

  • options Object (optional)
    • path String (optional) Windows - The executable path to compare against. Defaults to process.execPath.
    • args String[] (optional) Windows - The command-line arguments to compare against. Defaults to an empty array.

If you provided path and args options to app.setLoginItemSettings, then you need to pass the same arguments here for openAtLogin to be set correctly.

Returns Object:

  • openAtLogin Boolean - true if the app is set to open at login.
  • openAsHidden Boolean macOS - true if the app is set to open as hidden at login. This setting is not available on MAS builds.
  • wasOpenedAtLogin Boolean macOS - true if the app was opened at login automatically. This setting is not available on MAS builds.
  • wasOpenedAsHidden Boolean macOS - true if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. This setting is not available on MAS builds.
  • restoreState Boolean macOS - true if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was closed. This setting is not available on MAS builds.
  • executableWillLaunchAtLogin Boolean Windows - true if app is set to open at login and its run key is not deactivated. This differs from openAtLogin as it ignores the args option, this property will be true if the given executable would be launched at login with any arguments.
  • launchItems Object[] Windows
    • name String Windows - name value of a registry entry.
    • path String Windows - The executable to an app that corresponds to a registry entry.
    • args String[] Windows - the command-line arguments to pass to the executable.
    • scope String Windows - one of user or machine. Indicates whether the registry entry is under HKEY_CURRENT USER or HKEY_LOCAL_MACHINE.
    • enabled Boolean Windows - true if the app registry key is startup approved and therefore shows as enabled in Task Manager and Windows settings.

app.setLoginItemSettings(settings) macOS Windows

  • settings Object
    • openAtLogin Boolean (optional) - true to open the app at login, false to remove the app as a login item. Defaults to false.
    • openAsHidden Boolean (optional) macOS - true to open the app as hidden. Defaults to false. The user can edit this setting from the System Preferences so app.getLoginItemSettings().wasOpenedAsHidden should be checked when the app is opened to know the current value. This setting is not available on MAS builds.
    • path String (optional) Windows - The executable to launch at login. Defaults to process.execPath.
    • args String[] (optional) Windows - The command-line arguments to pass to the executable. Defaults to an empty array. Take care to wrap paths in quotes.
    • enabled Boolean (optional) Windows - true will change the startup approved registry key and enable / disable the App in Task Manager and Windows Settings. Defaults to true.
    • name String (optional) Windows - value name to write into registry. Defaults to the app's AppUserModelId(). Set the app's login item settings.

To work with Electron's autoUpdater on Windows, which uses Squirrel, you'll want to set the launch path to Update.exe, and pass arguments that specify your application name. For example:

const appFolder = path.dirname(process.execPath)
const updateExe = path.resolve(appFolder, '..', 'Update.exe')
const exeName = path.basename(process.execPath)

app.setLoginItemSettings({
  openAtLogin: true,
  path: updateExe,
  args: [
    '--processStart', `"${exeName}"`,
    '--process-start-args', `"--hidden"`
  ]
})

app.isAccessibilitySupportEnabled() macOS Windows

Returns Boolean - true if Chrome's accessibility support is enabled, false otherwise. This API will return true if the use of assistive technologies, such as screen readers, has been detected. See https://www.chromium.org/developers/design-documents/accessibility for more details.

app.setAccessibilitySupportEnabled(enabled) macOS Windows

Manually enables Chrome's accessibility support, allowing to expose accessibility switch to users in application settings. See Chromium's accessibility docs for more details. Disabled by default.

This API must be called after the ready event is emitted.

Note: Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.

app.showAboutPanel()

Show the app's about panel options. These options can be overridden with app.setAboutPanelOptions(options).

app.setAboutPanelOptions(options)

  • options Object
    • applicationName String (optional) - The app's name.
    • applicationVersion String (optional) - The app's version.
    • copyright String (optional) - Copyright information.
    • version String (optional) macOS - The app's build version number.
    • credits String (optional) macOS Windows - Credit information.
    • authors String[] (optional) Linux - List of app authors.
    • website String (optional) Linux - The app's website.
    • iconPath String (optional) Linux Windows - Path to the app's icon in a JPEG or PNG file format. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.

Set the about panel options. This will override the values defined in the app's .plist file on macOS. See the Apple docs for more details. On Linux, values must be set in order to be shown; there are no defaults.

If you do not set credits but still wish to surface them in your app, AppKit will look for a file named "Credits.html", "Credits.rtf", and "Credits.rtfd", in that order, in the bundle returned by the NSBundle class method main. The first file found is used, and if none is found, the info area is left blank. See Apple documentation for more information.

app.isEmojiPanelSupported()

Returns Boolean - whether or not the current OS version allows for native emoji pickers.

app.showEmojiPanel() macOS Windows

Show the platform's native emoji picker.

app.startAccessingSecurityScopedResource(bookmarkData) mas

  • bookmarkData String - The base64 encoded security scoped bookmark data returned by the dialog.showOpenDialog or dialog.showSaveDialog methods.

Returns Function - This function must be called once you have finished accessing the security scoped file. If you do not remember to stop accessing the bookmark, kernel resources will be leaked and your app will lose its ability to reach outside the sandbox completely, until your app is restarted.

// Start accessing the file.
const stopAccessingSecurityScopedResource = app.startAccessingSecurityScopedResource(data)
// You can now access the file outside of the sandbox 🎉

// Remember to stop accessing the file once you've finished with it.
stopAccessingSecurityScopedResource()

Start accessing a security scoped resource. With this method Electron applications that are packaged for the Mac App Store may reach outside their sandbox to access files chosen by the user. See Apple's documentation for a description of how this system works.

app.enableSandbox()

Enables full sandbox mode on the app. This means that all renderers will be launched sandboxed, regardless of the value of the sandbox flag in WebPreferences.

This method can only be called before app is ready.

app.isInApplicationsFolder() macOS

Returns Boolean - Whether the application is currently running from the systems Application folder. Use in combination with app.moveToApplicationsFolder()

app.moveToApplicationsFolder([options]) macOS

  • options Object (optional)
    • conflictHandler Function\ (optional) - A handler for potential conflict in move failure.
      • conflictType String - The type of move conflict encountered by the handler; can be exists or existsAndRunning, where exists means that an app of the same name is present in the Applications directory and existsAndRunning means both that it exists and that it's presently running.

Returns Boolean - Whether the move was successful. Please note that if the move is successful, your application will quit and relaunch.

No confirmation dialog will be presented by default. If you wish to allow the user to confirm the operation, you may do so using the dialog API.

NOTE: This method throws errors if anything other than the user causes the move to fail. For instance if the user cancels the authorization dialog, this method returns false. If we fail to perform the copy, then this method will throw an error. The message in the error should be informative and tell you exactly what went wrong.

By default, if an app of the same name as the one being moved exists in the Applications directory and is not running, the existing app will be trashed and the active app moved into its place. If it is running, the pre-existing running app will assume focus and the previously active app will quit itself. This behavior can be changed by providing the optional conflict handler, where the boolean returned by the handler determines whether or not the move conflict is resolved with default behavior. i.e. returning false will ensure no further action is taken, returning true will result in the default behavior and the method continuing.

For example:

app.moveToApplicationsFolder({
  conflictHandler: (conflictType) => {
    if (conflictType === 'exists') {
      return dialog.showMessageBoxSync({
        type: 'question',
        buttons: ['Halt Move', 'Continue Move'],
        defaultId: 0,
        message: 'An app of this name already exists'
      }) === 1
    }
  }
})

Would mean that if an app already exists in the user directory, if the user chooses to 'Continue Move' then the function would continue with its default behavior and the existing app will be trashed and the active app moved into its place.

app.isSecureKeyboardEntryEnabled() macOS

Returns Boolean - whether Secure Keyboard Entry is enabled.

By default this API will return false.

app.setSecureKeyboardEntryEnabled(enabled) macOS

  • enabled Boolean - Enable or disable Secure 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.

Properties

app.accessibilitySupportEnabled macOS Windows

A Boolean property that's true if Chrome's accessibility support is enabled, false otherwise. This property will be true if the use of assistive technologies, such as screen readers, has been detected. Setting this property to true manually enables Chrome's accessibility support, allowing developers to expose accessibility switch to users in application settings.

See Chromium's accessibility docs for more details. Disabled by default.

This API must be called after the ready event is emitted.

Note: Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.

app.applicationMenu

A Menu | null property that returns Menu if one has been set and null otherwise. Users can pass a Menu to set this property.

app.badgeCount Linux macOS

An Integer property that returns the badge count for current app. Setting the count to 0 will hide the badge.

On macOS, setting this with any nonzero integer shows on the dock icon. On Linux, this property only works for Unity launcher.

Note: Unity launcher requires the existence of a .desktop file to work, for more information please read Desktop Environment Integration.

Note: On macOS, you need to ensure that your application has the permission to display notifications for this property to take effect.

app.commandLine Readonly

A CommandLine object that allows you to read and manipulate the command line arguments that Chromium uses.

app.dock macOS Readonly

A Dock | undefined object that allows you to perform actions on your app icon in the user's dock on macOS.

app.isPackaged Readonly

A Boolean property that returns true if the app is packaged, false otherwise. For many apps, this property can be used to distinguish development and production environments.

app.name

A String property that indicates the current application's name, which is the name in the application's package.json file.

Usually the name field of package.json is a short lowercase name, according to the npm modules spec. You should usually also specify a productName field, which is your application's full capitalized name, and which will be preferred over name by Electron.

app.userAgentFallback

A String which is the user agent string Electron will use as a global fallback.

This is the user agent that will be used when no user agent is set at the webContents or session level. It is useful for ensuring that your entire app has the same user agent. Set to a custom value as early as possible in your app's initialization to ensure that your overridden value is used.

app.allowRendererProcessReuse

A Boolean which when true disables the overrides that Electron has in place to ensure renderer processes are restarted on every navigation. The current default value for this property is true.

The intention is for these overrides to become disabled by default and then at some point in the future this property will be removed. This property impacts which native modules you can use in the renderer process. For more information on the direction Electron is going with renderer process restarts and usage of native modules in the renderer process please check out this Tracking Issue.

app.runningUnderRosettaTranslation macOS Readonly

A Boolean which when true indicates that the app is currently running under the Rosetta Translator Environment.

You can use this property to prompt users to download the arm64 version of your application when they are running the x64 version under Rosetta incorrectly.

Application Debugging

Whenever your Electron application is not behaving the way you wanted it to, an array of debugging tools might help you find coding errors, performance bottlenecks, or optimization opportunities.

Renderer Process

The most comprehensive tool to debug individual renderer processes is the Chromium Developer Toolset. It is available for all renderer processes, including instances of BrowserWindow, BrowserView, and WebView. You can open them programmatically by calling the openDevTools() API on the webContents of the instance:

const { BrowserWindow } = require('electron')

const win = new BrowserWindow()
win.webContents.openDevTools()

Google offers excellent documentation for their developer tools. We recommend that you make yourself familiar with them - they are usually one of the most powerful utilities in any Electron Developer's tool belt.

Main Process

Debugging the main process is a bit trickier, since you cannot open developer tools for them. The Chromium Developer Tools can be used to debug Electron's main process thanks to a closer collaboration between Google / Chrome and Node.js, but you might encounter oddities like require not being present in the console.

For more information, see the Debugging the Main Process documentation.

V8 Crashes

If the V8 context crashes, the DevTools will display this message.

DevTools was disconnected from the page. Once page is reloaded, DevTools will automatically reconnect.

Chromium logs can be enabled via the ELECTRON_ENABLE_LOGGING environment variable. For more information, see the environment variables documentation.

Alternatively, the command line argument --enable-logging can be passed. More information is available in the command line switches documentation.

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.plist
  • Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist

You can also rename the helper app to avoid showing Electron Helper in the Activity Monitor, but make sure you have renamed the helper app's executable file's name.

The structure of a renamed app would be like:

MyApp.app/Contents
├── Info.plist
├── MacOS/
│   └── MyApp
└── Frameworks/
    └── MyApp Helper.app
        ├── Info.plist
        └── MacOS/
            └── MyApp Helper

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

  1. Install Surf, via npm: npm install -g [email protected]

  2. Create a new S3 bucket and create the following empty directory structure:

    - electron/
      - symbols/
      - dist/
    
  3. Set the following Environment Variables:

    • ELECTRON_GITHUB_TOKEN - a token that can create releases on GitHub
    • ELECTRON_S3_ACCESS_KEY, ELECTRON_S3_BUCKET, ELECTRON_S3_SECRET_KEY - the place where you'll upload Node.js headers as well as symbols
    • ELECTRON_RELEASE - Set to true and the upload part will run, leave unset and surf-build will do CI-type checks, appropriate to run for every pull request.
    • CI - Set to true or else it will fail
    • GITHUB_TOKEN - set it to the same as ELECTRON_GITHUB_TOKEN
    • SURF_TEMP - set to C:\Temp on Windows to prevent path too long issues
    • TARGET_ARCH - set to ia32 or x64
  4. In script/upload.py, you must set ELECTRON_REPO to your fork (MYORG/electron), especially if you are a contributor to Electron proper.

  5. surf-build -r https://github.com/MYORG/electron -s YOUR_COMMIT -n 'surf-PLATFORM-ARCH'

  6. 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.execFile
  • child_process.execFileSync
  • fs.open
  • fs.openSync
  • process.dlopen - Used by require on 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: 'error'

Returns:

  • error Error

Emitted when there is an error while updating.

Event: 'checking-for-update'

Emitted when checking if an update has started.

Event: 'update-available'

Emitted when there is an available update. The update is downloaded automatically.

Event: 'update-not-available'

Emitted when there is no available update.

Event: 'update-downloaded'

Returns:

  • event Event
  • releaseNotes String
  • releaseName String
  • releaseDate Date
  • updateURL String

Emitted when an update has been downloaded.

On Windows only releaseName is available.

Note: It is not strictly necessary to handle this event. A successfully downloaded update will still be applied the next time the application starts.

Event: 'before-quit-for-update'

This event is emitted after a user calls quitAndInstall().

When this API is called, the before-quit event is not emitted before all windows are closed. As a result you should listen to this event if you wish to perform actions before the windows are closed while a process is quitting, as well as listening to before-quit.

Methods

The autoUpdater object has the following methods:

autoUpdater.setFeedURL(options)

  • options Object
    • url String
    • headers Record<String, String> (optional) macOS - HTTP request headers.
    • serverType String (optional) macOS - Can be json or default, 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.
  1. 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
  2. Get the Azure storage account key

    • Log into Azure using credentials stored in LastPass (under Azure Enterprise) and then find the storage account corresponding to the name found in AppVeyor.
      • Example, for appveyorlibccbuilds Disk Storage Account Name you'd look for appveyorlibccbuilds in the list of storage accounts @ Home < Storage Accounts
        • Click into it and look for Access Keys, and then you can use any of the keys present in the list.
  3. 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.
  4. 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
    • Go into Azure and get the URI for the newly created image as described in a previous step
  5. Spin up a new VM using the Create Master VM from VHD PowerShell.

    • From PowerShell, execute ps1 file with ./create_master_vm_from_vhd.ps1
    • You will need the credential information available in the AppVeyor build cloud definition.
      • This includes:
        • Client ID
        • Client Secret
        • Tenant ID
        • Subscription ID
        • Resource Group
        • Virtual Network
    • 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
  6. 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.
  7. Using Microsoft Remote Desktop, click Connect to connect to the VM.

    • Credentials for logging into the VM are found in LastPass under the AppVeyor Enterprise master VM credentials.
  8. Modify the VM as required.

  9. Shut down the VM and then delete it in Azure.

  10. Add the new image to the Appveyor Cloud settings or modify an existing image to point to the new VHD.

BluetoothDevice Object

  • deviceName String
  • deviceId String

Boilerplates and CLIs

Electron development is unopinionated - there is no "one true way" to develop, build, package, or release an Electron application. Additional features for Electron, both for build- and run-time, can usually be found on npm in individual packages, allowing developers to build both the app and build pipeline they need.

That level of modularity and extendability ensures that all developers working with Electron, both big and small in team-size, are never restricted in what they can or cannot do at any time during their development lifecycle. However, for many developers, one of the community-driven boilerplates or command line tools might make it dramatically easier to compile, package, and release an app.

Boilerplate vs CLI

A boilerplate is only a starting point - a canvas, so to speak - from which you build your application. They usually come in the form of a repository you can clone and customize to your heart's content.

A command line tool on the other hand continues to support you throughout the development and release. They are more helpful and supportive but enforce guidelines on how your code should be structured and built. Especially for beginners, using a command line tool is likely to be helpful.

electron-forge

A "complete tool for building modern Electron applications". Electron Forge unifies the existing (and well maintained) build tools for Electron development into a cohesive package so that anyone can jump right in to Electron development.

Forge comes with a ready-to-use template using Webpack as a bundler. It includes an example typescript configuration and provides two configuration files to enable easy customization. It uses the same core modules used by the greater Electron community (like electron-packager) – changes made by Electron maintainers (like Slack) benefit Forge's users, too.

You can find more information and documentation on electronforge.io.

electron-builder

A "complete solution to package and build a ready-for-distribution Electron app" that focuses on an integrated experience. electron-builder adds one single dependency focused on simplicity and manages all further requirements internally.

electron-builder replaces features and modules used by the Electron maintainers (such as the auto-updater) with custom ones. They are generally tighter integrated but will have less in common with popular Electron apps like Atom, Visual Studio Code, or Slack.

You can find more information and documentation in the repository.

electron-react-boilerplate

If you don't want any tools but only a solid boilerplate to build from, CT Lin's electron-react-boilerplate might be worth a look. It's quite popular in the community and uses electron-builder internally.

Other Tools and Boilerplates

The "Awesome Electron" list contains more tools and boilerplates to choose from. If you find the length of the list intimidating, don't forget that adding tools as you go along is a valid approach, too.

Breaking Changes

Breaking changes will be documented here, and deprecation warnings added to JS code where possible, at least one major version before the change is made.

Types of Breaking Changes

This document uses the following convention to categorize breaking changes:

  • API Changed: An API was changed in such a way that code that has not been updated is guaranteed to throw an exception.
  • Behavior Changed: The behavior of Electron has changed, but not in such a way that an exception will necessarily be thrown.
  • Default Changed: Code depending on the old default may break, not necessarily throwing an exception. The old behavior can be restored by explicitly specifying the value.
  • Deprecated: An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
  • Removed: An API or feature was removed, and is no longer supported by Electron.

Planned Breaking API Changes (13.0)

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(/* ... */)

Planned Breaking API Changes (12.0)

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.start
  • crashReporter.getLastCrashReport
  • crashReporter.getUploadedReports
  • crashReporter.getUploadToServer
  • crashReporter.setUploadToServer
  • crashReporter.getCrashesDirectory

They should be called only from the main process.

See #23265 for more details.

Default Changed: crashReporter.start({ compress: true })

The default value of the compress option to crashReporter.start has changed from false to true. This means that crash dumps will be uploaded to the crash ingestion server with the Content-Encoding: gzip header, and the body will be compressed.

If your crash ingestion server does not support compressed payloads, you can turn off compression by specifying { compress: false } in the crash reporter options.

Deprecated: remote module

The remote module is deprecated in Electron 12, and will be removed in Electron 14. It is replaced by the @electron/remote module.

// Deprecated in Electron 12:
const { BrowserWindow } = require('electron').remote
// Replace with:
const { BrowserWindow } = require('@electron/remote')

// In the main process:
require('@electron/remote/main').initialize()

Deprecated: shell.moveItemToTrash()

The synchronous shell.moveItemToTrash() has been replaced by the new, asynchronous shell.trashItem().

// Deprecated in Electron 12
shell.moveItemToTrash(path)
// Replace with
shell.trashItem(path).then(/* ... */)

Planned Breaking API Changes (11.0)

Removed: BrowserView.{destroy, fromId, fromWebContents, getAllViews} and id property of BrowserView

The experimental APIs BrowserView.{destroy, fromId, fromWebContents, getAllViews} have now been removed. Additionally, the id property of BrowserView has also been removed.

For more detailed information, see #23578.

Planned Breaking API Changes (10.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.start
  • crashReporter.getLastCrashReport
  • crashReporter.getUploadedReports
  • crashReporter.getUploadToServer
  • crashReporter.setUploadToServer
  • crashReporter.getCrashesDirectory

The only non-deprecated methods remaining in the crashReporter module in the renderer are addExtraParameter, removeExtraParameter and getParameters.

All above methods remain non-deprecated when called from the main process.

See #23265 for more details.

Deprecated: crashReporter.start({ compress: false })

Setting { compress: false } in crashReporter.start is deprecated. Nearly all crash ingestion servers support gzip compression. This option will be removed in a future version of Electron.

Removed: Browser Window Affinity

The affinity option when constructing a new BrowserWindow will be removed as part of our plan to more closely align with Chromium's process model for security, performance and maintainability.

For more detailed information see #18397.

Default Changed: enableRemoteModule defaults to false

In Electron 9, using the remote module without explicitly enabling it via the enableRemoteModule WebPreferences option began emitting a warning. In Electron 10, the remote module is now disabled by default. To use the remote module, enableRemoteModule: true must be specified in WebPreferences:

const w = new BrowserWindow({
  webPreferences: {
    enableRemoteModule: true
  }
})

We recommend moving away from the remote module.

protocol.unregisterProtocol

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.registerFileProtocol

protocol.registerBufferProtocol

protocol.registerStringProtocol

protocol.registerHttpProtocol

protocol.registerStreamProtocol

protocol.interceptFileProtocol

protocol.interceptStringProtocol

protocol.interceptBufferProtocol

protocol.interceptHttpProtocol

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)

Planned Breaking API Changes (9.0)

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.

Planned Breaking API Changes (8.0)

Behavior Changed: Values sent over IPC are now serialized with Structured Clone Algorithm

The algorithm used to serialize objects sent over IPC (through ipcRenderer.send, ipcRenderer.sendSync, WebContents.send and related methods) has been switched from a custom algorithm to V8's built-in Structured Clone Algorithm, the same algorithm used to serialize messages for postMessage. This brings about a 2x performance improvement for large messages, but also brings some breaking changes in behavior.

  • Sending Functions, Promises, WeakMaps, WeakSets, or objects containing any such values, over IPC will now throw an exception, instead of silently converting the functions to undefined.
// Previously:
ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
// => results in { value: 3 } arriving in the main process

// From Electron 8:
ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
// => throws Error("() => {} could not be cloned.")
  • NaN, Infinity and -Infinity will now be correctly serialized, instead of being converted to null.
  • Objects containing cyclic references will now be correctly serialized, instead of being converted to null.
  • Set, Map, Error and RegExp values will be correctly serialized, instead of being converted to {}.
  • BigInt values will be correctly serialized, instead of being converted to null.
  • Sparse arrays will be serialized as such, instead of being converted to dense arrays with nulls.
  • Date objects will be transferred as Date objects, instead of being converted to their ISO string representation.
  • Typed Arrays (such as Uint8Array, Uint16Array, Uint32Array and so on) will be transferred as such, instead of being converted to Node.js Buffer.
  • Node.js Buffer objects will be transferred as Uint8Arrays. You can convert a Uint8Array back to a Node.js Buffer by wrapping the underlying ArrayBuffer:
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.

Planned Breaking API Changes (7.0)

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).

Planned Breaking API Changes (6.0)

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.

Planned Breaking API Changes (5.0)

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)
// Removed
menu.popup(browserWindow, 100, 200, 2)
// Replaced with
menu.popup(browserWindow, { x: 100, y: 200, positioningItem: 2 })

nativeImage

// Removed
nativeImage.toPng()
// Replaced with
nativeImage.toPNG()

// Removed
nativeImage.toJpeg()
// Replaced with
nativeImage.toJPEG()

process

  • process.versions.electron and process.version.chrome will be made read-only properties for consistency with the other process.versions properties set by Node.

webContents

// Removed
webContents.setZoomLevelLimits(1, 2)
// Replaced with
webContents.setVisualZoomLevelLimits(1, 2)

webFrame

// Removed
webFrame.setZoomLevelLimits(1, 2)
// Replaced with
webFrame.setVisualZoomLevelLimits(1, 2)

<webview>

// Removed
webview.setZoomLevelLimits(1, 2)
// Replaced with
webview.setVisualZoomLevelLimits(1, 2)

Duplicate ARM Assets

Each Electron release includes two identical ARM builds with slightly different filenames, like electron-v1.7.3-linux-arm.zip and electron-v1.7.3-linux-armv7l.zip. The asset with the v7l prefix was added to clarify to users which ARM version it supports, and to disambiguate it from future armv6l and arm64 assets that may be produced.

The file without the prefix is still being published to avoid breaking any setups that may be consuming it. Starting at 2.0, the unprefixed file will no longer be published.

For details, see 6986 and 7189.

Class: BrowserView

Create and control views.

Process: Main

A BrowserView can be used to embed additional web content into a BrowserWindow. It is like a child window, except that it is positioned relative to its owning window. It is meant to be an alternative to the webview tag.

Example

// In the main process.
const { BrowserView, BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 600 })

const view = new BrowserView()
win.setBrowserView(view)
view.setBounds({ x: 0, y: 0, width: 300, height: 300 })
view.webContents.loadURL('https://electronjs.org')

new BrowserView([options]) Experimental

  • options Object (optional)

Instance Properties

Objects created with new BrowserView have the following properties:

view.webContents Experimental

A WebContents object owned by this view.

Instance Methods

Objects created with new BrowserView have the following instance methods:

view.setAutoResize(options) Experimental

  • options Object
    • width Boolean (optional) - If true, the view's width will grow and shrink together with the window. false by default.
    • height Boolean (optional) - If true, the view's height will grow and shrink together with the window. false by default.
    • horizontal Boolean (optional) - If true, the view's x position and width will grow and shrink proportionally with the window. false by default.
    • vertical Boolean (optional) - If true, the view's y position and height will grow and shrink proportionally with the window. false by default.

view.setBounds(bounds) Experimental

Resizes and moves the view to the supplied bounds relative to the window.

view.getBounds() Experimental

Returns Rectangle

The bounds of this BrowserView instance as Object.

view.setBackgroundColor(color) Experimental

  • color String - Color in #aarrggbb or #argb form. The alpha channel is optional.

BrowserWindow

Create and control browser windows.

Process: Main

// In the main process.
const { BrowserWindow } = require('electron')

// Or use `remote` from the renderer process.
// const { BrowserWindow } = require('electron').remote

const win = new BrowserWindow({ width: 800, height: 600 })

// Load a remote URL
win.loadURL('https://github.com')

// Or load a local HTML file
win.loadURL(`file://${__dirname}/app/index.html`)

Frameless window

To create a window without chrome, or a transparent window in arbitrary shape, you can use the Frameless Window API.

Showing window gracefully

When loading a page in the window directly, users may see the page load incrementally, which is not a good experience for a native app. To make the window display without visual flash, there are two solutions for different situations.

Using ready-to-show event

While loading the page, the ready-to-show event will be emitted when the renderer process has rendered the page for the first time if the window has not been shown yet. Showing the window after this event will have no visual flash:

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ show: false })
win.once('ready-to-show', () => {
  win.show()
})

This event is usually emitted after the did-finish-load event, but for pages with many remote resources, it may be emitted before the did-finish-load event.

Please note that using this event implies that the renderer will be considered "visible" and paint even though show is false. This event will never fire if you use paintWhenInitiallyHidden: false

Setting backgroundColor

For a complex app, the ready-to-show event could be emitted too late, making the app feel slow. In this case, it is recommended to show the window immediately, and use a backgroundColor close to your app's background:

const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ backgroundColor: '#2e2c29' })
win.loadURL('https://github.com')

Note that even for apps that use ready-to-show event, it is still recommended to set backgroundColor to make app feel more native.

Parent and child windows

By using parent option, you can create child windows:

const { BrowserWindow } = require('electron')

const top = new BrowserWindow()
const child = new BrowserWindow({ parent: top })
child.show()
top.show()

The child window will always show on top of the top window.

A modal window is a child window that disables parent window, to create a modal window, you have to set both parent and modal options:

const { BrowserWindow } = require('electron')

const child = new BrowserWindow({ parent: top, modal: true, show: false })
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
  child.show()
})

Page visibility

The Page Visibility API works as follows:

  • On all platforms, the visibility state tracks whether the window is hidden/minimized or not.
  • Additionally, on macOS, the visibility state also tracks the window occlusion state. If the window is occluded (i.e. fully covered) by another window, the visibility state will be hidden. On other platforms, the visibility state will be hidden only when the window is minimized or explicitly hidden with win.hide().
  • If a BrowserWindow is created with show: false, the initial visibility state will be visible despite the window actually being hidden.
  • If backgroundThrottling is disabled, the visibility state will remain visible even if the window is minimized, occluded, or hidden.

It is recommended that you pause expensive operations when the visibility state is hidden in order to minimize power consumption.

Platform notices

  • On macOS modal windows will be displayed as sheets attached to the parent window.
  • On macOS the child windows will keep the relative position to parent window when parent window moves, while on Windows and Linux child windows will not move.
  • On Linux the type of modal windows will be changed to dialog.
  • On Linux many desktop environments do not support hiding a modal window.

Class: BrowserWindow

Create and control browser windows.

Process: Main

BrowserWindow is an EventEmitter.

It creates a new BrowserWindow with native properties as set by the options.

new BrowserWindow([options])

  • options Object (optional)
    • width Integer (optional) - Window's width in pixels. Default is 800.
    • height Integer (optional) - Window's height in pixels. Default is 600.
    • x Integer (optional) - (required if y is used) Window's left offset from screen. Default is to center the window.
    • y Integer (optional) - (required if x is used) Window's top offset from screen. Default is to center the window.
    • useContentSize Boolean (optional) - The width and height would be used as web page's size, which means the actual window's size will include window frame's size and be slightly larger. Default is false.
    • center Boolean (optional) - Show window in the center of the screen.
    • minWidth Integer (optional) - Window's minimum width. Default is 0.
    • minHeight Integer (optional) - Window's minimum height. Default is 0.
    • maxWidth Integer (optional) - Window's maximum width. Default is no limit.
    • maxHeight Integer (optional) - Window's maximum height. Default is no limit.
    • resizable Boolean (optional) - Whether window is resizable. Default is true.
    • movable Boolean (optional) - Whether window is movable. This is not implemented on Linux. Default is true.
    • minimizable Boolean (optional) - Whether window is minimizable. This is not implemented on Linux. Default is true.
    • maximizable Boolean (optional) - Whether window is maximizable. This is not implemented on Linux. Default is true.
    • closable Boolean (optional) - Whether window is closable. This is not implemented on Linux. Default is true.
    • focusable Boolean (optional) - Whether the window can be focused. Default is true. On Windows setting focusable: false also implies setting skipTaskbar: true. On Linux setting focusable: false makes the window stop interacting with wm, so the window will always stay on top in all workspaces.
    • alwaysOnTop Boolean (optional) - Whether the window should always stay on top of other windows. Default is false.
    • fullscreen Boolean (optional) - Whether the window should show in fullscreen. When explicitly set to false the fullscreen button will be hidden or disabled on macOS. Default is false.
    • fullscreenable Boolean (optional) - Whether the window can be put into fullscreen mode. On macOS, also whether the maximize/zoom button should toggle full screen mode or maximize window. Default is true.
    • simpleFullscreen Boolean (optional) - Use pre-Lion fullscreen on macOS. Default is false.
    • skipTaskbar Boolean (optional) - Whether to show the window in taskbar. Default is false.
    • kiosk Boolean (optional) - Whether the window is in kiosk mode. Default is false.
    • title String (optional) - Default window title. Default is "Electron". If the HTML tag <title> is defined in the HTML file loaded by loadURL(), this property will be ignored.
    • icon (NativeImage | String) (optional) - The window icon. On Windows it is recommended to use ICO icons to get best visual effects, you can also leave it undefined so the executable's icon will be used.
    • show Boolean (optional) - Whether window should be shown when created. Default is true.
    • paintWhenInitiallyHidden Boolean (optional) - Whether the renderer should be active when show is false and it has just been created. In order for document.visibilityState to work correctly on first load with show: false you should set this to false. Setting this to false will cause the ready-to-show event to not fire. Default is true.
    • frame Boolean (optional) - Specify false to create a Frameless Window. Default is true.
    • parent BrowserWindow (optional) - Specify parent window. Default is null.
    • modal Boolean (optional) - Whether this is a modal window. This only works when the window is a child window. Default is false.
    • acceptFirstMouse Boolean (optional) - Whether the web view accepts a single mouse-down event that simultaneously activates the window. Default is false.
    • disableAutoHideCursor Boolean (optional) - Whether to hide cursor when typing. Default is false.
    • autoHideMenuBar Boolean (optional) - Auto hide the menu bar unless the Alt key is pressed. Default is false.
    • enableLargerThanScreen Boolean (optional) - Enable the window to be resized larger than screen. Only relevant for macOS, as other OSes allow larger-than-screen windows by default. Default is false.
    • backgroundColor String (optional) - Window's background color as a hexadecimal value, like #66CD00 or #FFF or #80FFFFFF (alpha in #AARRGGBB format is supported if transparent is set to true). Default is #FFF (white).
    • hasShadow Boolean (optional) - Whether window should have a shadow. Default is true.
    • opacity Number (optional) - Set the initial opacity of the window, between 0.0 (fully transparent) and 1.0 (fully opaque). This is only implemented on Windows and macOS.
    • darkTheme Boolean (optional) - Forces using dark theme for the window, only works on some GTK+3 desktop environments. Default is false.
    • transparent Boolean (optional) - Makes the window transparent. Default is false. On Windows, does not work unless the window is frameless.
    • type String (optional) - The type of window, default is normal window. See more about this below.
    • visualEffectState String (optional) - Specify how the material appearance should reflect window activity state on macOS. Must be used with the vibrancy property. Possible values are:
      • followWindow - The backdrop should automatically appear active when the window is active, and inactive when it is not. This is the default.
      • active - The backdrop should always appear active.
      • inactive - The backdrop should always appear inactive.
    • titleBarStyle String (optional) - The style of window title bar. Default is default. Possible values are:
      • default - Results in the standard gray opaque Mac title bar.
      • hidden - Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls ("traffic lights") in the top left.
      • hiddenInset - Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge.
      • customButtonsOnHover Boolean (optional) - Draw custom close, and minimize buttons on macOS frameless windows. These buttons will not display unless hovered over in the top left of the window. These custom buttons prevent issues with mouse events that occur with the standard window toolbar buttons. Note: This option is currently experimental.
    • trafficLightPosition Point (optional) - Set a custom position for the traffic light buttons. Can only be used with titleBarStyle set to hidden
    • fullscreenWindowTitle Boolean (optional) - Shows the title in the title bar in full screen mode on macOS for all titleBarStyle options. Default is false.
    • thickFrame Boolean (optional) - Use WS_THICKFRAME style for frameless windows on Windows, which adds standard window frame. Setting it to false will remove window shadow and window animations. Default is true.
    • vibrancy String (optional) - Add a type of vibrancy effect to the window, only on macOS. Can be appearance-based, light, dark, titlebar, selection, menu, popover, sidebar, medium-light, ultra-dark, header, sheet, window, hud, fullscreen-ui, tooltip, content, under-window, or under-page. Please note that using frame: false in combination with a vibrancy value requires that you use a non-default titleBarStyle as well. Also note that appearance-based, light, dark, medium-light, and ultra-dark have been deprecated and will be removed in an upcoming version of macOS.
    • zoomToPageWidth Boolean (optional) - Controls the behavior on macOS when option-clicking the green stoplight button on the toolbar or by clicking the Window > Zoom menu item. If true, the window will grow to the preferred width of the web page when zoomed, false will cause it to zoom to the width of the screen. This will also affect the behavior when calling maximize() directly. Default is false.
    • tabbingIdentifier String (optional) - Tab group name, allows opening the window as a native tab on macOS 10.12+. Windows with the same tabbing identifier will be grouped together. This also adds a native new tab button to your window's tab bar and allows your app and window to receive the new-window-for-tab event.
    • webPreferences Object (optional) - Settings of web page's features.
      • devTools Boolean (optional) - Whether to enable DevTools. If it is set to false, can not use BrowserWindow.webContents.openDevTools() to open DevTools. Default is true.
      • nodeIntegration Boolean (optional) - Whether node integration is enabled. Default is false.
      • nodeIntegrationInWorker Boolean (optional) - Whether node integration is enabled in web workers. Default is false. More about this can be found in Multithreading.
      • nodeIntegrationInSubFrames Boolean (optional) - Experimental option for enabling Node.js support in sub-frames such as iframes and child windows. All your preloads will load for every iframe, you can use process.isMainFrame to determine if you are in the main frame or not.
      • preload String (optional) - Specifies a script that will be loaded before other scripts run in the page. This script will always have access to node APIs no matter whether node integration is turned on or off. The value should be the absolute file path to the script. When node integration is turned off, the preload script can reintroduce Node global symbols back to the global scope. See example here.
      • sandbox Boolean (optional) - If set, this will sandbox the renderer associated with the window, making it compatible with the Chromium OS-level sandbox and disabling the Node.js engine. This is not the same as the nodeIntegration option and the APIs available to the preload script are more limited. Read more about the option here.
      • enableRemoteModule Boolean (optional) - Whether to enable the remote module. Default is false.
      • session Session (optional) - Sets the session used by the page. Instead of passing the Session object directly, you can also choose to use the partition option instead, which accepts a partition string. When both session and partition are provided, session will be preferred. Default is the default session.
      • partition String (optional) - Sets the session used by the page according to the session's partition string. 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. Default is the default session.
      • affinity String (optional) - When specified, web pages with the same affinity will run in the same renderer process. Note that due to reusing the renderer process, certain webPreferences options will also be shared between the web pages even when you specified different values for them, including but not limited to preload, sandbox and nodeIntegration. So it is suggested to use exact same webPreferences for web pages with the same affinity. Deprecated
      • zoomFactor Number (optional) - The default zoom factor of the page, 3.0 represents 300%. Default is 1.0.
      • javascript Boolean (optional) - Enables JavaScript support. Default is true.
      • webSecurity Boolean (optional) - When false, it will disable the same-origin policy (usually using testing websites by people), and set allowRunningInsecureContent to true if this options has not been set by user. Default is true.
      • allowRunningInsecureContent Boolean (optional) - Allow an https page to run JavaScript, CSS or plugins from http URLs. Default is false.
      • images Boolean (optional) - Enables image support. Default is true.
      • textAreasAreResizable Boolean (optional) - Make TextArea elements resizable. Default is true.
      • webgl Boolean (optional) - Enables WebGL support. Default is true.
      • plugins Boolean (optional) - Whether plugins should be enabled. Default is false.
      • experimentalFeatures Boolean (optional) - Enables Chromium's experimental features. Default is false.
      • scrollBounce Boolean (optional) - Enables scroll bounce (rubber banding) effect on macOS. Default is false.
      • enableBlinkFeatures String (optional) - A list of feature strings separated by ,, like CSSVariables,KeyboardEventKey to enable. The full list of supported feature strings can be found in the RuntimeEnabledFeatures.json5 file.
      • disableBlinkFeatures String (optional) - A list of feature strings separated by ,, like CSSVariables,KeyboardEventKey to disable. The full list of supported feature strings can be found in the RuntimeEnabledFeatures.json5 file.
      • defaultFontFamily Object (optional) - Sets the default font for the font-family.
        • standard String (optional) - Defaults to Times New Roman.
        • serif String (optional) - Defaults to Times New Roman.
        • sansSerif String (optional) - Defaults to Arial.
        • monospace String (optional) - Defaults to Courier New.
        • cursive String (optional) - Defaults to Script.
        • fantasy String (optional) - Defaults to Impact.
      • defaultFontSize Integer (optional) - Defaults to 16.
      • defaultMonospaceFontSize Integer (optional) - Defaults to 13.
      • minimumFontSize Integer (optional) - Defaults to 0.
      • defaultEncoding String (optional) - Defaults to ISO-8859-1.
      • backgroundThrottling Boolean (optional) - Whether to throttle animations and timers when the page becomes background. This also affects the Page Visibility API. Defaults to true.
      • offscreen Boolean (optional) - Whether to enable offscreen rendering for the browser window. Defaults to false. See the offscreen rendering tutorial for more details.
      • contextIsolation Boolean (optional) - Whether to run Electron APIs and the specified preload script in a separate JavaScript context. Defaults to false. The context that the preload script runs in will still have full access to the document and window globals but it will use its own set of JavaScript builtins (Array, Object, JSON, etc.) and will be isolated from any changes made to the global environment by the loaded page. The Electron API will only be available in the preload script and not the loaded page. This option should be used when loading potentially untrusted remote content to ensure the loaded content cannot tamper with the preload script and any Electron APIs being used. This option uses the same technique used by Chrome Content Scripts. You can access this context in the dev tools by selecting the 'Electron Isolated Context' entry in the combo box at the top of the Console tab.
      • worldSafeExecuteJavaScript Boolean (optional) - If true, values returned from webFrame.executeJavaScript will be sanitized to ensure JS values can't unsafely cross between worlds when using contextIsolation. The default is false. In Electron 12, the default will be changed to true. Deprecated
      • nativeWindowOpen Boolean (optional) - Whether to use native window.open(). Defaults to false. Child windows will always have node integration disabled unless nodeIntegrationInSubFrames is true. Note: This option is currently experimental.
      • webviewTag Boolean (optional) - Whether to enable the <webview> tag. Defaults to false. Note: The preload script configured for the <webview> will have node integration enabled when it is executed so you should ensure remote/untrusted content is not able to create a <webview> tag with a possibly malicious preload script. You can use the will-attach-webview event on webContents to strip away the preload script and to validate or alter the <webview>'s initial settings.
      • additionalArguments String[] (optional) - A list of strings that will be appended to process.argv in the renderer process of this app. Useful for passing small bits of data down to renderer process preload scripts.
      • safeDialogs Boolean (optional) - Whether to enable browser style consecutive dialog protection. Default is false.
      • safeDialogsMessage String (optional) - The message to display when consecutive dialog protection is triggered. If not defined the default message would be used, note that currently the default message is in English and not localized.
      • disableDialogs Boolean (optional) - Whether to disable dialogs completely. Overrides safeDialogs. Default is false.
      • navigateOnDragDrop Boolean (optional) - Whether dragging and dropping a file or link onto the page causes a navigation. Default is false.
      • autoplayPolicy String (optional) - Autoplay policy to apply to content in the window, can be no-user-gesture-required, user-gesture-required, document-user-activation-required. Defaults to no-user-gesture-required.
      • disableHtmlFullscreenWindowResize Boolean (optional) - Whether to prevent the window from resizing when entering HTML Fullscreen. Default is false.
      • accessibleTitle String (optional) - An alternative title string provided only to accessibility tools such as screen readers. This string is not directly visible to users.
      • spellcheck Boolean (optional) - Whether to enable the builtin spellchecker. Default is true.
      • enableWebSQL Boolean (optional) - Whether to enable the WebSQL api. Default is true.
      • v8CacheOptions String (optional) - Enforces the v8 code caching policy used by blink. Accepted values are
        • none - Disables code caching
        • code - Heuristic based code caching
        • bypassHeatCheck - Bypass code caching heuristics but with lazy compilation
        • bypassHeatCheckAndEagerCompile - Same as above except compilation is eager. Default policy is code.

When setting minimum or maximum window size with minWidth/maxWidth/ minHeight/maxHeight, it only constrains the users. It won't prevent you from passing a size that does not follow size constraints to setBounds/setSize or to the constructor of BrowserWindow.

The possible values and behaviors of the type option are platform dependent. Possible values are:

  • On Linux, possible types are desktop, dock, toolbar, splash, notification.
  • On macOS, possible types are desktop, textured.
    • The textured type adds metal gradient appearance (NSTexturedBackgroundWindowMask).
    • The desktop type places the window at the desktop background window level (kCGDesktopWindowLevel - 1). Note that desktop window will not receive focus, keyboard or mouse events, but you can use globalShortcut to receive input sparingly.
  • On Windows, possible type is toolbar.

Instance Events

Objects created with new BrowserWindow emit the following events:

Note: Some events are only available on specific operating systems and are labeled as such.

Event: 'page-title-updated'

Returns:

  • event Event
  • title String
  • explicitSet Boolean

Emitted when the document changed its title, calling event.preventDefault() will prevent the native window's title from changing. explicitSet is false when title is synthesized from file URL.

Event: 'close'

Returns:

  • event Event

Emitted when the window is going to be closed. It's emitted before the beforeunload and unload event of the DOM. Calling event.preventDefault() will cancel the close.

Usually you would want to use the beforeunload handler to decide whether the window should be closed, which will also be called when the window is reloaded. In Electron, returning any value other than undefined would cancel the close. For example:

window.onbeforeunload = (e) => {
  console.log('I do not want to be closed')

  // Unlike usual browsers that a message box will be prompted to users, returning
  // a non-void value will silently cancel the close.
  // It is recommended to use the dialog API to let the user confirm closing the
  // application.
  e.returnValue = false // equivalent to `return false` but not recommended
}

Note: There is a subtle difference between the behaviors of window.onbeforeunload = handler and window.addEventListener('beforeunload', handler). It is recommended to always set the event.returnValue explicitly, instead of only returning a value, as the former works more consistently within Electron.

Event: 'closed'

Emitted when the window is closed. After you have received this event you should remove the reference to the window and avoid using it any more.

Event: 'session-end' Windows

Emitted when window session is going to end due to force shutdown or machine restart or session log off.

Event: 'unresponsive'

Emitted when the web page becomes unresponsive.

Event: 'responsive'

Emitted when the unresponsive web page becomes responsive again.

Event: 'blur'

Emitted when the window loses focus.

Event: 'focus'

Emitted when the window gains focus.

Event: 'show'

Emitted when the window is shown.

Event: 'hide'

Emitted when the window is hidden.

Event: 'ready-to-show'

Emitted when the web page has been rendered (while not being shown) and window can be displayed without a visual flash.

Please note that using this event implies that the renderer will be considered "visible" and paint even though show is false. This event will never fire if you use paintWhenInitiallyHidden: false

Event: 'maximize'

Emitted when window is maximized.

Event: 'unmaximize'

Emitted when the window exits from a maximized state.

Event: 'minimize'

Emitted when the window is minimized.

Event: 'restore'

Emitted when the window is restored from a minimized state.

Event: 'will-resize' macOS Windows

Returns:

  • event Event
  • newBounds Rectangle - Size the window is being resized to.

Emitted before the window is resized. Calling event.preventDefault() will prevent the window from being resized.

Note that this is only emitted when the window is being resized manually. Resizing the window with setBounds/setSize will not emit this event.

Event: 'resize'

Emitted after the window has been resized.

Event: 'resized' macOS Windows

Emitted once when the window has finished being resized.

This is usually emitted when the window has been resized manually. On macOS, resizing the window with setBounds/setSize and setting the animate parameter to true will also emit this event once resizing has finished.

Event: 'will-move' macOS Windows

Returns:

  • event Event
  • newBounds Rectangle - Location the window is being moved to.

Emitted before the window is moved. On Windows, calling event.preventDefault() will prevent the window from being moved.

Note that this is only emitted when the window is being resized manually. Resizing the window with setBounds/setSize will not emit this event.

Event: 'move'

Emitted when the window is being moved to a new position.

Event: 'moved' macOS Windows

Emitted once when the window is moved to a new position.

Note: On macOS this event is an alias of move.

Event: 'enter-full-screen'

Emitted when the window enters a full-screen state.

Event: 'leave-full-screen'

Emitted when the window leaves a full-screen state.

Event: 'enter-html-full-screen'

Emitted when the window enters a full-screen state triggered by HTML API.

Event: 'leave-html-full-screen'

Emitted when the window leaves a full-screen state triggered by HTML API.

Event: 'always-on-top-changed'

Returns:

  • event Event
  • isAlwaysOnTop Boolean

Emitted when the window is set or unset to show always on top of other windows.

Event: 'app-command' Windows Linux

Returns:

  • event Event
  • command String

Emitted when an App Command is invoked. These are typically related to keyboard media keys or browser commands, as well as the "Back" button built into some mice on Windows.

Commands are lowercased, underscores are replaced with hyphens, and the APPCOMMAND_ prefix is stripped off. e.g. APPCOMMAND_BROWSER_BACKWARD is emitted as browser-backward.

const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.on('app-command', (e, cmd) => {
  // Navigate the window back when the user hits their mouse back button
  if (cmd === 'browser-backward' && win.webContents.canGoBack()) {
    win.webContents.goBack()
  }
})

The following app commands are explicitly supported on Linux:

  • browser-backward
  • browser-forward

Event: 'scroll-touch-begin' macOS

Emitted when scroll wheel event phase has begun.

Event: 'scroll-touch-end' macOS

Emitted when scroll wheel event phase has ended.

Event: 'scroll-touch-edge' macOS

Emitted when scroll wheel event phase filed upon reaching the edge of element.

Event: 'swipe' macOS

Returns:

  • event Event
  • direction String

Emitted on 3-finger swipe. Possible directions are up, right, down, left.

The method underlying this event is built to handle older macOS-style trackpad swiping, where the content on the screen doesn't move with the swipe. Most macOS trackpads are not configured to allow this kind of swiping anymore, so in order for it to emit properly the 'Swipe between pages' preference in System Preferences > Trackpad > More Gestures must be set to 'Swipe with two or three fingers'.

Event: 'rotate-gesture' macOS

Returns:

  • event Event
  • rotation Float

Emitted on trackpad rotation gesture. Continually emitted until rotation gesture is ended. The rotation value on each emission is the angle in degrees rotated since the last emission. The last emitted event upon a rotation gesture will always be of value 0. Counter-clockwise rotation values are positive, while clockwise ones are negative.

Event: 'sheet-begin' macOS

Emitted when the window opens a sheet.

Event: 'sheet-end' macOS

Emitted when the window has closed a sheet.

Event: 'new-window-for-tab' macOS

Emitted when the native new tab button is clicked.

Event: 'system-context-menu' Windows

Returns:

  • event Event
  • point Point - The screen coordinates the context menu was triggered at

Emitted when the system context menu is triggered on the window, this is normally only triggered when the user right clicks on the non-client area of your window. This is the window titlebar or any area you have declared as -webkit-app-region: drag in a frameless window.

Calling event.preventDefault() will prevent the menu from being displayed.

Static Methods

The BrowserWindow class has the following static methods:

BrowserWindow.getAllWindows()

Returns BrowserWindow[] - An array of all opened browser windows.

BrowserWindow.getFocusedWindow()

Returns BrowserWindow | null - The window that is focused in this application, otherwise returns null.

BrowserWindow.fromWebContents(webContents)

Returns BrowserWindow | null - The window that owns the given webContents or null if the contents are not owned by a window.

BrowserWindow.fromBrowserView(browserView)

Returns BrowserWindow | null - The window that owns the given browserView. If the given view is not attached to any window, returns null.

BrowserWindow.fromId(id)

  • id Integer

Returns BrowserWindow | null - The window with the given id.

BrowserWindow.addExtension(path) Deprecated

  • path String

Adds Chrome extension located at path, and returns extension's name.

The method will also not return if the extension's manifest is missing or incomplete.

Note: This API cannot be called before the ready event of the app module is emitted.

Note: This method is deprecated. Instead, use ses.loadExtension(path).

BrowserWindow.removeExtension(name) Deprecated

  • name String

Remove a Chrome extension by name.

Note: This API cannot be called before the ready event of the app module is emitted.

Note: This method is deprecated. Instead, use ses.removeExtension(extension_id).

BrowserWindow.getExtensions() Deprecated

Returns Record<String, ExtensionInfo> - The keys are the extension names and each value is an Object containing name and version properties.

Note: This API cannot be called before the ready event of the app module is emitted.

Note: This method is deprecated. Instead, use ses.getAllExtensions().

BrowserWindow.addDevToolsExtension(path) Deprecated

  • path String

Adds DevTools extension located at path, and returns extension's name.

The extension will be remembered so you only need to call this API once, this API is not for programming use. If you try to add an extension that has already been loaded, this method will not return and instead log a warning to the console.

The method will also not return if the extension's manifest is missing or incomplete.

Note: This API cannot be called before the ready event of the app module is emitted.

Note: This method is deprecated. Instead, use ses.loadExtension(path).

BrowserWindow.removeDevToolsExtension(name) Deprecated

  • name String

Remove a DevTools extension by name.

Note: This API cannot be called before the ready event of the app module is emitted.

Note: This method is deprecated. Instead, use ses.removeExtension(extension_id).

BrowserWindow.getDevToolsExtensions() Deprecated

Returns Record<string, ExtensionInfo> - The keys are the extension names and each value is an Object containing name and version properties.

To check if a DevTools extension is installed you can run the following:

const { BrowserWindow } = require('electron')

const installed = 'devtron' in BrowserWindow.getDevToolsExtensions()
console.log(installed)

Note: This API cannot be called before the ready event of the app module is emitted.

Note: This method is deprecated. Instead, use ses.getAllExtensions().

Instance Properties

Objects created with new BrowserWindow have the following properties:

const { BrowserWindow } = require('electron')
// In this example `win` is our instance
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')

win.webContents Readonly

A WebContents object this window owns. All web page related events and operations will be done via it.

See the webContents documentation for its methods and events.

win.id Readonly

A Integer property representing the unique ID of the window. Each ID is unique among all BrowserWindow instances of the entire Electron application.

win.autoHideMenuBar

A Boolean property that determines whether the window menu bar should hide itself automatically. Once set, the menu bar will only show when users press the single Alt key.

If the menu bar is already visible, setting this property to true won't hide it immediately.

win.simpleFullScreen

A Boolean property that determines whether the window is in simple (pre-Lion) fullscreen mode.

win.fullScreen

A Boolean property that determines whether the window is in fullscreen mode.

win.visibleOnAllWorkspaces

A Boolean property that determines whether the window is visible on all workspaces.

Note: Always returns false on Windows.

win.shadow

A Boolean property that determines whether the window has a shadow.

win.menuBarVisible Windows Linux

A Boolean property that determines whether the menu bar should be visible.

Note: If the menu bar is auto-hide, users can still bring up the menu bar by pressing the single Alt key.

win.kiosk

A Boolean property that determines whether the window is in kiosk mode.

win.documentEdited macOS

A Boolean property that specifies whether the window’s document has been edited.

The icon in title bar will become gray when set to true.

win.representedFilename macOS

A String property that determines the pathname of the file the window represents, and the icon of the file will show in window's title bar.

win.title

A String property that determines the title of the native window.

Note: The title of the web page can be different from the title of the native window.

win.minimizable

A Boolean property that determines whether the window can be manually minimized by user.

On Linux the setter is a no-op, although the getter returns true.

win.maximizable

A Boolean property that determines whether the window can be manually maximized by user.

On Linux the setter is a no-op, although the getter returns true.

win.fullScreenable

A Boolean property that determines whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.

win.resizable

A Boolean property that determines whether the window can be manually resized by user.

win.closable

A Boolean property that determines whether the window can be manually closed by user.

On Linux the setter is a no-op, although the getter returns true.

win.movable

A Boolean property that determines Whether the window can be moved by user.

On Linux the setter is a no-op, although the getter returns true.

win.excludedFromShownWindowsMenu macOS

A Boolean property that determines whether the window is excluded from the application’s Windows menu. false by default.

const win = new BrowserWindow({ height: 600, width: 600 })

const template = [
  {
    role: 'windowmenu'
  }
]

win.excludedFromShownWindowsMenu = true

const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)

win.accessibleTitle

A String property that defines an alternative title provided only to accessibility tools such as screen readers. This string is not directly visible to users.

Instance Methods

Objects created with new BrowserWindow have the following instance methods:

Note: Some methods are only available on specific operating systems and are labeled as such.

win.destroy()

Force closing the window, the unload and beforeunload event won't be emitted for the web page, and close event will also not be emitted for this window, but it guarantees the closed event will be emitted.

win.close()

Try to close the window. This has the same effect as a user manually clicking the close button of the window. The web page may cancel the close though. See the close event.

win.focus()

Focuses on the window.

win.blur()

Removes focus from the window.

win.isFocused()

Returns Boolean - Whether the window is focused.

win.isDestroyed()

Returns Boolean - Whether the window is destroyed.

win.show()

Shows and gives focus to the window.

win.showInactive()

Shows the window but doesn't focus on it.

win.hide()

Hides the window.

win.isVisible()

Returns Boolean - Whether the window is visible to the user.

win.isModal()

Returns Boolean - Whether current window is a modal window.

win.maximize()

Maximizes the window. This will also show (but not focus) the window if it isn't being displayed already.

win.unmaximize()

Unmaximizes the window.

win.isMaximized()

Returns Boolean - Whether the window is maximized.

win.minimize()

Minimizes the window. On some platforms the minimized window will be shown in the Dock.

win.restore()

Restores the window from minimized state to its previous state.

win.isMinimized()

Returns Boolean - Whether the window is minimized.

win.setFullScreen(flag)

  • flag Boolean

Sets whether the window should be in fullscreen mode.

win.isFullScreen()

Returns Boolean - Whether the window is in fullscreen mode.

win.setSimpleFullScreen(flag) macOS

  • flag Boolean

Enters or leaves simple fullscreen mode.

Simple fullscreen mode emulates the native fullscreen behavior found in versions of macOS prior to Lion (10.7).

win.isSimpleFullScreen() macOS

Returns Boolean - Whether the window is in simple (pre-Lion) fullscreen mode.

win.isNormal()

Returns Boolean - Whether the window is in normal state (not maximized, not minimized, not in fullscreen mode).

win.setAspectRatio(aspectRatio[, extraSize]) macOS Linux

  • aspectRatio Float - The aspect ratio to maintain for some portion of the content view.
  • extraSize Size (optional) macOS - The extra size not to be included while maintaining the aspect ratio.

This will make a window maintain an aspect ratio. The extra size allows a developer to have space, specified in pixels, not included within the aspect ratio calculations. This API already takes into account the difference between a window's size and its content size.

Consider a normal window with an HD video player and associated controls. Perhaps there are 15 pixels of controls on the left edge, 25 pixels of controls on the right edge and 50 pixels of controls below the player. In order to maintain a 16:9 aspect ratio (standard aspect ratio for HD @1920x1080) within the player itself we would call this function with arguments of 16/9 and { width: 40, height: 50 }. The second argument doesn't care where the extra width and height are within the content view--only that they exist. Sum any extra width and height areas you have within the overall content view.

win.setBackgroundColor(backgroundColor)

  • backgroundColor String - Window's background color as a hexadecimal value, like #66CD00 or #FFF or #80FFFFFF (alpha is supported if transparent is true). Default is #FFF (white).

Sets the background color of the window. See Setting backgroundColor.

win.previewFile(path[, displayName]) macOS

  • path String - The absolute path to the file to preview with QuickLook. This is important as Quick Look uses the file name and file extension on the path to determine the content type of the file to open.
  • displayName String (optional) - The name of the file to display on the Quick Look modal view. This is purely visual and does not affect the content type of the file. Defaults to path.

Uses Quick Look to preview a file at a given path.

win.closeFilePreview() macOS

Closes the currently open Quick Look panel.

win.setBounds(bounds[, animate])

  • bounds Partial<Rectangle>
  • animate Boolean (optional) macOS

Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.

const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

// set all bounds properties
win.setBounds({ x: 440, y: 225, width: 800, height: 600 })

// set a single bounds property
win.setBounds({ width: 100 })

// { x: 440, y: 225, width: 100, height: 600 }
console.log(win.getBounds())

win.getBounds()

Returns Rectangle - The bounds of the window as Object.

win.getBackgroundColor()

Returns String - Gets the background color of the window. See Setting backgroundColor.

win.setContentBounds(bounds[, animate])

  • bounds Rectangle
  • animate Boolean (optional) macOS

Resizes and moves the window's client area (e.g. the web page) to the supplied bounds.

win.getContentBounds()

Returns Rectangle - The bounds of the window's client area as Object.

win.getNormalBounds()

Returns Rectangle - Contains the window bounds of the normal state

Note: whatever the current state of the window : maximized, minimized or in fullscreen, this function always returns the position and size of the window in normal state. In normal state, getBounds and getNormalBounds returns the same Rectangle.

win.setEnabled(enable)

  • enable Boolean

Disable or enable the window.

win.isEnabled()

Returns Boolean - whether the window is enabled.

win.setSize(width, height[, animate])

  • width Integer
  • height Integer
  • animate Boolean (optional) macOS

Resizes the window to width and height. If width or height are below any set minimum size constraints the window will snap to its minimum size.

win.getSize()

Returns Integer[] - Contains the window's width and height.

win.setContentSize(width, height[, animate])

  • width Integer
  • height Integer
  • animate Boolean (optional) macOS

Resizes the window's client area (e.g. the web page) to width and height.

win.getContentSize()

Returns Integer[] - Contains the window's client area's width and height.

win.setMinimumSize(width, height)

  • width Integer
  • height Integer

Sets the minimum size of window to width and height.

win.getMinimumSize()

Returns Integer[] - Contains the window's minimum width and height.

win.setMaximumSize(width, height)

  • width Integer
  • height Integer

Sets the maximum size of window to width and height.

win.getMaximumSize()

Returns Integer[] - Contains the window's maximum width and height.

win.setResizable(resizable)

  • resizable Boolean

Sets whether the window can be manually resized by the user.

win.isResizable()

Returns Boolean - Whether the window can be manually resized by the user.

win.setMovable(movable) macOS Windows

  • movable Boolean

Sets whether the window can be moved by user. On Linux does nothing.

win.isMovable() macOS Windows

Returns Boolean - Whether the window can be moved by user.

On Linux always returns true.

win.setMinimizable(minimizable) macOS Windows

  • minimizable Boolean

Sets whether the window can be manually minimized by user. On Linux does nothing.

win.isMinimizable() macOS Windows

Returns Boolean - Whether the window can be manually minimized by the user.

On Linux always returns true.

win.setMaximizable(maximizable) macOS Windows

  • maximizable Boolean

Sets whether the window can be manually maximized by user. On Linux does nothing.

win.isMaximizable() macOS Windows

Returns Boolean - Whether the window can be manually maximized by user.

On Linux always returns true.

win.setFullScreenable(fullscreenable)

  • fullscreenable Boolean

Sets whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.

win.isFullScreenable()

Returns Boolean - Whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.

win.setClosable(closable) macOS Windows

  • closable Boolean

Sets whether the window can be manually closed by user. On Linux does nothing.

win.isClosable() macOS Windows

Returns Boolean - Whether the window can be manually closed by user.

On Linux always returns true.

win.setAlwaysOnTop(flag[, level][, relativeLevel])

  • flag Boolean
  • level String (optional) macOS Windows - Values include normal, floating, torn-off-menu, modal-panel, main-menu, status, pop-up-menu, screen-saver, and dock (Deprecated). The default is floating when flag is true. The level is reset to normal when the flag is false. Note that from floating to status included, the window is placed below the Dock on macOS and below the taskbar on Windows. From pop-up-menu to a higher it is shown above the Dock on macOS and above the taskbar on Windows. See the macOS docs for more details.
  • relativeLevel Integer (optional) macOS - The number of layers higher to set this window relative to the given level. The default is 0. Note that Apple discourages setting levels higher than 1 above screen-saver.

Sets whether the window should show always on top of other windows. After setting this, the window is still a normal window, not a toolbox window which can not be focused on.

win.isAlwaysOnTop()

Returns Boolean - Whether the window is always on top of other windows.

win.moveAbove(mediaSourceId)

  • mediaSourceId String - Window id in the format of DesktopCapturerSource's id. For example "window:1869:0".

Moves window above the source window in the sense of z-order. If the mediaSourceId is not of type window or if the window does not exist then this method throws an error.

win.moveTop()

Moves window to top(z-order) regardless of focus

win.center()

Moves window to the center of the screen.

win.setPosition(x, y[, animate])

  • x Integer
  • y Integer
  • animate Boolean (optional) macOS

Moves window to x and y.

win.getPosition()

Returns Integer[] - Contains the window's current position.

win.setTitle(title)

  • title String

Changes the title of native window to title.

win.getTitle()

Returns String - The title of the native window.

Note: The title of the web page can be different from the title of the native window.

win.setSheetOffset(offsetY[, offsetX]) macOS

  • offsetY Float
  • offsetX Float (optional)

Changes the attachment point for sheets on macOS. By default, sheets are attached just below the window frame, but you may want to display them beneath a HTML-rendered toolbar. For example:

const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

const toolbarRect = document.getElementById('toolbar').getBoundingClientRect()
win.setSheetOffset(toolbarRect.height)

win.flashFrame(flag)

  • flag Boolean

Starts or stops flashing the window to attract user's attention.

win.setSkipTaskbar(skip)

  • skip Boolean

Makes the window not show in the taskbar.

win.setKiosk(flag)

  • flag Boolean

Enters or leaves kiosk mode.

win.isKiosk()

Returns Boolean - Whether the window is in kiosk mode.

win.getMediaSourceId()

Returns String - Window id in the format of DesktopCapturerSource's id. For example "window🔢0".

More precisely the format is window:id:other_id where id is HWND on Windows, CGWindowID (uint64_t) on macOS and Window (unsigned long) on Linux. other_id is used to identify web contents (tabs) so within the same top level window.

win.getNativeWindowHandle()

Returns Buffer - The platform-specific handle of the window.

The native type of the handle is HWND on Windows, NSView* on macOS, and Window (unsigned long) on Linux.

win.hookWindowMessage(message, callback) Windows

  • message Integer
  • callback Function

Hooks a windows message. The callback is called when the message is received in the WndProc.

win.isWindowMessageHooked(message) Windows

  • message Integer

Returns Boolean - true or false depending on whether the message is hooked.

win.unhookWindowMessage(message) Windows

  • message Integer

Unhook the window message.

win.unhookAllWindowMessages() Windows

Unhooks all of the window messages.

win.setRepresentedFilename(filename) macOS

  • filename String

Sets the pathname of the file the window represents, and the icon of the file will show in window's title bar.

win.getRepresentedFilename() macOS

Returns String - The pathname of the file the window represents.

win.setDocumentEdited(edited) macOS

  • edited Boolean

Specifies whether the window’s document has been edited, and the icon in title bar will become gray when set to true.

win.isDocumentEdited() macOS

Returns Boolean - Whether the window's document has been edited.

win.focusOnWebView()

win.blurWebView()

win.capturePage([rect])

  • rect Rectangle (optional) - The bounds to capture

Returns Promise<NativeImage> - Resolves with a NativeImage

Captures a snapshot of the page within rect. Omitting rect will capture the whole visible page.

win.loadURL(url[, options])

  • url String
  • options Object (optional)
    • httpReferrer (String | Referrer) (optional) - An HTTP Referrer URL.
    • userAgent String (optional) - A user agent originating the request.
    • extraHeaders String (optional) - Extra headers separated by "\n"
    • postData (UploadRawData[] | UploadFile[] | UploadBlob[]) (optional)
    • baseURLForDataURL String (optional) - Base URL (with trailing path separator) for files to be loaded by the data URL. This is needed only if the specified url is a data URL and needs to load other files.

Returns Promise<void> - the promise will resolve when the page has finished loading (see did-finish-load), and rejects if the page fails to load (see did-fail-load).

Same as webContents.loadURL(url[, options]).

The url can be a remote address (e.g. http://) or a path to a local HTML file using the file:// protocol.

To ensure that file URLs are properly formatted, it is recommended to use Node's url.format method:

const url = require('url').format({
  protocol: 'file',
  slashes: true,
  pathname: require('path').join(__dirname, 'index.html')
})

win.loadURL(url)

You can load a URL using a POST request with URL-encoded data by doing the following:

win.loadURL('http://localhost:8000/post', {
  postData: [{
    type: 'rawData',
    bytes: Buffer.from('hello=world')
  }],
  extraHeaders: 'Content-Type: application/x-www-form-urlencoded'
})

win.loadFile(filePath[, options])

  • filePath String
  • options Object (optional)
    • query Record<String, String> (optional) - Passed to url.format().
    • search String (optional) - Passed to url.format().
    • hash String (optional) - Passed to url.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.setMenu(menu) Linux Windows

  • menu Menu | null

Sets the menu as the window's menu bar.

win.removeMenu() Linux Windows

Remove the window's menu bar.

win.setProgressBar(progress[, options])

  • progress Double
  • options Object (optional)
    • mode String Windows - Mode for the progress bar. Can be none, normal, indeterminate, error or paused.

Sets progress value in progress bar. Valid range is [0, 1.0].

Remove progress bar when progress < 0; Change to indeterminate mode when progress > 1.

On Linux platform, only supports Unity desktop environment, you need to specify the *.desktop file name to desktopName field in package.json. By default, it will assume {app.name}.desktop.

On Windows, a mode can be passed. Accepted values are none, normal, indeterminate, error, and paused. If you call setProgressBar without a mode set (but with a value within the valid range), normal will be assumed.

win.setOverlayIcon(overlay, description) Windows

  • overlay NativeImage | null - the icon to display on the bottom right corner of the taskbar icon. If this parameter is null, the overlay is cleared
  • description String - a description that will be provided to Accessibility screen readers

Sets a 16 x 16 pixel overlay onto the current taskbar icon, usually used to convey some sort of application status or to passively notify the user.

win.setHasShadow(hasShadow)

  • hasShadow Boolean

Sets whether the window should have a shadow.

win.hasShadow()

Returns Boolean - Whether the window has a shadow.

win.setOpacity(opacity) Windows macOS

  • opacity Number - between 0.0 (fully transparent) and 1.0 (fully opaque)

Sets the opacity of the window. On Linux, does nothing. Out of bound number values are clamped to the [0, 1] range.

win.getOpacity()

Returns Number - between 0.0 (fully transparent) and 1.0 (fully opaque). On Linux, always returns 1.

win.setShape(rects) Windows Linux Experimental

  • rects Rectangle[] - Sets a shape on the window. Passing an empty list reverts the window to being rectangular.

Setting a window shape determines the area within the window where the system permits drawing and user interaction. Outside of the given region, no pixels will be drawn and no mouse events will be registered. Mouse events outside of the region will not be received by that window, but will fall through to whatever is behind the window.

win.setThumbarButtons(buttons) Windows

Returns Boolean - Whether the buttons were added successfully

Add a thumbnail toolbar with a specified set of buttons to the thumbnail image of a window in a taskbar button layout. Returns a Boolean object indicates whether the thumbnail has been added successfully.

The number of buttons in thumbnail toolbar should be no greater than 7 due to the limited room. Once you setup the thumbnail toolbar, the toolbar cannot be removed due to the platform's limitation. But you can call the API with an empty array to clean the buttons.

The buttons is an array of Button objects:

  • Button Object
    • icon NativeImage - The icon showing in thumbnail toolbar.
    • click Function
    • tooltip String (optional) - The text of the button's tooltip.
    • flags String[] (optional) - Control specific states and behaviors of the button. By default, it is ['enabled'].

The flags is an array that can include following 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

Sets the region of the window to show as the thumbnail image displayed when hovering over the window in the taskbar. You can reset the thumbnail to be the entire window by specifying an empty region: { x: 0, y: 0, width: 0, height: 0 }.

win.setThumbnailToolTip(toolTip) Windows

  • toolTip String

Sets the toolTip that is displayed when hovering over the window thumbnail in the taskbar.

win.setAppDetails(options) Windows

  • options Object
    • appId String (optional) - Window's App User Model ID. It has to be set, otherwise the other options will have no effect.
    • appIconPath String (optional) - Window's Relaunch Icon.
    • appIconIndex Integer (optional) - Index of the icon in appIconPath. Ignored when appIconPath is not set. Default is 0.
    • relaunchCommand String (optional) - Window's Relaunch Command.
    • relaunchDisplayName String (optional) - Window's Relaunch Display Name.

Sets the properties for the window's taskbar button.

Note: relaunchCommand and relaunchDisplayName must always be set together. If one of those properties is not set, then neither will be used.

win.showDefinitionForSelection() macOS

Same as webContents.showDefinitionForSelection().

win.setIcon(icon) Windows Linux

Changes window icon.

win.setWindowButtonVisibility(visible) macOS

  • visible Boolean

Sets whether the window traffic light buttons should be visible.

This cannot be called when titleBarStyle is set to customButtonsOnHover.

win.setAutoHideMenuBar(hide)

  • hide Boolean

Sets whether the window menu bar should hide itself automatically. Once set the menu bar will only show when users press the single Alt key.

If the menu bar is already visible, calling setAutoHideMenuBar(true) won't hide it immediately.

win.isMenuBarAutoHide()

Returns Boolean - Whether menu bar automatically hides itself.

win.setMenuBarVisibility(visible) Windows Linux

  • visible Boolean

Sets whether the menu bar should be visible. If the menu bar is auto-hide, users can still bring up the menu bar by pressing the single Alt key.

win.isMenuBarVisible()

Returns Boolean - Whether the menu bar is visible.

win.setVisibleOnAllWorkspaces(visible[, options])

  • visible Boolean
  • options Object (optional)
    • visibleOnFullScreen Boolean (optional) macOS - Sets whether the window should be visible above fullscreen windows

Sets whether the window should be visible on all workspaces.

Note: This API does nothing on Windows.

win.isVisibleOnAllWorkspaces()

Returns Boolean - Whether the window is visible on all workspaces.

Note: This API always returns false on Windows.

win.setIgnoreMouseEvents(ignore[, options])

  • ignore Boolean
  • options Object (optional)
    • forward Boolean (optional) macOS Windows - If true, forwards mouse move messages to Chromium, enabling mouse related events such as mouseleave. Only used when ignore is true. If ignore is false, forwarding is always disabled regardless of this value.

Makes the window ignore all mouse events.

All mouse events happened in this window will be passed to the window below this window, but if this window has focus, it will still receive keyboard events.

win.setContentProtection(enable) macOS Windows

  • enable Boolean

Prevents the window contents from being captured by other apps.

On macOS it sets the NSWindow's sharingType to NSWindowSharingNone. On Windows it calls SetWindowDisplayAffinity with WDA_MONITOR.

win.setFocusable(focusable) macOS Windows

  • focusable Boolean

Changes whether the window can be focused.

On macOS it does not remove the focus from the window.

win.setParentWindow(parent)

  • parent BrowserWindow | null

Sets parent as current window's parent window, passing null will turn current window into a top-level window.

win.getParentWindow()

Returns BrowserWindow - The parent window.

win.getChildWindows()

Returns BrowserWindow[] - All child windows.

win.setAutoHideCursor(autoHide) macOS

  • autoHide Boolean

Controls whether to hide cursor when typing.

win.selectPreviousTab() macOS

Selects the previous tab when native tabs are enabled and there are other tabs in the window.

win.selectNextTab() macOS

Selects the next tab when native tabs are enabled and there are other tabs in the window.

win.mergeAllWindows() macOS

Merges all windows into one window with multiple tabs when native tabs are enabled and there is more than one open window.

win.moveTabToNewWindow() macOS

Moves the current tab into a new window if native tabs are enabled and there is more than one tab in the current window.

win.toggleTabBar() macOS

Toggles the visibility of the tab bar if native tabs are enabled and there is only one tab in the current window.

win.addTabbedWindow(browserWindow) macOS

  • browserWindow BrowserWindow

Adds a window as a tab on this window, after the tab for the window instance.

win.setVibrancy(type) macOS

  • type String | null - Can be appearance-based, light, dark, titlebar, selection, menu, popover, sidebar, medium-light, ultra-dark, header, sheet, window, hud, fullscreen-ui, tooltip, content, under-window, or under-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

Set a custom position for the traffic light buttons. Can only be used with titleBarStyle set to hidden.

win.getTrafficLightPosition() macOS

Returns Point - The current position for the traffic light buttons. Can only be used with titleBarStyle set to hidden.

win.setTouchBar(touchBar) macOS

  • touchBar TouchBar | null

Sets the touchBar layout for the current window. Specifying null or undefined clears the touch bar. This method only has an effect if the machine has a touch bar and is running on macOS 10.12.1+.

Note: The TouchBar API is currently experimental and may change or be removed in future Electron releases.

win.setBrowserView(browserView) Experimental

  • browserView BrowserView | null - Attach browserView to win. If there are other BrowserViews 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

Replacement API for setBrowserView supporting work with multi browser views.

win.removeBrowserView(browserView) Experimental

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.eval(code)

  • code String

Evaluates the code in the child window.

win.focus()

Focuses the child window (brings the window to front).

win.print()

Invokes the print dialog on the child window.

win.postMessage(message, targetOrigin)

  • message any
  • targetOrigin String

Sends a message to the child window with the specified origin or * for no origin preference.

In addition to these methods, the child window implements window.opener object with no properties and a single method.

Instance Properties

The BrowserWindowProxy object has the following instance properties:

win.closed

A Boolean that is set to true after the child window gets closed.

Build Instructions

Follow the guidelines below for building Electron.

Platform prerequisites

Check the build prerequisites for your platform before proceeding

Build Tools

Electron's Build Tools automate much of the setup for compiling Electron from source with different configurations and build targets. If you wish to set up the environment manually, the instructions are listed below.

GN prerequisites

You'll need to install depot_tools, the toolset used for fetching Chromium and its dependencies.

Also, on Windows, you'll need to set the environment variable DEPOT_TOOLS_WIN_TOOLCHAIN=0. To do so, open Control PanelSystem and SecuritySystemAdvanced 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 like https://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

Troubleshooting

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 PanelSystem and SecuritySystemAdvanced system settings and add a system variable DEPOT_TOOLS_WIN_TOOLCHAIN with value 0. This tells depot_tools to use your locally installed version of Visual Studio (by default, depot_tools will try to download a Google-internal version that only Googlers have access to).

Build Instructions (Linux)

Follow the guidelines below for building Electron on Linux.

Prerequisites

  • At least 25GB disk space and 8GB RAM.

  • Python 2.7.x. Some distributions like CentOS 6.x still use Python 2.6.x so you may need to check your Python version with python -V.

    Please also ensure that your system and Python version support at least TLS 1.2. For a quick test, run the following script:

    $ npx @electron/check-python-tls
    

    If the script returns that your configuration is using an outdated security protocol, use your system's package manager to update Python to the latest version in the 2.7.x branch. Alternatively, visit https://www.python.org/downloads/ for detailed instructions.

  • Node.js. There are various ways to install Node. You can download source code from nodejs.org and compile it. Doing so permits installing Node on your own home directory as a standard user. Or try repositories such as NodeSource.

  • clang 3.4 or later.

  • Development headers of GTK 3 and libnotify.

On Ubuntu, install the following libraries:

$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \
                       libnotify-dev libgnome-keyring-dev \
                       libasound2-dev libcap-dev libcups2-dev libxtst-dev \
                       libxss1 libnss3-dev gcc-multilib g++-multilib curl \
                       gperf bison python-dbusmock openjdk-8-jre

On RHEL / CentOS, install the following libraries:

$ sudo yum install clang dbus-devel gtk3-devel libnotify-devel \
                   libgnome-keyring-devel xorg-x11-server-utils libcap-devel \
                   cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \
                   nss-devel python-dbusmock openjdk-8-jre

On Fedora, install the following libraries:

$ sudo dnf install clang dbus-devel gtk3-devel libnotify-devel \
                   libgnome-keyring-devel xorg-x11-server-utils libcap-devel \
                   cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \
                   nss-devel python-dbusmock openjdk-8-jre

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"'

Building

See Build Instructions: GN

Troubleshooting

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.

Prerequisites

  • macOS >= 10.11.6
  • Xcode >= 9.0.0
  • node.js (external)
  • Python 2.7 with support for TLS 1.2

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 [email protected] && brew link [email protected] --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.

Building Electron

See Build Instructions: GN.

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, replacing 2019 and Community with your installed versions and replacing DRIVE: with the drive that Visual Studio is on. Often, this will be C:.
      • WINDOWSSDKDIR = DRIVE:\path\to\Windows Kits\10, replacing DRIVE: with the drive that Windows Kits is on. Often, this will be C:.
    • Python for Windows (pywin32) Extensions is also needed in order to run the build process.
  • Node.js
  • Git
  • Debugging Tools for Windows of Windows SDK 10.0.15063.468 if you plan on creating a full distribution since symstore.exe is used for creating a symbol store from .pdb files.
    • Different versions of the SDK can be installed side by side. To install the SDK, open Visual Studio Installer, select ChangeIndividual 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 PanelProgramsPrograms and Features → Select the "Windows Software Development Kit" → ChangeChange → Check "Debugging Tools For Windows" → Change. Or, you can download the standalone SDK installer and use it to install the Debugging Tools.

If you don't currently have a Windows installation, dev.microsoftedge.com has timebombed versions of Windows that you can use to build Electron.

Building Electron is done entirely with command-line scripts and cannot be done with Visual Studio. You can develop Electron with any editor but support for building with Visual Studio will come in the future.

Note: Even though Visual Studio is not used for building, it's still required because we need the build toolchains it provides.

Exclude source tree from Windows Security

Windows Security doesn't like one of the files in the Chromium source code (see https://crbug.com/441184), so it will constantly delete it, causing gclient sync issues. You can exclude the source tree from being monitored by Windows Security by following these instructions.

Building

See Build Instructions: GN

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

Troubleshooting

Command xxxx not found

If you encountered an error like Command xxxx not found, you may try to use the VS2015 Command Prompt console to execute the build scripts.

Fatal internal compiler error: C1001

Make sure you have the latest Visual Studio update installed.

LNK1181: cannot open input file 'kernel32.lib'

Try reinstalling 32bit Node.js.

Error: ENOENT, stat 'C:\Users\USERNAME\AppData\Roaming\npm'

Creating that directory should fix the problem:

$ mkdir ~\AppData\Roaming\npm

node-gyp is not recognized as an internal or external command

You may get this error if you are using Git Bash for building, you should use PowerShell or VS2015 Command Prompt instead.

cannot create directory at '...': Filename too long

node.js has some extremely long pathnames, and by default git on windows doesn't handle long pathnames correctly (even though windows supports them). This should fix it:

$ git config --system core.longpaths true

error: use of undeclared identifier 'DefaultDelegateCheckMode'

This can happen during build, when Debugging Tools for Windows has been installed with Windows Driver Kit. Uninstall Windows Driver Kit and install Debugging Tools with steps described above.

ImportError: No module named win32file

Make sure you have installed pywin32 with pip install pywin32.

Build Scripts Hang Until Keypress

This bug is a "feature" of Windows' command prompt. It happens when clicking inside the prompt window with QuickEdit enabled and is intended to allow selecting and copying output text easily. Since each accidental click will pause the build process, you might want to disable this feature in the command prompt properties.

Build System Overview

Electron uses GN for project generation and ninja for building. Project configurations can be found in the .gn and .gni files.

GN Files

The following gn files contain the main rules for building Electron:

  • BUILD.gn defines how Electron itself is built and includes the default configurations for linking with Chromium.
  • build/args/{debug,release,all}.gn contain the default build arguments for building Electron.

Component Build

Since Chromium is quite a large project, the final linking stage can take quite a few minutes, which makes it hard for development. In order to solve this, Chromium introduced the "component build", which builds each component as a separate shared library, making linking very quick but sacrificing file size and performance.

Electron inherits this build option from Chromium. In Debug builds, the binary will be linked to a shared library version of Chromium's components to achieve fast linking time; for Release builds, the binary will be linked to the static library versions, so we can have the best possible binary size and performance.

Tests

NB this section is out of date and contains information that is no longer relevant to the GN-built electron.

Test your changes conform to the project coding style using:

$ npm run lint

Test functionality using:

$ npm test

Whenever you make changes to Electron source code, you'll need to re-run the build before the tests:

$ npm run build && npm test

You can make the test suite run faster by isolating the specific test or block you're currently working on using Mocha's exclusive tests feature. Append .only to any describe or it function call:

describe.only('some feature', () => {
  // ... only tests in this block will be run
})

Alternatively, you can use mocha's grep option to only run tests matching the given regular expression pattern:

$ npm test -- --grep child_process

Tests that include native modules (e.g. runas) can't be executed with the debug build (see #2558 for details), but they will work with the release build.

To run the tests with the release build use:

$ npm test -- -R

Certificate Object

  • data String - PEM encoded data
  • issuer CertificatePrincipal - Issuer principal
  • issuerName String - Issuer's Common Name
  • issuerCert Certificate - Issuer certificate (if not self-signed)
  • subject CertificatePrincipal - Subject principal
  • subjectName String - Subject's Common Name
  • serialNumber String - Hex value represented string
  • validStart Number - Start date of the certificate being valid in seconds
  • validExpiry Number - End date of the certificate being valid in seconds
  • fingerprint String - Fingerprint of the certificate

CertificatePrincipal Object

  • commonName String - Common Name.
  • organizations String[] - Organization names.
  • organizationUnits String[] - Organization Unit names.
  • locality String - Locality.
  • state String - State or province.
  • country String - Country or region.

Chromium Development

A collection of resources for learning about Chromium and tracking its development

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:

  1. Make codes changes in Electron repository.
  2. Run git add your_changed_file.cc.
  3. Run git-clang-format, and you will probably see modifications in your_changed_file.cc, these modifications are generated from clang-format.
  4. Run git add your_changed_file.cc, and commit your change.
  5. Now the branch is ready to be opened as a pull request.

If you want to format the changed code on your latest git commit (HEAD), you can run git-clang-format HEAD~1. See git-clang-format -h for more details.

Editor Integration

You can also integrate clang-format directly into your favorite editors. For further guidance on setting up editor integration, see these pages:

Using clang-tidy on C++ Code

clang-tidy is a tool to automatically check C/C++/Objective-C code for style violations, programming errors, and best practices.

Electron's clang-tidy integration is provided as a linter script which can be run with npm run lint:clang-tidy. While clang-tidy checks your on-disk files, you need to have built Electron so that it knows which compiler flags were used. There is one required option for the script --output-dir, which tells the script which build directory to pull the compilation information from. A typical usage would be: npm run lint:clang-tiy --out-dir ../out/Testing

With no filenames provided, all C/C++/Objective-C files will be checked. You can provide a list of files to be checked by passing the filenames after the options: npm run lint:clang-tiy --out-dir ../out/Testing shell/browser/api/electron_api_app.cc

While clang-tidy has a long list of possible checks, in Electron only a few are enabled by default. At the moment Electron doesn't have a .clang-tidy config, so clang-tidy will find the one from Chromium at src/.clang-tidy and use the checks which Chromium has enabled. You can change which checks are run by using the --checks= option. This is passed straight through to clang-tidy, so see its documentation for full details. Wildcards can be used, and checks can be disabled by prefixing a -. By default any checks listed are added to those in .clang-tidy, so if you'd like to limit the checks to specific ones you should first exclude all checks then add back what you want, like --checks=-*,performance*.

Running clang-tidy is rather slow - internally it compiles each file and then runs the checks so it will always be some factor slower than compilation. While you can use parallel runs to speed it up using the --jobs|-j option, clang-tidy also uses a lot of memory during its checks, so it can easily run into out-of-memory errors. As such the default number of jobs is one.

Class: ClientRequest

Make HTTP/HTTPS requests.

Process: Main

ClientRequest implements the Writable Stream interface and is therefore an EventEmitter.

new ClientRequest(options)

  • options (Object | String) - If options is a String, it is interpreted as the request URL. If it is an object, it is expected to fully specify an HTTP request via the following properties:
    • method String (optional) - The HTTP request method. Defaults to the GET method.
    • url String (optional) - The request URL. Must be provided in the absolute form with the protocol scheme specified as http or https.
    • session Session (optional) - The Session instance with which the request is associated.
    • partition String (optional) - The name of the partition with which the request is associated. Defaults to the empty string. The session option prevails on partition. Thus if a session is explicitly specified, partition is ignored.
    • useSessionCookies Boolean (optional) - Whether to send cookies with this request from the provided session. This will make the net request's cookie behavior match a fetch request. Default is false.
    • protocol String (optional) - The protocol scheme in the form 'scheme:'. Currently supported values are 'http:' or 'https:'. Defaults to 'http:'.
    • host String (optional) - The server host provided as a concatenation of the hostname and the port number 'hostname:port'.
    • hostname String (optional) - The server host name.
    • port Integer (optional) - The server's listening port number.
    • path String (optional) - The path part of the request URL.
    • redirect String (optional) - The redirect mode for this request. Should be one of follow, error or manual. Defaults to follow. When mode is error, any redirection will be aborted. When mode is manual the redirection will be cancelled unless request.followRedirect is invoked synchronously during the redirect event.

options properties such as protocol, host, hostname, port and path strictly follow the Node.js model as described in the URL module.

For instance, we could have created the same request to 'github.com' as follows:

const request = net.request({
  method: 'GET',
  protocol: 'https:',
  hostname: 'github.com',
  port: 443,
  path: '/'
})

Instance Events

Event: 'response'

Returns:

  • response IncomingMessage - An object representing the HTTP response message.

Event: 'login'

Returns:

  • authInfo Object
    • isProxy Boolean
    • scheme String
    • host String
    • port Integer
    • realm String
  • callback Function
    • username String (optional)
    • password String (optional)

Emitted when an authenticating proxy is asking for user credentials.

The callback function is expected to be called back with user credentials:

  • username String
  • password String
request.on('login', (authInfo, callback) => {
  callback('username', 'password')
})

Providing empty credentials will cancel the request and report an authentication error on the response object:

request.on('response', (response) => {
  console.log(`STATUS: ${response.statusCode}`);
  response.on('error', (error) => {
    console.log(`ERROR: ${JSON.stringify(error)}`)
  })
})
request.on('login', (authInfo, callback) => {
  callback()
})

Event: 'finish'

Emitted just after the last chunk of the request's data has been written into the request object.

Event: 'abort'

Emitted when the request is aborted. The abort event will not be fired if the request is already closed.

Event: 'error'

Returns:

  • error Error - an error object providing some information about the failure.

Emitted when the net module fails to issue a network request. Typically when the request object emits an error event, a close event will subsequently follow and no response object will be provided.

Event: 'close'

Emitted as the last event in the HTTP request-response transaction. The close event indicates that no more events will be emitted on either the request or response objects.

Event: 'redirect'

Returns:

  • statusCode Integer
  • method String
  • redirectUrl String
  • responseHeaders Record<String, String[]>

Emitted when the server returns a redirect response (e.g. 301 Moved Permanently). Calling request.followRedirect will continue with the redirection. If this event is handled, request.followRedirect must be called synchronously, otherwise the request will be cancelled.

Instance Properties

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.

Instance Methods

request.setHeader(name, value)

  • name String - An extra HTTP header name.
  • value String - An extra HTTP header value.

Adds an extra HTTP header. The header name will be issued as-is without lowercasing. It can be called only before first write. Calling this method after the first write will throw an error. If the passed value is not a String, its toString() method will be called to obtain the final value.

Certain headers are restricted from being set by apps. These headers are listed below. More information on restricted headers can be found in Chromium's header utils.

  • Content-Length
  • Host
  • Trailer or Te
  • Upgrade
  • Cookie2
  • Keep-Alive
  • Transfer-Encoding

Additionally, setting the Connection header to the value upgrade is also disallowed.

request.getHeader(name)

  • name String - Specify an extra header name.

Returns String - The value of a previously set extra header name.

request.removeHeader(name)

  • name String - Specify an extra header name.

Removes a previously set extra header name. This method can be called only before first write. Trying to call it after the first write will throw an error.

request.write(chunk[, encoding][, callback])

  • chunk (String | Buffer) - A chunk of the request body's data. If it is a string, it is converted into a Buffer using the specified encoding.
  • encoding String (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'.
  • callback Function (optional) - Called after the write operation ends.

callback is essentially a dummy function introduced in the purpose of keeping similarity with the Node.js API. It is called asynchronously in the next tick after chunk content have been delivered to the Chromium networking layer. Contrary to the Node.js implementation, it is not guaranteed that chunk content have been flushed on the wire before callback is called.

Adds a chunk of data to the request body. The first write operation may cause the request headers to be issued on the wire. After the first write operation, it is not allowed to add or remove a custom header.

request.end([chunk][, encoding][, callback])

  • chunk (String | Buffer) (optional)
  • encoding String (optional)
  • callback Function (optional)

Sends the last chunk of the request data. Subsequent write or end operations will not be allowed. The finish event is emitted just after the end operation.

request.abort()

Cancels an ongoing HTTP transaction. If the request has already emitted the close event, the abort operation will have no effect. Otherwise an ongoing event will emit abort and close events. Additionally, if there is an ongoing response object,it will emit the aborted event.

request.followRedirect()

Continues any pending redirection. Can only be called during a 'redirect' event.

request.getUploadProgress()

Returns Object:

  • active Boolean - Whether the request is currently active. If this is false no other properties will be set
  • started Boolean - Whether the upload has started. If this is false both current and total will be set to 0.
  • current Integer - The number of bytes that have been uploaded so far
  • total Integer - The number of bytes that will be uploaded this request

You can use this method in conjunction with POST requests to get the progress of a file upload or other data transfer.

clipboard

Perform copy and paste operations on the system clipboard.

Process: Main, Renderer

On Linux, there is also a selection clipboard. To manipulate it you need to pass selection to each method:

const { clipboard } = require('electron')

clipboard.writeText('Example String', 'selection')
console.log(clipboard.readText('selection'))

Methods

The clipboard module has the following methods:

Note: Experimental APIs are marked as such and could be removed in future.

clipboard.readText([type])

  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Returns String - The content in the clipboard as plain text.

const { clipboard } = require('electron')

clipboard.writeText('hello i am a bit of text!')

const text = clipboard.readText()
console.log(text)
// hello i am a bit of text!'

clipboard.writeText(text[, type])

  • text String
  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Writes the text into the clipboard as plain text.

const { clipboard } = require('electron')

const text = 'hello i am a bit of text!'
clipboard.writeText(text)

clipboard.readHTML([type])

  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Returns String - The content in the clipboard as markup.

const { clipboard } = require('electron')

clipboard.writeHTML('<b>Hi</b>')
const html = clipboard.readHTML()

console.log(html)
// <meta charset='utf-8'><b>Hi</b>

clipboard.writeHTML(markup[, type])

  • markup String
  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Writes markup to the clipboard.

const { clipboard } = require('electron')

clipboard.writeHTML('<b>Hi</b')

clipboard.readImage([type])

  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Returns NativeImage - The image content in the clipboard.

clipboard.writeImage(image[, type])

  • image NativeImage
  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Writes image to the clipboard.

clipboard.readRTF([type])

  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Returns String - The content in the clipboard as RTF.

const { clipboard } = require('electron')

clipboard.writeRTF('{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}')

const rtf = clipboard.readRTF()
console.log(rtf)
// {\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}

clipboard.writeRTF(text[, type])

  • text String
  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Writes the text into the clipboard in RTF.

const { clipboard } = require('electron')

const rtf = '{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}'
clipboard.writeRTF(rtf)

clipboard.readBookmark() macOS Windows

Returns Object:

  • title String
  • url String

Returns an Object containing title and url keys representing the bookmark in the clipboard. The title and url values will be empty strings when the bookmark is unavailable.

clipboard.writeBookmark(title, url[, type]) macOS Windows

  • title String
  • url String
  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Writes the title and url into the clipboard as a bookmark.

Note: Most apps on Windows don't support pasting bookmarks into them so you can use clipboard.write to write both a bookmark and fallback text to the clipboard.

const { clipboard } = require('electron')

clipboard.writeBookmark({
  text: 'https://electronjs.org',
  bookmark: 'Electron Homepage'
})

clipboard.readFindText() macOS

Returns String - The text on the find pasteboard, which is the pasteboard that holds information about the current state of the active application’s find panel.

This method uses synchronous IPC when called from the renderer process. The cached value is reread from the find pasteboard whenever the application is activated.

clipboard.writeFindText(text) macOS

  • text String

Writes the text into the find pasteboard (the pasteboard that holds information about the current state of the active application’s find panel) as plain text. This method uses synchronous IPC when called from the renderer process.

clipboard.clear([type])

  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Clears the clipboard content.

clipboard.availableFormats([type])

  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Returns String[] - An array of supported formats for the clipboard type.

const { clipboard } = require('electron')

const formats = clipboard.availableFormats()
console.log(formats)
// [ 'text/plain', 'text/html' ]

clipboard.has(format[, type]) Experimental

  • format String
  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Returns Boolean - Whether the clipboard supports the specified format.

const { clipboard } = require('electron')

const hasFormat = clipboard.has('<p>selection</p>')
console.log(hasFormat)
// 'true' or 'false

clipboard.read(format) Experimental

  • format String

Returns String - Reads format type from the clipboard.

clipboard.readBuffer(format) Experimental

  • format String

Returns Buffer - Reads format type from the clipboard.

const { clipboard } = require('electron')

const buffer = Buffer.from('this is binary', 'utf8')
clipboard.writeBuffer('public.utf8-plain-text', buffer)

const ret = clipboard.readBuffer('public.utf8-plain-text')

console.log(buffer.equals(out))
// true

clipboard.writeBuffer(format, buffer[, type]) Experimental

  • format String
  • buffer Buffer
  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Writes the buffer into the clipboard as format.

const { clipboard } = require('electron')

const buffer = Buffer.from('writeBuffer', 'utf8')
clipboard.writeBuffer('public.utf8-plain-text', buffer)

clipboard.write(data[, type])

  • data Object
    • text String (optional)
    • html String (optional)
    • image NativeImage (optional)
    • rtf String (optional)
    • bookmark String (optional) - The title of the URL at text.
  • type String (optional) - Can be selection or clipboard; default is 'clipboard'. selection is only available on Linux.

Writes data to the clipboard.

const { clipboard } = require('electron')

clipboard.write({
  text: 'test',
  html: '<b>Hi</b>',
  rtf: '{\\rtf1\\utf8 text}',
  bookmark: 'a title'
})

console.log(clipboard.readText())
// 'test'

console.log(clipboard.readHTML())
// <meta charset='utf-8'><b>Hi</b>

console.log(clipboard.readRTF())
// '{\\rtf1\\utf8 text}'

console.log(clipboard.readBookmark())
// { title: 'a title', url: 'test' }

Code Signing

Code signing is a security technology that you use to certify that an app was created by you.

On macOS the system can detect any change to the app, whether the change is introduced accidentally or by malicious code.

On Windows, the system assigns a trust level to your code signing certificate which if you don't have, or if your trust level is low, will cause security dialogs to appear when users start using your application. Trust level builds over time so it's better to start code signing as early as possible.

While it is possible to distribute unsigned apps, it is not recommended. Both Windows and macOS will, by default, prevent either the download or the execution of unsigned applications. Starting with macOS Catalina (version 10.15), users have to go through multiple manual steps to open unsigned applications.

macOS Catalina Gatekeeper warning: The app cannot be opened because the
developer cannot be verified

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:

  1. Enroll in the Apple Developer Program (requires an annual fee)
  2. Download and install Xcode - this requires a computer running macOS
  3. 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": "[email protected]",
          "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:

  1. Get a Windows Authenticode code signing certificate (requires an annual fee)
  2. 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:

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)
  • Place class properties in the following order:
    • Class methods and properties (methods starting with a @)
    • Instance methods and properties
  • Avoid platform-dependent code:
    • Use path.join() to concatenate filenames.
    • Use os.tmpdir() rather than /tmp when you need to reference the temporary directory.
  • Using a plain return when returning explicitly at the end of a function.
    • Not return null, return undefined, null or undefined

C++ and Python

For C++ and Python, we follow Chromium's Coding Style. You can use clang-format to format the C++ code automatically. There is also a script script/cpplint.py to check whether all files conform.

The Python version we are using now is Python 2.7.

The C++ code uses a lot of Chromium's abstractions and types, so it's recommended to get acquainted with them. A good place to start is Chromium's Important Abstractions and Data Structures document. The document mentions some special types, scoped types (that automatically release their memory when going out of scope), logging mechanisms etc.

Documentation

  • Write remark markdown style.

You can run npm run lint-docs to ensure that your documentation changes are formatted correctly.

JavaScript

  • Write standard JavaScript style.
  • File names should be concatenated with - instead of _, e.g. file-name.js rather than file_name.js, because in github/atom module names are usually in the module-name form. This rule only applies to .js files.
  • Use newer ES6/ES2015 syntax where appropriate
    • const for requires and other constants. If the value is a primitive, use uppercase naming (eg const NUMBER_OF_RETRIES = 5).
    • let for defining variables
    • Arrow functions instead of function () { }
    • Template literals instead of string concatenation using +

Naming Things

Electron APIs uses the same capitalization scheme as Node.js:

  • When the module itself is a class like BrowserWindow, use PascalCase.
  • When the module is a set of APIs, like globalShortcut, use camelCase.
  • When the API is a property of object, and it is complex enough to be in a separate chapter like win.webContents, use mixedCase.
  • For other non-module APIs, use natural titles, like <webview> Tag or Process 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.

Instance Methods

commandLine.appendSwitch(switch[, value])

  • switch String - A command-line switch, without the leading --
  • value String (optional) - A value for the given switch

Append a switch (with optional value) to Chromium's command line.

Note: This will not affect process.argv. The intended usage of this function is to control Chromium's behavior.

commandLine.appendArgument(value)

  • value String - The argument to append to the command line

Append an argument to Chromium's command line. The argument will be quoted correctly. Switches will precede arguments regardless of appending order.

If you're appending an argument like --switch=value, consider using appendSwitch('switch', 'value') instead.

Note: This will not affect process.argv. The intended usage of this function is to control Chromium's behavior.

commandLine.hasSwitch(switch)

  • switch String - A command-line switch

Returns Boolean - Whether the command-line switch is present.

commandLine.getSwitchValue(switch)

  • switch String - A command-line switch

Returns String - The command-line switch value.

Note: When the switch is not present or has no value, it returns empty string.

Supported Command Line Switches

Command line switches supported by Electron.

You can use app.commandLine.appendSwitch to append them in your app's main script before the ready event of the app module is emitted:

const { app } = require('electron')
app.commandLine.appendSwitch('remote-debugging-port', '8315')
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1')

app.whenReady().then(() => {
  // Your code here
})

Electron CLI Flags

--auth-server-whitelist=url

A comma-separated list of servers for which integrated authentication is enabled.

For example:

--auth-server-whitelist='*example.com, *foobar.com, *baz'

then any url ending with example.com, foobar.com, baz will be considered for integrated authentication. Without * prefix the URL has to match exactly.

--auth-negotiate-delegate-whitelist=url

A comma-separated list of servers for which delegation of user credentials is required. Without * prefix the URL has to match exactly.

--disable-ntlm-v2

Disables NTLM v2 for posix platforms, no effect elsewhere.

--disable-http-cache

Disables the disk cache for HTTP requests.

--disable-http2

Disable HTTP/2 and SPDY/3.1 protocols.

--disable-renderer-backgrounding

Prevents Chromium from lowering the priority of invisible pages' renderer processes.

This flag is global to all renderer processes, if you only want to disable throttling in one window, you can take the hack of playing silent audio.

--disk-cache-size=size

Forces the maximum disk space to be used by the disk cache, in bytes.

--enable-api-filtering-logging

Enables caller stack logging for the following APIs (filtering events):

  • desktopCapturer.getSources() / desktop-capturer-get-sources
  • remote.require() / remote-require
  • remote.getGlobal() / remote-get-builtin
  • remote.getBuiltin() / remote-get-global
  • remote.getCurrentWindow() / remote-get-current-window
  • remote.getCurrentWebContents() / remote-get-current-web-contents

--enable-logging

Prints Chromium's logging into console.

This switch can not be used in app.commandLine.appendSwitch since it is parsed earlier than user's app is loaded, but you can set the ELECTRON_ENABLE_LOGGING environment variable to achieve the same effect.

--host-rules=rules

A comma-separated list of rules that control how hostnames are mapped.

For example:

  • MAP * 127.0.0.1 Forces all hostnames to be mapped to 127.0.0.1
  • MAP *.google.com proxy Forces all google.com subdomains to be resolved to "proxy".
  • MAP test.com [::1]:77 Forces "test.com" to resolve to IPv6 loopback. Will also force the port of the resulting socket address to be 77.
  • MAP * baz, EXCLUDE www.google.com Remaps everything to "baz", except for "www.google.com".

These mappings apply to the endpoint host in a net request (the TCP connect and host resolver in a direct connection, and the CONNECT in an HTTP proxy connection, and the endpoint host in a SOCKS proxy connection).

--host-resolver-rules=rules

Like --host-rules but these rules only apply to the host resolver.

--ignore-certificate-errors

Ignores certificate related errors.

--ignore-connections-limit=domains

Ignore the connections limit for domains list separated by ,.

--js-flags=flags

Specifies the flags passed to the Node.js engine. It has to be passed when starting Electron if you want to enable the flags in the main process.

$ electron --js-flags="--harmony_proxies --harmony_collections" your-app

See the Node.js documentation or run node --help in your terminal for a list of available flags. Additionally, run node --v8-options to see a list of flags that specifically refer to Node.js's V8 JavaScript engine.

--lang

Set a custom locale.

--log-net-log=path

Enables net log events to be saved and writes them to path.

--no-proxy-server

Don't use a proxy server and always make direct connections. Overrides any other proxy server flags that are passed.

--no-sandbox

Disables Chromium sandbox, which is now enabled by default. Should only be used for testing.

--proxy-bypass-list=hosts

Instructs Electron to bypass the proxy server for the given semi-colon-separated list of hosts. This flag has an effect only if used in tandem with --proxy-server.

For example:

const { app } = require('electron')
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')

Will use the proxy server for all hosts except for local addresses (localhost, 127.0.0.1 etc.), google.com subdomains, hosts that contain the suffix foo.com and anything at 1.2.3.4:5678.

--proxy-pac-url=url

Uses the PAC script at the specified url.

--proxy-server=address:port

Use a specified proxy server, which overrides the system setting. This switch only affects requests with HTTP protocol, including HTTPS and WebSocket requests. It is also noteworthy that not all proxy servers support HTTPS and WebSocket requests. The proxy URL does not support username and password authentication per Chromium issue.

--remote-debugging-port=port

Enables remote debugging over HTTP on the specified port.

--ppapi-flash-path=path

Sets the path of the pepper flash plugin.

--ppapi-flash-version=version

Sets the version of the pepper flash plugin.

--v=log_level

Gives the default maximal active V-logging level; 0 is the default. Normally positive values are used for V-logging levels.

This switch only works when --enable-logging is also passed.

--vmodule=pattern

Gives the per-module maximal V-logging levels to override the value given by --v. E.g. my_module=2,foo*=3 would change the logging level for all code in source files my_module.* and foo*.*.

Any pattern containing a forward or backward slash will be tested against the whole pathname and not only the module. E.g. */foo/bar/*=2 would change the logging level for all code in the source files under a foo/bar directory.

This switch only works when --enable-logging is also passed.

--force_high_performance_gpu

Force using discrete GPU when there are multiple GPUs available.

--force_low_power_gpu

Force using integrated GPU when there are multiple GPUs available.

Node.js Flags

Electron supports some of the CLI flags supported by Node.js.

Note: Passing unsupported command line switches to Electron when it is not running in ELECTRON_RUN_AS_NODE will have no effect.

--inspect-brk[=[host:]port]

Activate inspector on host:port and break at start of user script. Default host:port is 127.0.0.1:9229.

Aliased to --debug-brk=[host:]port.

--inspect-port=[host:]port

Set the host:port to be used when the inspector is activated. Useful when activating the inspector by sending the SIGUSR1 signal. Default host is 127.0.0.1.

Aliased to --debug-port=[host:]port.

--inspect[=[host:]port]

Activate inspector on host:port. Default is 127.0.0.1:9229.

V8 inspector integration allows tools such as Chrome DevTools and IDEs to debug and profile Electron instances. The tools attach to Electron instances via a TCP port and communicate using the Chrome DevTools Protocol.

See the Debugging the Main Process guide for more details.

Aliased to --debug[=[host:]port.

--inspect-publish-uid=stderr,http

Specify ways of the inspector web socket url exposure.

By default inspector websocket url is available in stderr and under /json/list endpoint on http://host:port/json/list.

contentTracing

Collect tracing data from Chromium to find performance bottlenecks and slow operations.

Process: Main

This module does not include a web interface. To view recorded traces, use trace viewer, available at chrome://tracing in Chrome.

Note: You should not use this module until the ready event of the app module is emitted.

const { app, contentTracing } = require('electron')

app.whenReady().then(() => {
  (async () => {
    await contentTracing.startRecording({
      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)

Returns Promise<void> - resolved once all child processes have acknowledged the startRecording request.

Start recording on all processes.

Recording begins immediately locally and asynchronously on child processes as soon as they receive the EnableRecording request.

If a recording is already running, the promise will be immediately resolved, as only one trace operation can be in progress at a time.

contentTracing.stopRecording([resultFilePath])

  • resultFilePath String (optional)

Returns Promise<String> - resolves with a path to a file that contains the traced data once all child processes have acknowledged the stopRecording request

Stop recording on all processes.

Child processes typically cache trace data and only rarely flush and send trace data back to the main process. This helps to minimize the runtime overhead of tracing since sending trace data over IPC can be an expensive operation. So, to end tracing, Chromium asynchronously asks all child processes to flush any pending trace data.

Trace data will be written into resultFilePath. If resultFilePath is empty or not provided, trace data will be written to a temporary file, and the path will be returned in the promise.

contentTracing.getTraceBufferUsage()

Returns Promise<Object> - Resolves with an object containing the value and percentage of trace buffer maximum usage

  • value Number
  • percentage Number

Get the maximum usage across processes of trace buffer as a percentage of the full state.

contextBridge

Create a safe, bi-directional, synchronous bridge across isolated contexts

Process: Renderer

An example of exposing an API to a renderer from an isolated preload script is given below:

// Preload (Isolated World)
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld(
  'electron',
  {
    doThing: () => ipcRenderer.send('do-a-thing')
  }
)
// Renderer (Main World)

window.electron.doThing()

Glossary

Main World

The "Main World" is the JavaScript context that your main renderer code runs in. By default, the page you load in your renderer executes code in this world.

Isolated World

When contextIsolation is enabled in your webPreferences, your preload scripts run in an "Isolated World". You can read more about context isolation and what it affects in the security docs.

Methods

The contextBridge module has the following methods:

contextBridge.exposeInMainWorld(apiKey, api) Experimental

  • apiKey String - The key to inject the API onto window with. The API will be accessible on window[apiKey].
  • api Record<String, any> - Your API object, more information on what this API can be and how it works is available below.

Usage

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.

Context Isolation

What is it?

Context Isolation is a feature that ensures that both your preload scripts and Electron's internal logic run in a separate context to the website you load in a webContents. This is important for security purposes as it helps prevent the website from accessing Electron internals or the powerful APIs your preload script has access to.

This means that the window object that your preload script has access to is actually a different object than the website would have access to. For example, if you set window.hello = 'wave' in your preload script and context isolation is enabled window.hello will be undefined if the website tries to access it.

Every single application should have context isolation enabled and from Electron 12 it will be enabled by default.

How do I enable it?

From Electron 12, it will be enabled by default. For lower versions it is an option in the webPreferences option when constructing new BrowserWindow's.

const mainWindow = new BrowserWindow({
  webPreferences: {
    contextIsolation: true
  }
})

Migration

I used to provide APIs from my preload script using window.X = apiObject now what?

Exposing APIs from your preload script to the loaded website is a common usecase and there is a dedicated module in Electron to help you do this in a painless way.

Before: With context isolation disabled

window.myAPI = {
  doAThing: () => {}
}

After: With context isolation enabled

const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
  doAThing: () => {}
})

The contextBridge module can be used to safely expose APIs from the isolated context your preload script runs in to the context the website is running in. The API will also be accessible from the website on window.myAPI just like it was before.

You should read the contextBridge documentation linked above to fully understand its limitations. For instance you can't send custom prototypes or symbols over the bridge.

Security Considerations

Just enabling contextIsolation and using contextBridge does not automatically mean that everything you do is safe. For instance this code is unsafe.

// ❌ Bad code
contextBridge.exposeInMainWorld('myAPI', {
  send: ipcRenderer.send
})

It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.

// ✅ Good code
contextBridge.exposeInMainWorld('myAPI', {
  loadPreferences: () => ipcRenderer.invoke('load-prefs')
})

Cookie Object

  • name String - The name of the cookie.
  • value String - The value of the cookie.
  • domain String (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains.
  • hostOnly Boolean (optional) - Whether the cookie is a host-only cookie; this will only be true if no domain was passed.
  • path String (optional) - The path of the cookie.
  • secure Boolean (optional) - Whether the cookie is marked as secure.
  • httpOnly Boolean (optional) - Whether the cookie is marked as HTTP only.
  • session Boolean (optional) - Whether the cookie is a session cookie or a persistent cookie with an expiration date.
  • expirationDate Double (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch. Not provided for session cookies.
  • sameSite String - The Same Site policy applied to this cookie. Can be unspecified, no_restriction, lax or strict.

Class: Cookies

Query and modify a session's cookies.

Process: Main

Instances of the Cookies class are accessed by using cookies property of a Session.

For example:

const { session } = require('electron')

// Query all cookies.
session.defaultSession.cookies.get({})
  .then((cookies) => {
    console.log(cookies)
  }).catch((error) => {
    console.log(error)
  })

// Query all cookies associated with a specific url.
session.defaultSession.cookies.get({ url: 'http://www.github.com' })
  .then((cookies) => {
    console.log(cookies)
  }).catch((error) => {
    console.log(error)
  })

// Set a cookie with the given cookie data;
// may overwrite equivalent cookies if they exist.
const cookie = { url: 'http://www.github.com', name: 'dummy_name', value: 'dummy' }
session.defaultSession.cookies.set(cookie)
  .then(() => {
    // success
  }, (error) => {
    console.error(error)
  })

Instance Events

The following events are available on instances of Cookies:

Event: 'changed'

  • event Event
  • cookie Cookie - The cookie that was changed.
  • cause String - The cause of the change with one of the following values:
    • explicit - The cookie was changed directly by a consumer's action.
    • overwrite - The cookie was automatically removed due to an insert operation that overwrote it.
    • expired - The cookie was automatically removed as it expired.
    • evicted - The cookie was automatically evicted during garbage collection.
    • expired-overwrite - The cookie was overwritten with an already-expired expiration date.
  • removed Boolean - true if the cookie was removed, false otherwise.

Emitted when a cookie is changed because it was added, edited, removed, or expired.

Instance Methods

The following methods are available on instances of Cookies:

cookies.get(filter)

  • filter Object
    • url String (optional) - Retrieves cookies which are associated with url. Empty implies retrieving cookies of all URLs.
    • name String (optional) - Filters cookies by name.
    • domain String (optional) - Retrieves cookies whose domains match or are subdomains of domains.
    • path String (optional) - Retrieves cookies whose path matches path.
    • secure Boolean (optional) - Filters cookies by their Secure property.
    • session Boolean (optional) - Filters out session or persistent cookies.

Returns Promise<Cookie[]> - A promise which resolves an array of cookie objects.

Sends a request to get all cookies matching filter, and resolves a promise with the response.

cookies.set(details)

  • details Object
    • url String - The URL to associate the cookie with. The promise will be rejected if the URL is invalid.
    • name String (optional) - The name of the cookie. Empty by default if omitted.
    • value String (optional) - The value of the cookie. Empty by default if omitted.
    • domain String (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains. Empty by default if omitted.
    • path String (optional) - The path of the cookie. Empty by default if omitted.
    • secure Boolean (optional) - Whether the cookie should be marked as Secure. Defaults to false.
    • httpOnly Boolean (optional) - Whether the cookie should be marked as HTTP only. Defaults to false.
    • expirationDate Double (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch. If omitted then the cookie becomes a session cookie and will not be retained between sessions.
    • sameSite String (optional) - The Same Site policy to apply to this cookie. Can be unspecified, no_restriction, lax or strict. Default is no_restriction.

Returns Promise<void> - A promise which resolves when the cookie has been set

Sets a cookie with details.

cookies.remove(url, name)

  • url String - The URL associated with the cookie.
  • name String - The name of cookie to remove.

Returns Promise<void> - A promise which resolves when the cookie has been removed

Removes the cookies matching url and name

cookies.flushStore()

Returns Promise<void> - A promise which resolves when the cookie store has been flushed

Writes any unwritten cookies data to disk.

CPUUsage Object

  • percentCPUUsage Number - Percentage of CPU used since the last call to getCPUUsage. First call returns 0.
  • idleWakeupsPerSecond Number - The number of average idle CPU wakeups per second since the last call to getCPUUsage. First call returns 0. Will always return 0 on Windows.

CrashReport Object

  • date Date
  • id String

crashReporter

Submit crash reports to a remote server.

Process: Main, Renderer

The following is an example of setting up Electron to automatically submit crash reports to a remote server:

const { crashReporter } = require('electron')

crashReporter.start({ submitURL: 'https://your-domain.com/url-to-submit' })

For setting up a server to accept and process crash reports, you can use following projects:

Or use a 3rd party hosted solution:

Crash reports are stored temporarily before being uploaded in a directory underneath the app's user data directory (called 'Crashpad' on Windows and Mac, or 'Crash Reports' on Linux). You can override this directory by calling app.setPath('crashDumps', '/path/to/crashes') before starting the crash reporter.

On Windows and macOS, Electron uses crashpad to monitor and report crashes. On Linux, Electron uses breakpad. This is an implementation detail driven by Chromium, and it may change in future. In particular, crashpad is newer and will likely eventually replace breakpad on all platforms.

Methods

The crashReporter module has the following methods:

crashReporter.start(options)

  • options Object
    • submitURL String - URL that crash reports will be sent to as POST.
    • productName String (optional) - Defaults to app.name.
    • companyName String (optional) Deprecated - Deprecated alias for { globalExtra: { _companyName: ... } }.
    • uploadToServer Boolean (optional) - Whether crash reports should be sent to the server. If false, crash reports will be collected and stored in the crashes directory, but not uploaded. Default is true.
    • ignoreSystemCrashHandler Boolean (optional) - If true, crashes generated in the main process will not be forwarded to the system crash handler. Default is false.
    • rateLimit Boolean (optional) macOS Windows - If true, limit the number of crashes uploaded to 1/hour. Default is false.
    • compress Boolean (optional) - If true, crash reports will be compressed and uploaded with Content-Encoding: gzip. Default is false.
    • extra Record<String, String> (optional) - Extra string key/value annotations that will be sent along with crash reports that are generated in the main process. Only string values are supported. Crashes generated in child processes will not contain these extra parameters to crash reports generated from child processes, call addExtraParameter from the child process.
    • globalExtra Record<String, String> (optional) - Extra string key/value annotations that will be sent along with any crash reports generated in any process. These annotations cannot be changed once the crash reporter has been started. If a key is present in both the global extra parameters and the process-specific extra parameters, then the global one will take precedence. By default, productName and the app version are included, as well as the Electron version.

This method must be called before using any other crashReporter APIs. Once initialized this way, the crashpad handler collects crashes from all subsequently created processes. The crash reporter cannot be disabled once started.

This method should be called as early as possible in app startup, preferably before app.on('ready'). If the crash reporter is not initialized at the time a renderer process is created, then that renderer process will not be monitored by the crash reporter.

Note: You can test out the crash reporter by generating a crash using process.crash().

Note: If you need to send additional/updated extra parameters after your first call start you can call addExtraParameter.

Note: Parameters passed in extra, globalExtra or set with addExtraParameter have limits on the length of the keys and values. Key names must be at most 39 bytes long, and values must be no longer than 127 bytes. Keys with names longer than the maximum will be silently ignored. Key values longer than the maximum length will be truncated.

Note: Calling this method from the renderer process is deprecated.

crashReporter.getLastCrashReport()

Returns CrashReport - The date and ID of the last crash report. Only crash reports that have been uploaded will be returned; even if a crash report is present on disk it will not be returned until it is uploaded. In the case that there are no uploaded reports, null is returned.

Note: Calling this method from the renderer process is deprecated.

crashReporter.getUploadedReports()

Returns CrashReport[]:

Returns all uploaded crash reports. Each report contains the date and uploaded ID.

Note: Calling this method from the renderer process is deprecated.

crashReporter.getUploadToServer()

Returns Boolean - Whether reports should be submitted to the server. Set through the start method or setUploadToServer.

Note: Calling this method from the renderer process is deprecated.

crashReporter.setUploadToServer(uploadToServer)

  • uploadToServer Boolean - Whether reports should be submitted to the server.

This would normally be controlled by user preferences. This has no effect if called before start is called.

Note: Calling this method from the renderer process is deprecated.

crashReporter.getCrashesDirectory() Deprecated

Returns String - The directory where crashes are temporarily stored before being uploaded.

Note: This method is deprecated, use app.getPath('crashDumps') instead.

crashReporter.addExtraParameter(key, value)

  • key String - Parameter key, must be no longer than 39 bytes.
  • value String - Parameter value, must be no longer than 127 bytes.

Set an extra parameter to be sent with the crash report. The values specified here will be sent in addition to any values set via the extra option when start was called.

Parameters added in this fashion (or via the extra parameter to crashReporter.start) are specific to the calling process. Adding extra parameters in the main process will not cause those parameters to be sent along with crashes from renderer or other child processes. Similarly, adding extra parameters in a renderer process will not result in those parameters being sent with crashes that occur in other renderer processes or in the main process.

Note: Parameters have limits on the length of the keys and values. Key names must be no longer than 39 bytes, and values must be no longer than 20320 bytes. Keys with names longer than the maximum will be silently ignored. Key values longer than the maximum length will be truncated.

Note: On linux values that are longer than 127 bytes will be chunked into multiple keys, each 127 bytes in length. E.g. addExtraParameter('foo', 'a'.repeat(130)) will result in two chunked keys foo__1 and foo__2, the first will contain the first 127 bytes and the second will contain the remaining 3 bytes. On your crash reporting backend you should stitch together keys in this format.

crashReporter.removeExtraParameter(key)

  • key String - Parameter key, must be no longer than 39 bytes.

Remove an extra parameter from the current set of parameters. Future crashes will not include this parameter.

crashReporter.getParameters()

Returns Record<String, String> - The current 'extra' parameters of the crash reporter.

Crash Report Payload

The crash reporter will send the following data to the submitURL as a multipart/form-data POST:

  • ver String - The version of Electron.
  • platform String - e.g. 'win32'.
  • process_type String - e.g. 'renderer'.
  • guid String - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72'.
  • _version String - The version in package.json.
  • _productName String - The product name in the crashReporter options object.
  • prod String - Name of the underlying product. In this case Electron.
  • _companyName String - The company name in the crashReporter options object.
  • upload_file_minidump File - The crash report in the format of minidump.
  • All level one properties of the extra object in the crashReporter options object.

CustomScheme Object

  • scheme String - Custom schemes to be registered with options.
  • privileges Object (optional)
    • standard Boolean (optional) - Default false.
    • secure Boolean (optional) - Default false.
    • bypassCSP Boolean (optional) - Default false.
    • allowServiceWorkers Boolean (optional) - Default false.
    • supportFetchAPI Boolean (optional) - Default false.
    • corsEnabled Boolean (optional) - Default false.
    • stream Boolean (optional) - Default false.

Dark Mode

Overview

Automatically update the native interfaces

"Native interfaces" include the file picker, window border, dialogs, context menus, and more - anything where the UI comes from your operating system and not from your app. The default behavior is to opt into this automatic theming from the OS.

Automatically update your own interfaces

If your app has its own dark mode, you should toggle it on and off in sync with the system's dark mode setting. You can do this by using the prefer-color-scheme CSS media query.

Manually update your own interfaces

If you want to manually switch between light/dark modes, you can do this by setting the desired mode in the themeSource property of the nativeTheme module. This property's value will be propagated to your Renderer process. Any CSS rules related to prefers-color-scheme will be updated accordingly.

macOS settings

In macOS 10.14 Mojave, Apple introduced a new system-wide dark mode for all macOS computers. If your Electron app has a dark mode, you can make it follow the system-wide dark mode setting using the nativeTheme api.

In macOS 10.15 Catalina, Apple introduced a new "automatic" dark mode option for all macOS computers. In order for the nativeTheme.shouldUseDarkColors and Tray APIs to work correctly in this mode on Catalina, you need to use Electron >=7.0.0, or set NSRequiresAquaSystemAppearance to false in your Info.plist file for older versions. Both Electron Packager and Electron Forge have a darwinDarkModeSupport option to automate the Info.plist changes during app build time.

If you wish to opt-out while using Electron > 8.0.0, you must set the NSRequiresAquaSystemAppearance key in the Info.plist file to true. Please note that Electron 8.0.0 and above will not let you opt-out of this theming, due to the use of the macOS 10.14 SDK.

Example

We'll start with a working application from the Quick Start Guide and add functionality gradually.

First, let's edit our interface so users can toggle between light and dark modes. This basic UI contains buttons to change the nativeTheme.themeSource setting and a text element indicating which themeSource value is selected. By default, Electron follows the system's dark mode preference, so we will hardcode the theme source as "System".

Add the following lines to the index.html file:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
    <link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
    <h1>Hello World!</h1>
    <p>Current theme source: <strong id="theme-source">System</strong></p>

    <button id="toggle-dark-mode">Toggle Dark Mode</button>
    <button id="reset-to-system">Reset to System Theme</button>

    <script src="renderer.js"></script>
  </body>
</body>
</html>

Next, add event listeners that listen for click events on the toggle buttons. Because the nativeTheme module only exposed in the Main process, you need to set up each listener's callback to use IPC to send messages to and handle responses from the Main process:

  • when the "Toggle Dark Mode" button is clicked, we send the dark-mode:toggle message (event) to tell the Main process to trigger a theme change, and update the "Current Theme Source" label in the UI based on the response from the Main process.
  • when the "Reset to System Theme" button is clicked, we send the dark-mode:system message (event) to tell the Main process to use the system color scheme, and update the "Current Theme Source" label to System.

To add listeners and handlers, add the following lines to the renderer.js file:

const { ipcRenderer } = require('electron')

document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
  const isDarkMode = await ipcRenderer.invoke('dark-mode:toggle')
  document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
})

document.getElementById('reset-to-system').addEventListener('click', async () => {
  await ipcRenderer.invoke('dark-mode:system')
  document.getElementById('theme-source').innerHTML = 'System'
})

If you run your code at this point, you'll see that your buttons don't do anything just yet, and your Main process will output an error like this when you click on your buttons: Error occurred in handler for 'dark-mode:toggle': No handler registered for 'dark-mode:toggle' This is expected — we haven't actually touched any nativeTheme code yet.

Now that we're done wiring the IPC from the Renderer's side, the next step is to update the main.js file to handle events from the Renderer process.

Depending on the received event, we update the nativeTheme.themeSource property to apply the desired theme on the system's native UI elements (e.g. context menus) and propagate the preferred color scheme to the Renderer process:

  • Upon receiving dark-mode:toggle, we check if the dark theme is currently active using the nativeTheme.shouldUseDarkColors property, and set the themeSource to the opposite theme.
  • Upon receiving dark-mode:system, we reset the themeSource to system.
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  win.loadFile('index.html')

  ipcMain.handle('dark-mode:toggle', () => {
    if (nativeTheme.shouldUseDarkColors) {
      nativeTheme.themeSource = 'light'
    } else {
      nativeTheme.themeSource = 'dark'
    }
    return nativeTheme.shouldUseDarkColors
  })

  ipcMain.handle('dark-mode:system', () => {
    nativeTheme.themeSouce = 'system'
  })
}

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

The final step is to add a bit of styling to enable dark mode for the web parts of the UI by leveraging the prefers-color-scheme CSS attribute. The value of prefers-color-scheme will follow your nativeTheme.themeSource setting.

Create a styles.css file and add the following lines:

@media (prefers-color-scheme: dark) {
  body { background:  #333; color: white; }
}

@media (prefers-color-scheme: light) {
  body { background:  #ddd; color: black; }
}

After launching the Electron application, you can change modes or reset the theme to system default by clicking corresponding buttons:

Dark Mode

Debugging on Windows

If you experience crashes or issues in Electron that you believe are not caused by your JavaScript application, but instead by Electron itself, debugging can be a little bit tricky, especially for developers not used to native/C++ debugging. However, using Visual Studio, Electron's hosted Symbol Server, and the Electron source code, you can enable step-through debugging with breakpoints inside Electron's source code.

See also: There's a wealth of information on debugging Chromium, much of which also applies to Electron, on the Chromium developers site: Debugging Chromium on Windows.

Requirements

  • A debug build of Electron: The easiest way is usually building it yourself, using the tools and prerequisites listed in the build instructions for Windows. While you can attach to and debug Electron as you can download it directly, you will find that it is heavily optimized, making debugging substantially more difficult: The debugger will not be able to show you the content of all variables and the execution path can seem strange because of inlining, tail calls, and other compiler optimizations.

  • Visual Studio with C++ Tools: The free community editions of Visual Studio 2013 and Visual Studio 2015 both work. Once installed, configure Visual Studio to use Electron's Symbol server. It will enable Visual Studio to gain a better understanding of what happens inside Electron, making it easier to present variables in a human-readable format.

  • ProcMon: The free SysInternals tool allows you to inspect a processes parameters, file handles, and registry operations.

Attaching to and Debugging Electron

To start a debugging session, open up PowerShell/CMD and execute your debug build of Electron, using the application to open as a parameter.

$ ./out/Testing/electron.exe ~/my-electron-app/

Setting Breakpoints

Then, open up Visual Studio. Electron is not built with Visual Studio and hence does not contain a project file - you can however open up the source code files "As File", meaning that Visual Studio will open them up by themselves. You can still set breakpoints - Visual Studio will automatically figure out that the source code matches the code running in the attached process and break accordingly.

Relevant code files can be found in ./shell/.

Attaching

You can attach the Visual Studio debugger to a running process on a local or remote computer. After the process is running, click Debug / Attach to Process (or press CTRL+ALT+P) to open the "Attach to Process" dialog box. You can use this capability to debug apps that are running on a local or remote computer, debug multiple processes simultaneously.

If Electron is running under a different user account, select the Show processes from all users check box. Notice that depending on how many BrowserWindows your app opened, you will see multiple processes. A typical one-window app will result in Visual Studio presenting you with two Electron.exe entries - one for the main process and one for the renderer process. Since the list only gives you names, there's currently no reliable way of figuring out which is which.

Which Process Should I Attach to?

Code executed within the main process (that is, code found in or eventually run by your main JavaScript file) will run inside the main process, while other code will execute inside its respective renderer process.

You can be attached to multiple programs when you are debugging, but only one program is active in the debugger at any time. You can set the active program in the Debug Location toolbar or the Processes window.

Using ProcMon to Observe a Process

While Visual Studio is fantastic for inspecting specific code paths, ProcMon's strength is really in observing everything your application is doing with the operating system - it captures File, Registry, Network, Process, and Profiling details of processes. It attempts to log all events occurring and can be quite overwhelming, but if you seek to understand what and how your application is doing to the operating system, it can be a valuable resource.

For an introduction to ProcMon's basic and advanced debugging features, go check out this video tutorial provided by Microsoft.

Class: Debugger

An alternate transport for Chrome's remote debugging protocol.

Process: Main

Chrome Developer Tools has a special binding available at JavaScript runtime that allows interacting with pages and instrumenting them.

const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

try {
  win.webContents.debugger.attach('1.1')
} catch (err) {
  console.log('Debugger attach failed : ', err)
}

win.webContents.debugger.on('detach', (event, reason) => {
  console.log('Debugger detached due to : ', reason)
})

win.webContents.debugger.on('message', (event, method, params) => {
  if (method === 'Network.requestWillBeSent') {
    if (params.request.url === 'https://www.github.com') {
      win.webContents.debugger.detach()
    }
  }
})

win.webContents.debugger.sendCommand('Network.enable')

Instance Events

Event: 'detach'

Returns:

  • event Event
  • reason String - Reason for detaching debugger.

Emitted when the debugging session is terminated. This happens either when webContents is closed or devtools is invoked for the attached webContents.

Event: 'message'

Returns:

  • event Event
  • method String - Method name.
  • params any - Event parameters defined by the 'parameters' attribute in the remote debugging protocol.
  • sessionId String - Unique identifier of attached debugging session, will match the value sent from debugger.sendCommand.

Emitted whenever the debugging target issues an instrumentation event.

Instance Methods

debugger.attach([protocolVersion])

  • protocolVersion String (optional) - Requested debugging protocol version.

Attaches the debugger to the webContents.

debugger.isAttached()

Returns Boolean - Whether a debugger is attached to the webContents.

debugger.detach()

Detaches the debugger from the webContents.

debugger.sendCommand(method[, commandParams, sessionId])

  • method String - Method name, should be one of the methods defined by the remote debugging protocol.
  • commandParams any (optional) - JSON object with request parameters.
  • sessionId String (optional) - send command to the target with associated debugging session id. The initial value can be obtained by sending Target.attachToTarget message.

Returns Promise<any> - A promise that resolves with the response defined by the 'returns' attribute of the command description in the remote debugging protocol or is rejected indicating the failure of the command.

Send given command to the debugging target.

Debugging on macOS

If you experience crashes or issues in Electron that you believe are not caused by your JavaScript application, but instead by Electron itself, debugging can be a little bit tricky, especially for developers not used to native/C++ debugging. However, using lldb, and the Electron source code, you can enable step-through debugging with breakpoints inside Electron's source code. You can also use XCode for debugging if you prefer a graphical interface.

Requirements

  • A debug build of Electron: The easiest way is usually building it yourself, using the tools and prerequisites listed in the build instructions for macOS. While you can attach to and debug Electron as you can download it directly, you will find that it is heavily optimized, making debugging substantially more difficult: The debugger will not be able to show you the content of all variables and the execution path can seem strange because of inlining, tail calls, and other compiler optimizations.

  • Xcode: In addition to Xcode, also install the Xcode command line tools. They include LLDB, the default debugger in Xcode on macOS. It supports debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.

  • .lldbinit: Create or edit ~/.lldbinit to allow Chromium code to be properly source-mapped.

    command script import ~/electron/src/tools/lldb/lldbinit.py
    

Attaching to and Debugging Electron

To start a debugging session, open up Terminal and start lldb, passing a non-release build of Electron as a parameter.

$ lldb ./out/Testing/Electron.app
(lldb) target create "./out/Testing/Electron.app"
Current executable set to './out/Testing/Electron.app' (x86_64).

Setting Breakpoints

LLDB is a powerful tool and supports multiple strategies for code inspection. For this basic introduction, let's assume that you're calling a command from JavaScript that isn't behaving correctly - so you'd like to break on that command's C++ counterpart inside the Electron source.

Relevant code files can be found in ./shell/.

Let's assume that you want to debug app.setName(), which is defined in browser.cc as Browser::SetName(). Set the breakpoint using the breakpoint command, specifying file and line to break on:

(lldb) breakpoint set --file browser.cc --line 117
Breakpoint 1: where = Electron Framework`atom::Browser::SetName(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 20 at browser.cc:118, address = 0x000000000015fdb4

Then, start Electron:

(lldb) run

The app will immediately be paused, since Electron sets the app's name on launch:

(lldb) run
Process 25244 launched: '/Users/fr/Code/electron/out/Testing/Electron.app/Contents/MacOS/Electron' (x86_64)
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118
   115  }
   116
   117  void Browser::SetName(const std::string& name) {
-> 118    name_override_ = name;
   119  }
   120
   121  int Browser::GetBadgeCount() {
(lldb)

To show the arguments and local variables for the current frame, run frame variable (or fr v), which will show you that the app is currently setting the name to "Electron".

(lldb) frame variable
(atom::Browser *) this = 0x0000000108b14f20
(const string &) name = "Electron": {
    [...]
}

To do a source level single step in the currently selected thread, execute step (or s). This would take you into name_override_.empty(). To proceed and do a step over, run next (or n).

(lldb) step
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119
   116
   117  void Browser::SetName(const std::string& name) {
   118    name_override_ = name;
-> 119  }
   120
   121  int Browser::GetBadgeCount() {
   122    return badge_count_;

NOTE: If you don't see source code when you think you should, you may not have added the ~/.lldbinit file above.

To finish debugging at this point, run process continue. You can also continue until a certain line is hit in this thread (thread until 100). This command will run the thread in the current frame till it reaches line 100 in this frame or stops if it leaves the current frame.

Now, if you open up Electron's developer tools and call setName, you will once again hit the breakpoint.

Further Reading

LLDB is a powerful tool with a great documentation. To learn more about it, consider Apple's debugging documentation, for instance the LLDB Command Structure Reference or the introduction to Using LLDB as a Standalone Debugger.

You can also check out LLDB's fantastic manual and tutorial, which will explain more complex debugging scenarios.

Debugging with XCode

Generate xcode project for debugging sources (cannot build code from xcode)

Run gn gen with the --ide=xcode argument.

$ gn gen out/Testing --ide=xcode

This will generate the electron.ninja.xcworkspace. You will have to open this workspace to set breakpoints and inspect.

See gn help gen for more information on generating IDE projects with GN.

Debugging and breakpoints

Launch Electron app after build. You can now open the xcode workspace created above and attach to the Electron process through the Debug > Attach To Process > Electron debug menu. [Note: If you want to debug the renderer process, you need to attach to the Electron Helper as well.]

You can now set breakpoints in any of the indexed files. However, you will not be able to set breakpoints directly in the Chromium source. To set break points in the Chromium source, you can choose Debug > Breakpoints > Create Symbolic Breakpoint and set any function name as the symbol. This will set the breakpoint for all functions with that name, from all the classes if there are more than one. You can also do this step of setting break points prior to attaching the debugger, however, actual breakpoints for symbolic breakpoint functions may not show up until the debugger is attached to the app.

Debugging the Main Process

The DevTools in an Electron browser window can only debug JavaScript that's executed in that window (i.e. the web pages). To debug JavaScript that's executed in the main process you will need to use an external debugger and launch Electron with the --inspect or --inspect-brk switch.

Command Line Switches

Use one of the following command line switches to enable debugging of the main process:

--inspect=[port]

Electron will listen for V8 inspector protocol messages on the specified port, an external debugger will need to connect on this port. The default port is 5858.

electron --inspect=5858 your/app

--inspect-brk=[port]

Like --inspect but pauses execution on the first line of JavaScript.

External Debuggers

You will need to use a debugger that supports the V8 inspector protocol.

  • Connect Chrome by visiting chrome://inspect and selecting to inspect the launched Electron app present there.
  • Debugging in VSCode

Debugging in VSCode

This guide goes over how to set up VSCode debugging for both your own Electron project as well as the native Electron codebase.

Debugging your Electron app

Main process

1. Open an Electron project in VSCode.

$ git clone [email protected]:electron/electron-quick-start.git
$ code electron-quick-start

2. Add a file .vscode/launch.json with the following configuration:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Main Process",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}",
      "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
      "windows": {
        "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
      },
      "args" : ["."],
      "outputCapture": "std"
    }
  ]
}

3. Debugging

Set some breakpoints in main.js, and start debugging in the Debug View. You should be able to hit the breakpoints.

Here is a pre-configured project that you can download and directly debug in VSCode: https://github.com/octref/vscode-electron-debug/tree/master/electron-quick-start

Debugging the Electron codebase

If you want to build Electron from source and modify the native Electron codebase, this section will help you in testing your modifications.

For those unsure where to acquire this code or how to build it, Electron's Build Tools automates and explains most of this process. If you wish to manually set up the environment, you can instead use these build instructions.

Windows (C++)

1. Open an Electron project in VSCode.

$ git clone [email protected]:electron/electron-quick-start.git
$ code electron-quick-start

2. Add a file .vscode/launch.json with the following configuration:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "(Windows) Launch",
      "type": "cppvsdbg",
      "request": "launch",
      "program": "${workspaceFolder}\\out\\your-executable-location\\electron.exe",
      "args": ["your-electron-project-path"],
      "stopAtEntry": false,
      "cwd": "${workspaceFolder}",
      "environment": [
          {"name": "ELECTRON_ENABLE_LOGGING", "value": "true"},
          {"name": "ELECTRON_ENABLE_STACK_DUMPING", "value": "true"},
          {"name": "ELECTRON_RUN_AS_NODE", "value": ""},
      ],
      "externalConsole": false,
      "sourceFileMap": {
          "o:\\": "${workspaceFolder}",
      },
    },
  ]
}

Configuration Notes

  • cppvsdbg requires the built-in C/C++ extension be enabled.
  • ${workspaceFolder} is the full path to Chromium's src directory.
  • your-executable-location will be one of the following depending on a few items:
    • Testing: If you are using the default settings of Electron's Build-Tools or the default instructions when building from source.
    • Release: If you built a Release build rather than a Testing build.
    • your-directory-name: If you modified this during your build process from the default, this will be whatever you specified.
  • The args array string "your-electron-project-path" should be the absolute path to either the directory or main.js file of the Electron project you are using for testing. In this example, it should be your path to electron-quick-start.

3. Debugging

Set some breakpoints in the .cc files of your choosing in the native Electron C++ code, and start debugging in the Debug View.

desktopCapturer

Access information about media sources that can be used to capture audio and video from the desktop using the navigator.mediaDevices.getUserMedia API.

Process: Main, Renderer

The following example shows how to capture video from a desktop window whose title is Electron:

// In the renderer process.
const { desktopCapturer } = require('electron')

desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => {
  for (const source of sources) {
    if (source.name === 'Electron') {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: false,
          video: {
            mandatory: {
              chromeMediaSource: 'desktop',
              chromeMediaSourceId: source.id,
              minWidth: 1280,
              maxWidth: 1280,
              minHeight: 720,
              maxHeight: 720
            }
          }
        })
        handleStream(stream)
      } catch (e) {
        handleError(e)
      }
      return
    }
  }
})

function handleStream (stream) {
  const video = document.querySelector('video')
  video.srcObject = stream
  video.onloadedmetadata = (e) => video.play()
}

function handleError (e) {
  console.log(e)
}

To capture video from a source provided by desktopCapturer the constraints passed to navigator.mediaDevices.getUserMedia must include chromeMediaSource: 'desktop', and audio: false.

To capture both audio and video from the entire desktop the constraints passed to navigator.mediaDevices.getUserMedia must include chromeMediaSource: 'desktop', for both audio and video, but should not include a chromeMediaSourceId constraint.

const constraints = {
  audio: {
    mandatory: {
      chromeMediaSource: 'desktop'
    }
  },
  video: {
    mandatory: {
      chromeMediaSource: 'desktop'
    }
  }
}

Methods

The desktopCapturer module has the following methods:

desktopCapturer.getSources(options)

  • options Object
    • types String[] - An array of Strings that lists the types of desktop sources to be captured, available types are screen and window.
    • thumbnailSize Size (optional) - The size that the media source thumbnail should be scaled to. Default is 150 x 150. Set width or height to 0 when you do not need the thumbnails. This will save the processing time required for capturing the content of each window and screen.
    • fetchWindowIcons Boolean (optional) - Set to true to enable fetching window icons. The default value is false. When false the appIcon property of the sources return null. Same if a source has the type screen.

Returns Promise<DesktopCapturerSource[]> - Resolves with an array of DesktopCapturerSource objects, each DesktopCapturerSource represents a screen or an individual window that can be captured.

Note Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher, which can detected by systemPreferences.getMediaAccessStatus.

Caveats

navigator.mediaDevices.getUserMedia does not work on macOS for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a signed kernel extension. Chromium, and by extension Electron, does not provide this.

It is possible to circumvent this limitation by capturing system audio with another macOS app like Soundflower and passing it through a virtual audio input device. This virtual device can then be queried with navigator.mediaDevices.getUserMedia.

DesktopCapturerSource Object

  • id String - The identifier of a window or screen that can be used as a chromeMediaSourceId constraint when calling [navigator.webkitGetUserMedia]. The format of the identifier will be window:XX or screen:XX, where XX is a random generated number.
  • name String - A screen source will be named either Entire Screen or Screen <index>, while the name of a window source will match the window title.
  • thumbnail NativeImage - A thumbnail image. Note: There is no guarantee that the size of the thumbnail is the same as the thumbnailSize specified in the options passed to desktopCapturer.getSources. The actual size depends on the scale of the screen or window.
  • display_id String - A unique identifier that will correspond to the id of the matching Display returned by the Screen API. On some platforms, this is equivalent to the XX portion of the id field above and on others it will differ. It will be an empty string if not available.
  • appIcon NativeImage - An icon image of the application that owns the window or null if the source has a type screen. The size of the icon is not known in advance and depends on what the application provides.

Desktop Environment Integration

Different operating systems provide different features for integrating desktop applications into their desktop environments. For example, on Windows, applications can put shortcuts in the JumpList of task bar, and on Mac, applications can put a custom menu in the dock menu.

This guide explains how to integrate your application into those desktop environments with Electron APIs.

Notifications

See the Notifications documentation.

Recent Documents

See Recent Documents documentation.

Progress Bar

See the Progress Bar documentation.

Unity Launcher

See the Unity Launcher documentation.

Represented File for macOS Window

See the Represented File documentation.

Dragging files out of the window

See the Native File Drag & Drop 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:

  1. Install it in Chrome browser.

  2. Navigate to chrome://extensions, and find its extension ID, which is a hash string like fmkadmapgofadopljbjfkapdkoienihi.

  3. 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.
  4. Pass the location of the extension to BrowserWindow.addDevToolsExtension API, 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)

  • browserWindow BrowserWindow (optional)
  • options Object
    • title String (optional)
    • defaultPath String (optional)
    • buttonLabel String (optional) - Custom label for the confirmation button, when left empty the default label will be used.
    • filters FileFilter[] (optional)
    • properties String[] (optional) - Contains which features the dialog should use. The following values are supported:
      • openFile - Allow files to be selected.
      • openDirectory - Allow directories to be selected.
      • multiSelections - Allow multiple paths to be selected.
      • showHiddenFiles - Show hidden files in dialog.
      • createDirectory macOS - Allow creating new directories from dialog.
      • promptToCreate Windows - Prompt for creation if the file path entered in the dialog does not exist. This does not actually create the file at the path but allows non-existent paths to be returned that should be created by the application.
      • noResolveAliases macOS - Disable the automatic alias (symlink) path resolution. Selected aliases will now return the alias path instead of their target path.
      • treatPackageAsDirectory macOS - Treat packages, such as .app folders, as a directory instead of a file.
      • dontAddToRecent Windows - Do not add the item being opened to the recent documents list.
    • message String (optional) macOS - Message to display above input boxes.
    • securityScopedBookmarks Boolean (optional) macOS mas - Create security scoped bookmarks when packaged for the Mac App Store.

Returns String[] | undefined, the file paths chosen by the user; if the dialog is cancelled it returns undefined.

The browserWindow argument allows the dialog to attach itself to a parent window, making it modal.

The filters specifies an array of file types that can be displayed or selected when you want to limit the user to a specific type. For example:

{
  filters: [
    { name: 'Images', extensions: ['jpg', 'png', 'gif'] },
    { name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
    { name: 'Custom File Type', extensions: ['as'] },
    { name: 'All Files', extensions: ['*'] }
  ]
}

The extensions array should contain extensions without wildcards or dots (e.g. 'png' is good but '.png' and '*.png' are bad). To show all files, use the '*' wildcard (no other wildcard is supported).

Note: On Windows and Linux an open dialog can not be both a file selector and a directory selector, so if you set properties to ['openFile', 'openDirectory'] on these platforms, a directory selector will be shown.

dialog.showOpenDialogSync(mainWindow, {
  properties: ['openFile', 'openDirectory']
})

dialog.showOpenDialog([browserWindow, ]options)

  • browserWindow BrowserWindow (optional)
  • options Object
    • title String (optional)
    • defaultPath String (optional)
    • buttonLabel String (optional) - Custom label for the confirmation button, when left empty the default label will be used.
    • filters FileFilter[] (optional)
    • properties String[] (optional) - Contains which features the dialog should use. The following values are supported:
      • openFile - Allow files to be selected.
      • openDirectory - Allow directories to be selected.
      • multiSelections - Allow multiple paths to be selected.
      • showHiddenFiles - Show hidden files in dialog.
      • createDirectory macOS - Allow creating new directories from dialog.
      • promptToCreate Windows - Prompt for creation if the file path entered in the dialog does not exist. This does not actually create the file at the path but allows non-existent paths to be returned that should be created by the application.
      • noResolveAliases macOS - Disable the automatic alias (symlink) path resolution. Selected aliases will now return the alias path instead of their target path.
      • treatPackageAsDirectory macOS - Treat packages, such as .app folders, as a directory instead of a file.
      • dontAddToRecent Windows - Do not add the item being opened to the recent documents list.
    • message String (optional) macOS - Message to display above input boxes.
    • securityScopedBookmarks Boolean (optional) macOS mas - Create security scoped bookmarks when packaged for the Mac App Store.

Returns Promise<Object> - Resolve with an object containing the following:

  • canceled Boolean - whether or not the dialog was canceled.
  • filePaths String[] - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array.
  • bookmarks String[] (optional) macOS mas - An array matching the filePaths array of base64 encoded strings which contains security scoped bookmark data. securityScopedBookmarks must be enabled for this to be populated. (For return values, see table here.)

The browserWindow argument allows the dialog to attach itself to a parent window, making it modal.

The filters specifies an array of file types that can be displayed or selected when you want to limit the user to a specific type. For example:

{
  filters: [
    { name: 'Images', extensions: ['jpg', 'png', 'gif'] },
    { name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
    { name: 'Custom File Type', extensions: ['as'] },
    { name: 'All Files', extensions: ['*'] }
  ]
}

The extensions array should contain extensions without wildcards or dots (e.g. 'png' is good but '.png' and '*.png' are bad). To show all files, use the '*' wildcard (no other wildcard is supported).

Note: On Windows and Linux an open dialog can not be both a file selector and a directory selector, so if you set properties to ['openFile', 'openDirectory'] on these platforms, a directory selector will be shown.

dialog.showOpenDialog(mainWindow, {
  properties: ['openFile', 'openDirectory']
}).then(result => {
  console.log(result.canceled)
  console.log(result.filePaths)
}).catch(err => {
  console.log(err)
})

dialog.showSaveDialogSync([browserWindow, ]options)

  • browserWindow BrowserWindow (optional)
  • options Object
    • title String (optional)
    • defaultPath String (optional) - Absolute directory path, absolute file path, or file name to use by default.
    • buttonLabel String (optional) - Custom label for the confirmation button, when left empty the default label will be used.
    • filters FileFilter[] (optional)
    • message String (optional) macOS - Message to display above text fields.
    • nameFieldLabel String (optional) macOS - Custom label for the text displayed in front of the filename text field.
    • showsTagField Boolean (optional) macOS - Show the tags input box, defaults to true.
    • properties String[] (optional)
      • showHiddenFiles - Show hidden files in dialog.
      • createDirectory macOS - Allow creating new directories from dialog.
      • treatPackageAsDirectory macOS - Treat packages, such as .app folders, as a directory instead of a file.
      • showOverwriteConfirmation Linux - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.
      • dontAddToRecent Windows - Do not add the item being saved to the recent documents list.
    • securityScopedBookmarks Boolean (optional) macOS mas - Create a security scoped bookmark when packaged for the Mac App Store. If this option is enabled and the file doesn't already exist a blank file will be created at the chosen path.

Returns String | undefined, the path of the file chosen by the user; if the dialog is cancelled it returns undefined.

The browserWindow argument allows the dialog to attach itself to a parent window, making it modal.

The filters specifies an array of file types that can be displayed, see dialog.showOpenDialog for an example.

dialog.showSaveDialog([browserWindow, ]options)

  • browserWindow BrowserWindow (optional)
  • options Object
    • title String (optional)
    • defaultPath String (optional) - Absolute directory path, absolute file path, or file name to use by default.
    • buttonLabel String (optional) - Custom label for the confirmation button, when left empty the default label will be used.
    • filters FileFilter[] (optional)
    • message String (optional) macOS - Message to display above text fields.
    • nameFieldLabel String (optional) macOS - Custom label for the text displayed in front of the filename text field.
    • showsTagField Boolean (optional) macOS - Show the tags input box, defaults to true.
    • properties String[] (optional)
      • showHiddenFiles - Show hidden files in dialog.
      • createDirectory macOS - Allow creating new directories from dialog.
      • treatPackageAsDirectory macOS - Treat packages, such as .app folders, as a directory instead of a file.
      • showOverwriteConfirmation Linux - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.
      • dontAddToRecent Windows - Do not add the item being saved to the recent documents list.
    • securityScopedBookmarks Boolean (optional) macOS mas - Create a security scoped bookmark when packaged for the Mac App Store. If this option is enabled and the file doesn't already exist a blank file will be created at the chosen path.

Returns Promise<Object> - Resolve with an object containing the following:

  • canceled Boolean - whether or not the dialog was canceled.
  • filePath String (optional) - If the dialog is canceled, this will be undefined.
  • bookmark String (optional) macOS mas - Base64 encoded string which contains the security scoped bookmark data for the saved file. securityScopedBookmarks must be enabled for this to be present. (For return values, see table here.)

The browserWindow argument allows the dialog to attach itself to a parent window, making it modal.

The filters specifies an array of file types that can be displayed, see dialog.showOpenDialog for an example.

Note: On macOS, using the asynchronous version is recommended to avoid issues when expanding and collapsing the dialog.

dialog.showMessageBoxSync([browserWindow, ]options)

  • browserWindow BrowserWindow (optional)
  • options Object
    • type String (optional) - Can be "none", "info", "error", "question" or "warning". On Windows, "question" displays the same icon as "info", unless you set an icon using the "icon" option. On macOS, both "warning" and "error" display the same warning icon.
    • buttons String[] (optional) - Array of texts for buttons. On Windows, an empty array will result in one button labeled "OK".
    • defaultId Integer (optional) - Index of the button in the buttons array which will be selected by default when the message box opens.
    • title String (optional) - Title of the message box, some platforms will not show it.
    • message String - Content of the message box.
    • detail String (optional) - Extra information of the message.
    • checkboxLabel String (optional) - If provided, the message box will include a checkbox with the given label.
    • checkboxChecked Boolean (optional) - Initial checked state of the checkbox. false by default.
    • icon (NativeImage | String) (optional)
    • cancelId Integer (optional) - The index of the button to be used to cancel the dialog, via the Esc key. By default this is assigned to the first button with "cancel" or "no" as the label. If no such labeled buttons exist and this option is not set, 0 will be used as the return value.
    • noLink Boolean (optional) - On Windows Electron will try to figure out which one of the buttons are common buttons (like "Cancel" or "Yes"), and show the others as command links in the dialog. This can make the dialog appear in the style of modern Windows apps. If you don't like this behavior, you can set noLink to true.
    • normalizeAccessKeys Boolean (optional) - Normalize the keyboard access keys across platforms. Default is false. 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 of Vie&w will be converted to Vie_w on Linux and View on macOS and can be selected via Alt-W on Windows and Linux.

Returns Integer - the index of the clicked button.

Shows a message box, it will block the process until the message box is closed. It returns the index of the clicked button.

The browserWindow argument allows the dialog to attach itself to a parent window, making it modal. If browserWindow is not shown dialog will not be attached to it. In such case it will be displayed as an independent window.

dialog.showMessageBox([browserWindow, ]options)

  • browserWindow BrowserWindow (optional)
  • options Object
    • type String (optional) - Can be "none", "info", "error", "question" or "warning". On Windows, "question" displays the same icon as "info", unless you set an icon using the "icon" option. On macOS, both "warning" and "error" display the same warning icon.
    • buttons String[] (optional) - Array of texts for buttons. On Windows, an empty array will result in one button labeled "OK".
    • defaultId Integer (optional) - Index of the button in the buttons array which will be selected by default when the message box opens.
    • title String (optional) - Title of the message box, some platforms will not show it.
    • message String - Content of the message box.
    • detail String (optional) - Extra information of the message.
    • checkboxLabel String (optional) - If provided, the message box will include a checkbox with the given label.
    • checkboxChecked Boolean (optional) - Initial checked state of the checkbox. false by default.
    • icon NativeImage (optional)
    • cancelId Integer (optional) - The index of the button to be used to cancel the dialog, via the Esc key. By default this is assigned to the first button with "cancel" or "no" as the label. If no such labeled buttons exist and this option is not set, 0 will be used as the return value.
    • noLink Boolean (optional) - On Windows Electron will try to figure out which one of the buttons are common buttons (like "Cancel" or "Yes"), and show the others as command links in the dialog. This can make the dialog appear in the style of modern Windows apps. If you don't like this behavior, you can set noLink to true.
    • normalizeAccessKeys Boolean (optional) - Normalize the keyboard access keys across platforms. Default is false. 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 of Vie&w will be converted to Vie_w on Linux and View on macOS and can be selected via Alt-W on Windows and Linux.

Returns Promise<Object> - resolves with a promise containing the following properties:

  • response Number - The index of the clicked button.
  • checkboxChecked Boolean - The checked state of the checkbox if checkboxLabel was set. Otherwise false.

Shows a message box, it will block the process until the message box is closed.

The browserWindow argument allows the dialog to attach itself to a parent window, making it modal.

dialog.showErrorBox(title, content)

  • title String - The title to display in the error box.
  • content String - The text content to display in the error box.

Displays a modal dialog that shows an error message.

This API can be called safely before the ready event the app module emits, it is usually used to report errors in early stage of startup. If called before the app readyevent on Linux, the message will be emitted to stderr, and no GUI dialog will appear.

dialog.showCertificateTrustDialog([browserWindow, ]options) macOS Windows

  • browserWindow BrowserWindow (optional)
  • options Object
    • certificate Certificate - The certificate to trust/import.
    • message String - The message to display to the user.

Returns Promise<void> - resolves when the certificate trust dialog is shown.

On macOS, this displays a modal dialog that shows a message and certificate information, and gives the user the option of trusting/importing the certificate. If you provide a browserWindow argument the dialog will be attached to the parent window, making it modal.

On Windows the options are more limited, due to the Win32 APIs used:

  • The message argument is not used, as the OS provides its own confirmation dialog.
  • The browserWindow argument is ignored since it is not possible to make this confirmation dialog modal.

Bookmarks array

showOpenDialog, showOpenDialogSync, showSaveDialog, and showSaveDialogSync will return a bookmarks array.

Build Type securityScopedBookmarks boolean Return Type Return Value
macOS mas True Success ['LONGBOOKMARKSTRING']
macOS mas True Error [''] (array of empty string)
macOS mas False NA [] (empty array)
non mas any NA [] (empty array)

Sheets

On macOS, dialogs are presented as sheets attached to a window if you provide a BrowserWindow reference in the browserWindow parameter, or modals if no window is provided.

You can call BrowserWindow.getCurrentWindow().setSheetOffset(offset) to change the offset from the window frame where sheets are attached.

Display Object

  • id Number - Unique identifier associated with the display.
  • rotation Number - Can be 0, 90, 180, 270, represents screen rotation in clock-wise degrees.
  • scaleFactor Number - Output device's pixel scale factor.
  • touchSupport String - Can be available, unavailable, unknown.
  • monochrome Boolean - Whether or not the display is a monochrome display.
  • accelerometerSupport String - Can be available, unavailable, unknown.
  • colorSpace String - represent a color space (three-dimensional object which contains all realizable color combinations) for the purpose of color conversions
  • colorDepth Number - The number of bits per pixel.
  • depthPerComponent Number - The number of bits per color component.
  • bounds Rectangle
  • size Size
  • workArea Rectangle
  • workAreaSize Size
  • internal Boolean - true for an internal display and false for an external display

The Display object represents a physical display connected to the system. A fake Display may exist on a headless system, or a Display may correspond to a remote, virtual display.

Class: Dock

Control your app in the macOS dock

Process: Main

The following example shows how to bounce your icon on the dock.

const { app } = require('electron')
app.dock.bounce()

Instance Methods

dock.bounce([type]) macOS

  • type String (optional) - Can be critical or informational. The default is informational

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.cancelBounce(id) macOS

  • id Integer

Cancel the bounce of id.

dock.downloadFinished(filePath) macOS

  • filePath String

Bounces the Downloads stack if the filePath is inside the Downloads folder.

dock.setBadge(text) macOS

  • text String

Sets the string to be displayed in the dock’s badging area.

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.setMenu(menu) macOS

Sets the application's [dock menu][dock-menu].

dock.getMenu() macOS

Returns Menu | null - The application's [dock menu][dock-menu].

dock.setIcon(image) macOS

Sets the image associated with this dock icon.

Class: DownloadItem

Control file downloads from remote sources.

Process: Main

DownloadItem is an EventEmitter that represents a download item in Electron. It is used in will-download event of Session class, and allows users to control the download item.

// In the main process.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.webContents.session.on('will-download', (event, item, webContents) => {
  // Set the save path, making Electron not to prompt a save dialog.
  item.setSavePath('/tmp/save.pdf')

  item.on('updated', (event, state) => {
    if (state === 'interrupted') {
      console.log('Download is interrupted but can be resumed')
    } else if (state === 'progressing') {
      if (item.isPaused()) {
        console.log('Download is paused')
      } else {
        console.log(`Received bytes: ${item.getReceivedBytes()}`)
      }
    }
  })
  item.once('done', (event, state) => {
    if (state === 'completed') {
      console.log('Download successfully')
    } else {
      console.log(`Download failed: ${state}`)
    }
  })
})

Instance Events

Event: 'updated'

Returns:

  • event Event
  • state String - Can be progressing or interrupted.

Emitted when the download has been updated and is not done.

The state can be one of following:

  • progressing - The download is in-progress.
  • interrupted - The download has interrupted and can be resumed.

Event: 'done'

Returns:

  • event Event
  • state String - Can be completed, cancelled or interrupted.

Emitted when the download is in a terminal state. This includes a completed download, a cancelled download (via downloadItem.cancel()), and interrupted download that can't be resumed.

The state can be one of following:

  • completed - The download completed successfully.
  • cancelled - The download has been cancelled.
  • interrupted - The download has interrupted and can not resume.

Instance Methods

The downloadItem object has the following methods:

downloadItem.setSavePath(path)

  • path String - Set the save file path of the download item.

The API is only available in session's will-download callback function. If user doesn't set the save path via the API, Electron will use the original routine to determine the save path; this usually prompts a save dialog.

downloadItem.getSavePath()

Returns String - The save path of the download item. This will be either the path set via downloadItem.setSavePath(path) or the path selected from the shown save dialog.

downloadItem.setSaveDialogOptions(options)

  • options SaveDialogOptions - Set the save file dialog options. This object has the same properties as the options parameter of dialog.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.

Instance Properties

downloadItem.savePath

A String property that determines the save file path of the download item.

The property is only available in session's will-download callback function. If user doesn't set the save path via the property, Electron will use the original routine to determine the save path; this usually prompts a save dialog.

Electron Release Timelines

  • The -beta.1 and stable dates are our solid release dates.
  • We strive for weekly beta releases, however we often release more betas than scheduled.
  • All dates are our goals but there may be reasons for adjusting the stable deadline, such as security bugs.
  • Take a look at the 5.0.0 Timeline blog post for info about publicizing our release dates.
  • Since Electron 6.0, we've been targeting every other Chromium version and releasing our stable on the same day as Chrome stable. You can reference Chromium's release schedule here. See Electron's new release cadence blog post for more details on our release schedule.
Version -beta.1 Stable Chrome Node
2.0.0 2018-02-21 2018-05-01 M61 v8.9
3.0.0 2018-06-21 2018-09-18 M66 v10.2
4.0.0 2018-10-11 2018-12-20 M69 v10.11
5.0.0 2019-01-22 2019-04-24 M73 v12.0
6.0.0 2019-05-01 2019-07-30 M76 v12.4
7.0.0 2019-08-01 2019-10-22 M78 v12.8
8.0.0 2019-10-24 2020-02-04 M80 v12.13
9.0.0 2020-02-06 2020-05-19 M83 v12.14
10.0.0 2020-05-21 2020-08-25 M85 v12.16
11.0.0 2020-08-27 2020-11-17 M87 v12.18
12.0.0 2020-11-19 2021-03-02 M89 v14.x

Electron Versioning

A detailed look at our versioning policy and implementation.

As of version 2.0.0, Electron follows semver. The following command will install the most recent stable build of Electron:

npm install --save-dev electron

To update an existing project to use the latest stable version:

npm install --save-dev [email protected]

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.

  1. Strict use of semver
  2. Introduction of semver-compliant -beta tags
  3. Introduction of conventional commit messages
  4. Well-defined stabilization branches
  5. The master branch is versionless; only stabilization branches contain version information

We will cover in detail how git branching works, how npm tagging works, what developers should expect to see, and how one can backport changes.

semver

From 2.0 onward, Electron will follow semver.

Below is a table explicitly mapping types of changes to their corresponding category of semver (e.g. Major, Minor, Patch).

Major Version Increments Minor Version Increments Patch Version Increments
Electron breaking API changes Electron non-breaking API changes Electron bug fixes
Node.js major version updates Node.js minor version updates Node.js patch version updates
Chromium version updates fix-related chromium patches

Note that most Chromium updates will be considered breaking. Fixes that can be backported will likely be cherry-picked as patches.

Stabilization Branches

Stabilization branches are branches that run parallel to master, taking in only cherry-picked commits that are related to security or stability. These branches are never merged back to master.

Since Electron 8, stabilization branches are always major version lines, and named against the following template $MAJOR-x-y e.g. 8-x-y. Prior to that we used minor version lines and named them as $MAJOR-$MINOR-x e.g. 2-0-x

We allow for multiple stabilization branches to exist simultaneously, and intend to support at least two in parallel at all times, backporting security fixes as necessary.

Older lines will not be supported by GitHub, but other groups can take ownership and backport stability and security fixes on their own. We discourage this, but recognize that it makes life easier for many app developers.

Beta Releases and Bug Fixes

Developers want to know which releases are safe to use. Even seemingly innocent features can introduce regressions in complex applications. At the same time, locking to a fixed version is dangerous because you’re ignoring security patches and bug fixes that may have come out since your version. Our goal is to allow the following standard semver ranges in package.json :

  • Use ~2.0.0 to admit only stability or security related fixes to your 2.0.0 release.
  • Use ^2.0.0 to admit non-breaking reasonably stable feature work as well as security and bug fixes.

What’s important about the second point is that apps using ^ should still be able to expect a reasonable level of stability. To accomplish this, semver allows for a pre-release identifier to indicate a particular version is not yet safe or stable.

Whatever you choose, you will periodically have to bump the version in your package.json as breaking changes are a fact of Chromium life.

The process is as follows:

  1. 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:
    1. The change is backwards API-compatible (deprecations are allowed)
    2. The risk to meeting our stability timeline must be low.
  2. 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.
  3. 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.
  4. 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:

  1. 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
  2. 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.
  3. Admitting features of any sort after Week 3 in the beta cycle is 👎 without a very good reason.

For each major and minor bump, you should expect to see something like the following:

2.0.0-beta.1
2.0.0-beta.2
2.0.0-beta.3
2.0.0
2.0.1
2.0.2

An example lifecycle in pictures:

  • A new release branch is created that includes the latest set of features. It is published as 2.0.0-beta.1.
  • A bug fix comes into master that can be backported to the release branch. The patch is applied, and a new beta is published as 2.0.0-beta.2.
  • The beta is considered generally stable and it is published again as a non-beta under 2.0.0.
  • Later, a zero-day exploit is revealed and a fix is applied to master. We backport the fix to the 2-0-x line and release 2.0.1.

A few examples of how various semver ranges will pick up new releases:

Missing Features: Alphas

Our strategy has a few tradeoffs, which for now we feel are appropriate. Most importantly that new features in master may take a while before reaching a stable release line. If you want to try a new feature immediately, you will have to build Electron yourself.

As a future consideration, we may introduce one or both of the following:

  • alpha releases that have looser stability constraints to betas; for example it would be allowable to admit new features while a stability channel is in alpha

Feature Flags

Feature flags are a common practice in Chromium, and are well-established in the web-development ecosystem. In the context of Electron, a feature flag or soft branch must have the following properties:

  • it is enabled/disabled either at runtime, or build-time; we do not support the concept of a request-scoped feature flag
  • it completely segments new and old code paths; refactoring old code to support a new feature violates the feature-flag contract
  • feature flags are eventually removed after the feature is released

Semantic Commits

We seek to increase clarity at all levels of the update and releases process. Starting with 2.0.0 we will require pull requests adhere to the Conventional Commits spec, which can be summarized as follows:

  • Commits that would result in a semver major bump must start their body with BREAKING CHANGE:.

  • Commits that would result in a semver minor bump must start with feat:.

  • Commits that would result in a semver patch bump must start with fix:.

  • We allow squashing of commits, provided that the squashed message adheres to the above message format.

  • It is acceptable for some commits in a pull request to not include a semantic prefix, as long as the pull request title contains a meaningful encompassing semantic message.

Versioned master

  • The master branch will always contain the next major version X.0.0-nightly.DATE in its package.json
  • Release branches are never merged back to master
  • Release branches do contain the correct version in their package.json
  • As soon as a release branch is cut for a major, master must be bumped to the next major. I.e. master is always versioned as the next theoretical release branch

Technical Differences Between Electron and NW.js

Like NW.js, Electron provides a platform to write desktop applications with web technologies. Both platforms enable developers to utilize HTML, JavaScript, and Node.js. On the surface, they seem very similar.

There are however fundamental differences between the two projects that make Electron a completely separate product from NW.js.

1) Entry of Application

In NW.js, the main entry point of an application can be an HTML web page. In that case, NW.js will open the given entry point in a browser window.

In Electron, the entry point is always a JavaScript script. Instead of providing a URL directly, you manually create a browser window and load an HTML file using the API. You also need to listen to window events to decide when to quit the application.

Electron works more like the Node.js runtime. Electron's APIs are lower level so you can use it for browser testing in place of PhantomJS.

2) Node Integration

In NW.js, the Node integration in web pages requires patching Chromium to work, while in Electron we chose a different way to integrate the libuv loop with each platform's message loop to avoid hacking Chromium. See the node_bindings code for how that was done.

3) JavaScript Contexts

If you are an experienced NW.js user, you should be familiar with the concept of Node context and web context. These concepts were invented because of how NW.js was implemented.

By using the multi-context feature of Node, Electron doesn't introduce a new JavaScript context in web pages.

Note: NW.js has optionally supported multi-context since 0.13.

4) Legacy Support

NW.js still offers a "legacy release" that supports Windows XP. It doesn't receive security updates.

Given that hardware manufacturers, Microsoft, Chromium, and Node.js haven't released even critical security updates for that system, we have to warn you that using Windows XP is wildly insecure and outright irresponsible.

However, we understand that requirements outside our wildest imagination may exist, so if you're looking for something like Electron that runs on Windows XP, the NW.js legacy release might be the right fit for you.

5) Features

There are numerous differences in the amount of supported features. Electron has a bigger community, more production apps using it, and a large amount of userland modules available on npm.

As an example, Electron has built-in support for automatic updates and countless tools that make the creation of installers easier. As an example in favor of NW.js, NW.js supports more Chrome.* APIs for the development of Chrome Apps.

Naturally, we believe that Electron is the better platform for polished production applications built with web technologies (like Visual Studio Code, Slack, or Facebook Messenger); however, we want to be fair to our web technology friends. If you have feature needs that Electron does not meet, you might want to try NW.js.

Environment Variables

Control application configuration and behavior without changing code.

Certain Electron behaviors are controlled by environment variables because they are initialized earlier than the command line flags and the app's code.

POSIX shell example:

$ export ELECTRON_ENABLE_LOGGING=true
$ electron

Windows console example:

> set ELECTRON_ENABLE_LOGGING=true
> electron

Production Variables

The following environment variables are intended primarily for use at runtime in packaged Electron applications.

NODE_OPTIONS

Electron includes support for a subset of Node's NODE_OPTIONS. The majority are supported with the exception of those which conflict with Chromium's use of BoringSSL.

Example:

export NODE_OPTIONS="--no-warnings --max-old-space-size=2048"

Unsupported options are:

--use-bundled-ca
--force-fips
--enable-fips
--openssl-config
--use-openssl-ca

NODE_OPTIONS are explicitly disallowed in packaged apps, except for the following:

--max-http-header-size
--http-parser

GOOGLE_API_KEY

Geolocation support in Electron requires the use of Google Cloud Platform's geolocation webservice. To enable this feature, acquire a Google API key and place the following code in your main process file, before opening any browser windows that will make geolocation requests:

process.env.GOOGLE_API_KEY = 'YOUR_KEY_HERE'

By default, a newly generated Google API key may not be allowed to make geolocation requests. To enable the geolocation webservice for your project, enable it through the API library.

N.B. You will need to add a Billing Account to the project associated to the API key for the geolocation webservice to work.

ELECTRON_NO_ASAR

Disables ASAR support. This variable is only supported in forked child processes and spawned child processes that set ELECTRON_RUN_AS_NODE.

ELECTRON_RUN_AS_NODE

Starts the process as a normal Node.js process.

In this mode, you will be able to pass cli options to Node.js as you would when running the normal Node.js executable, with the exception of the following flags:

  • "--openssl-config"
  • "--use-bundled-ca"
  • "--use-openssl-ca",
  • "--force-fips"
  • "--enable-fips"

These flags are disabled owing to the fact that Electron uses BoringSSL instead of OpenSSL when building Node.js' crypto module, and so will not work as designed.

ELECTRON_NO_ATTACH_CONSOLE Windows

Don't attach to the current console session.

ELECTRON_FORCE_WINDOW_MENU_BAR Linux

Don't use the global menu bar on Linux.

ELECTRON_TRASH Linux

Set the trash implementation on Linux. Default is gio.

Options:

  • gvfs-trash
  • trash-cli
  • kioclient5
  • kioclient

Development Variables

The following environment variables are intended primarily for development and debugging purposes.

ELECTRON_ENABLE_LOGGING

Prints Chrome's internal logging to the console.

ELECTRON_LOG_ASAR_READS

When Electron reads from an ASAR file, log the read offset and file path to the system tmpdir. The resulting file can be provided to the ASAR module to optimize file ordering.

ELECTRON_ENABLE_STACK_DUMPING

Prints the stack trace to the console when Electron crashes.

This environment variable will not work if the crashReporter is started.

ELECTRON_DEFAULT_ERROR_MODE Windows

Shows the Windows's crash dialog when Electron crashes.

This environment variable will not work if the crashReporter is started.

ELECTRON_OVERRIDE_DIST_PATH

When running from the electron package, this variable tells the electron command to use the specified build of Electron instead of the one downloaded by npm install. Usage:

export ELECTRON_OVERRIDE_DIST_PATH=/Users/username/projects/electron/out/Testing

Set By Electron

Electron sets some variables in your environment at runtime.

ORIGINAL_XDG_CURRENT_DESKTOP

This variable is set to the value of XDG_CURRENT_DESKTOP that your application originally launched with. Electron sometimes modifies the value of XDG_CURRENT_DESKTOP to affect other logic within Chromium so if you want access to the original value you should look up this environment variable instead.

Event Object extends GlobalEvent

  • preventDefault VoidFunction

Experimental APIs

Some of Electrons APIs are tagged with _Experimental_ in the documentation. This tag indicates that the API may not be considered stable and the API may be removed or modified more frequently than other APIs with less warning.

Conditions for an API to be tagged as Experimental

Anyone can request an API be tagged as experimental in a feature PR, disagreements on the experimental nature of a feature can be discussed in the API WG if they can't be resolved in the PR.

Process for removing the Experimental tag

Once an API has been stable and in at least two major stable release lines it can be nominated to have its experimental tag removed. This discussion should happen at an API WG meeting. Things to consider when discussing / nominating:

  • The above "two major stables release lines" condition must have been met
  • During that time no major bugs / issues should have been caused by the adoption of this feature
  • The API is stable enough and hasn't been heavily impacted by Chromium upgrades
  • Is anyone using the API?
  • Is the API fulfilling the original proposed usecases, does it have any gaps?

Extension Object

  • id String
  • manifest any - Copy of the extension's manifest data.
  • name String
  • path String - The extension's file path.
  • version String
  • url String - The extension's chrome-extension:// URL.

ExtensionInfo Object

  • name String
  • version String

Chrome Extension Support

Electron supports a subset of the Chrome Extensions API, primarily to support DevTools extensions and Chromium-internal extensions, but it also happens to support some other extension capabilities.

Note: Electron does not support arbitrary Chrome extensions from the store, and it is a non-goal of the Electron project to be perfectly compatible with Chrome's implementation of Extensions.

Loading extensions

Electron only supports loading unpacked extensions (i.e., .crx files do not work). Extensions are installed per-session. To load an extension, call ses.loadExtension:

const { session } = require('electron')

session.loadExtension('path/to/unpacked/extension').then(({ id }) => {
  // ...
})

Loaded extensions will not be automatically remembered across exits; if you do not call loadExtension when the app runs, the extension will not be loaded.

Note that loading extensions is only supported in persistent sessions. Attempting to load an extension into an in-memory session will throw an error.

See the session documentation for more information about loading, unloading, and querying active extensions.

Supported Extensions APIs

We support the following extensions APIs, with some caveats. Other APIs may additionally be supported, but support for any APIs not listed here is provisional and may be removed.

chrome.devtools.inspectedWindow

All features of this API are supported.

chrome.devtools.network

All features of this API are supported.

chrome.devtools.panels

All features of this API are supported.

chrome.extension

The following properties of chrome.extension are supported:

  • chrome.extension.lastError

The following methods of chrome.extension are supported:

  • chrome.extension.getURL
  • chrome.extension.getBackgroundPage

chrome.runtime

The following properties of chrome.runtime are supported:

  • chrome.runtime.lastError
  • chrome.runtime.id

The following methods of chrome.runtime are supported:

  • chrome.runtime.getBackgroundPage
  • chrome.runtime.getManifest
  • chrome.runtime.getURL
  • chrome.runtime.connect
  • chrome.runtime.sendMessage

The following events of chrome.runtime are supported:

  • chrome.runtime.onStartup
  • chrome.runtime.onInstalled
  • chrome.runtime.onSuspend
  • chrome.runtime.onSuspendCanceled
  • chrome.runtime.onConnect
  • chrome.runtime.onMessage

chrome.storage

Only chrome.storage.local is supported; chrome.storage.sync and chrome.storage.managed are not.

chrome.tabs

The following methods of chrome.tabs are supported:

  • chrome.tabs.sendMessage
  • chrome.tabs.executeScript

Note: In Chrome, passing -1 as a tab ID signifies the "currently active tab". Since Electron has no such concept, passing -1 as a tab ID is not supported and will raise an error.

chrome.management

The following methods of chrome.management are supported:

  • chrome.management.getAll
  • chrome.management.get
  • chrome.management.getSelf
  • chrome.management.getPermissionWarningsById
  • chrome.management.getPermissionWarningsByManifest
  • chrome.management.onEnabled
  • chrome.management.onDisabled

Electron FAQ

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:

subpixel rendering example

Sub-pixel anti-aliasing needs a non-transparent background of the layer containing the font glyphs. (See this issue for more info).

To achieve this goal, set the background in the constructor for BrowserWindow:

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
  backgroundColor: '#fff'
})

The effect is visible only on (some?) LCD screens. Even if you don't see a difference, some of your users may. It is best to always set the background this way, unless you have reasons not to do so.

Notice that just setting the background in the CSS does not have the desired effect.

FileFilter Object

  • name String
  • extensions String[]

File Object

Use the HTML5 File API to work natively with files on the filesystem.

The DOM's File interface provides abstraction around native files in order to let users work on native files directly with the HTML5 file API. Electron has added a path attribute to the File interface which exposes the file's real path on filesystem.

Example of getting a real path from a dragged-onto-the-app file:

<div id="holder">
  Drag your file here
</div>

<script>
  document.addEventListener('drop', (e) => {
    e.preventDefault();
    e.stopPropagation();

    for (const f of e.dataTransfer.files) {
      console.log('File(s) you dragged here: ', f.path)
    }
  });
  document.addEventListener('dragover', (e) => {
    e.preventDefault();
    e.stopPropagation();
  });
</script>

FilePathWithHeaders Object

  • path String - The path to the file to send.
  • headers Record<string, string> (optional) - Additional headers to be sent.

Frameless Window

Open a window without toolbars, borders, or other graphical "chrome".

A frameless window is a window that has no chrome, the parts of the window, like toolbars, that are not a part of the web page. These are options on the BrowserWindow class.

Create a frameless window

To create a frameless window, you need to set frame to false in BrowserWindow's options:

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600, frame: false })
win.show()

Alternatives on macOS

There's an alternative way to specify a chromeless window. Instead of setting frame to false which disables both the titlebar and window controls, you may want to have the title bar hidden and your content extend to the full window size, yet still preserve the window controls ("traffic lights") for standard window actions. You can do so by specifying the titleBarStyle option:

hidden

Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls (“traffic lights”) in the top left.

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hidden' })
win.show()

hiddenInset

Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge.

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
win.show()

customButtonsOnHover

Uses custom drawn close, and miniaturize buttons that display when hovering in the top left of the window. The fullscreen button is not available due to restrictions of frameless windows as they interface with Apple's macOS window masks. These custom buttons prevent issues with mouse events that occur with the standard window toolbar buttons. This option is only applicable for frameless windows.

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: false })
win.show()

Transparent window

By setting the transparent option to true, you can also make the frameless window transparent:

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ transparent: true, frame: false })
win.show()

Limitations

  • You can not click through the transparent area. We are going to introduce an API to set window shape to solve this, see our issue for details.
  • Transparent windows are not resizable. Setting resizable to true may make a transparent window stop working on some platforms.
  • The blur filter only applies to the web page, so there is no way to apply blur effect to the content below the window (i.e. other applications open on the user's system).
  • On Windows operating systems, transparent windows will not work when DWM is disabled.
  • On Linux, users have to put --enable-transparent-visuals --disable-gpu in the command line to disable GPU and allow ARGB to make transparent window, this is caused by an upstream bug that alpha channel doesn't work on some NVidia drivers on Linux.
  • On Mac, the native window shadow will not be shown on a transparent window.

Click-through window

To create a click-through window, i.e. making the window ignore all mouse events, you can call the win.setIgnoreMouseEvents(ignore) API:

const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.setIgnoreMouseEvents(true)

Forwarding

Ignoring mouse messages makes the web page oblivious to mouse movement, meaning that mouse movement events will not be emitted. On Windows operating systems an optional parameter can be used to forward mouse move messages to the web page, allowing events such as mouseleave to be emitted:

const win = require('electron').remote.getCurrentWindow()
const el = document.getElementById('clickThroughElement')
el.addEventListener('mouseenter', () => {
  win.setIgnoreMouseEvents(true, { forward: true })
})
el.addEventListener('mouseleave', () => {
  win.setIgnoreMouseEvents(false)
})

This makes the web page click-through when over el, and returns to normal outside it.

Draggable region

By default, the frameless window is non-draggable. Apps need to specify -webkit-app-region: drag in CSS to tell Electron which regions are draggable (like the OS's standard titlebar), and apps can also use -webkit-app-region: no-drag to exclude the non-draggable area from the draggable region. Note that only rectangular shapes are currently supported.

Note: -webkit-app-region: drag is known to have problems while the developer tools are open. See this GitHub issue for more information including a workaround.

To make the whole window draggable, you can add -webkit-app-region: drag as body's style:

<body style="-webkit-app-region: drag">
</body>

And note that if you have made the whole window draggable, you must also mark buttons as non-draggable, otherwise it would be impossible for users to click on them:

button {
  -webkit-app-region: no-drag;
}

If you're only setting a custom titlebar as draggable, you also need to make all buttons in titlebar non-draggable.

Text selection

In a frameless window the dragging behavior may conflict with selecting text. For example, when you drag the titlebar you may accidentally select the text on the titlebar. To prevent this, you need to disable text selection within a draggable area like this:

.titlebar {
  -webkit-user-select: none;
  -webkit-app-region: drag;
}

Context menu

On some platforms, the draggable area will be treated as a non-client frame, so when you right click on it a system menu will pop up. To make the context menu behave correctly on all platforms you should never use a custom context menu on draggable areas.

Electron Fuses

Package time feature toggles

What are fuses?

For a subset of Electron functionality it makes sense to disable certain features for an entire application. For example, 99% of apps don't make use of ELECTRON_RUN_AS_NODE, these applications want to be able to ship a binary that is incapable of using that feature. We also don't want Electron consumers building Electron from source as that is both a massive technical challenge and has a high cost of both time and money.

Fuses are the solution to this problem, at a high level they are "magic bits" in the Electron binary that can be flipped when packaging your Electron app to enable / disable certain features / restrictions. Because they are flipped at package time before you code sign your app the OS becomes responsible for ensuring those bits aren't flipped back via OS level code signing validation (Gatekeeper / App Locker).

How do I flip the fuses?

The easy way

We've made a handy module @electron/fuses to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases.

require('@electron/fuses').flipFuses(
  // Path to electron
  require('electron'),
  // Fuses to flip
  {
    runAsNode: false
  }
)

The hard way

Quick Glossary

  • Fuse Wire: A sequence of bytes in the Electron binary used to control the fuses
  • Sentinel: A static known sequence of bytes you can use to locate the fuse wire
  • Fuse Schema: The format / allowed values for the fuse wire

Manually flipping fuses requires editing the Electron binary and modifying the fuse wire to be the sequence of bytes that represent the state of the fuses you want.

Somewhere in the Electron binary there will be a sequence of bytes that look like this:

| ...binary | sentinel_bytes | fuse_version | fuse_wire_length | fuse_wire | ...binary |
  • sentinel_bytes is always this exact string dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX
  • fuse_version is a single byte whose unsigned integer value represents the version of the fuse schema
  • fuse_wire_length is a single byte whose unsigned integer value represents the number of fuses in the following fuse wire
  • fuse_wire is a sequence of N bytes, each byte represents a single fuse and its state.
    • "0" (0x30) indicates the fuse is disabled
    • "1" (0x31) indicates the fuse is enabled
    • "r" (0x72) indicates the fuse has been removed and changing the byte to either 1 or 0 will have no effect.

To flip a fuse you find its position in the fuse wire and change it to "0" or "1" depending on the state you'd like.

You can view the current schema here.

globalShortcut

Detect keyboard events when the application does not have keyboard focus.

Process: Main

The globalShortcut module can register/unregister a global keyboard shortcut with the operating system so that you can customize the operations for various shortcuts.

Note: The shortcut is global; it will work even if the app does not have the keyboard focus. 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)

Returns Boolean - Whether or not the shortcut was registered successfully.

Registers a global shortcut of accelerator. The callback is called when the registered shortcut is pressed by the user.

When the accelerator is already taken by other applications, this call will silently fail. This behavior is intended by operating systems, since they don't want applications to fight for global shortcuts.

The following accelerators will not be registered successfully on macOS 10.14 Mojave unless the app has been authorized as a trusted accessibility client:

  • "Media Play/Pause"
  • "Media Next Track"
  • "Media Previous Track"
  • "Media Stop"

globalShortcut.registerAll(accelerators, callback)

  • accelerators String[] - an array of Accelerators.
  • callback Function

Registers a global shortcut of all accelerator items in accelerators. The callback is called when any of the registered shortcuts are pressed by the user.

When a given accelerator is already taken by other applications, this call will silently fail. This behavior is intended by operating systems, since they don't want applications to fight for global shortcuts.

The following accelerators will not be registered successfully on macOS 10.14 Mojave unless the app has been authorized as a trusted accessibility client:

  • "Media Play/Pause"
  • "Media Next Track"
  • "Media Previous Track"
  • "Media Stop"

globalShortcut.isRegistered(accelerator)

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)

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_canvas String - Canvas.
  • flash_3d String - Flash.
  • flash_stage3d String - Flash Stage3D.
  • flash_stage3d_baseline String - Flash Stage3D Baseline profile.
  • gpu_compositing String - Compositing.
  • multiple_raster_threads String - Multiple Raster Threads.
  • native_gpu_memory_buffers String - Native GpuMemoryBuffers.
  • rasterization String - Rasterization.
  • video_decode String - Video Decode.
  • video_encode String - Video Encode.
  • vpx_decode String - VPx Video Decode.
  • webgl String - WebGL.
  • webgl2 String - WebGL2.

Possible values:

  • disabled_software - Software only. Hardware acceleration disabled (yellow)
  • disabled_off - Disabled (red)
  • disabled_off_ok - Disabled (yellow)
  • unavailable_software - Software only, hardware acceleration unavailable (yellow)
  • unavailable_off - Unavailable (red)
  • unavailable_off_ok - Unavailable (yellow)
  • enabled_readback - Hardware accelerated but at reduced performance (yellow)
  • enabled_force - Hardware accelerated on all pages (green)
  • enabled - Hardware accelerated (green)
  • enabled_on - Enabled (green)
  • enabled_force_on - Force enabled (green)

inAppPurchase

In-app purchases on Mac App Store.

Process: Main

Events

The inAppPurchase module emits the following events:

Event: 'transactions-updated'

Emitted when one or more transactions have been updated.

Returns:

  • event Event
  • transactions Transaction[] - Array of Transaction objects.

Methods

The inAppPurchase module has the following methods:

inAppPurchase.purchaseProduct(productID[, quantity])

  • productID String - The identifiers of the product to purchase. (The identifier of com.example.app.product1 is product1).
  • quantity Integer (optional) - The number of items the user wants to purchase.

Returns Promise<Boolean> - Returns true if the product is valid and added to the payment queue.

You should listen for the transactions-updated event as soon as possible and certainly before you call purchaseProduct.

inAppPurchase.getProducts(productIDs)

  • productIDs String[] - The identifiers of the products to get.

Returns Promise<Product[]> - Resolves with an array of Product objects.

Retrieves the product descriptions.

inAppPurchase.canMakePayments()

Returns Boolean - whether a user can make a payment.

inAppPurchase.restoreCompletedTransactions()

Restores finished transactions. This method can be called either to install purchases on additional devices, or to restore purchases for an application that the user deleted and reinstalled.

The payment queue delivers a new transaction for each previously completed transaction that can be restored. Each transaction includes a copy of the original transaction.

inAppPurchase.getReceiptURL()

Returns String - the path to the receipt.

inAppPurchase.finishAllTransactions()

Completes all pending transactions.

inAppPurchase.finishTransactionByDate(date)

  • date String - The ISO formatted date of the transaction to finish.

Completes the pending transactions corresponding to the date.

In-App Purchase (macOS)

Preparing

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.

iTunes Connect Developer Help: Create an 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.

Instance Events

Event: 'data'

Returns:

  • chunk Buffer - A chunk of response body's data.

The data event is the usual method of transferring response data into applicative code.

Event: 'end'

Indicates that response body has ended.

Event: 'aborted'

Emitted when a request has been canceled during an ongoing HTTP transaction.

Event: 'error'

Returns:

error Error - Typically holds an error string identifying failure root cause.

Emitted when an error was encountered while streaming response data events. For instance, if the server closes the underlying while the response is still streaming, an error event will be emitted on the response object and a close event will subsequently follow on the request object.

Instance Properties

An IncomingMessage instance has the following readable properties:

response.statusCode

An Integer indicating the HTTP response status code.

response.statusMessage

A String representing the HTTP status message.

response.headers

A Record<string, string | string[]> representing the HTTP response headers. The headers object is formatted as follows:

  • All header names are lowercased.
  • Duplicates of age, authorization, content-length, content-type, etag, expires, from, host, if-modified-since, if-unmodified-since, last-modified, location, max-forwards, proxy-authorization, referer, retry-after, server, or user-agent are discarded.
  • set-cookie is always an array. Duplicates are added to the array.
  • For duplicate cookie headers, the values are joined together with '; '.
  • For all other headers, the values are joined together with ', '.

response.httpVersion

A String indicating the HTTP protocol version number. Typical values are '1.0' or '1.1'. Additionally httpVersionMajor and httpVersionMinor are two Integer-valued readable properties that return respectively the HTTP major and minor version numbers.

response.httpVersionMajor

An Integer indicating the HTTP protocol major version number.

response.httpVersionMinor

An Integer indicating the HTTP protocol minor version number.

InputEvent Object

  • modifiers String[] (optional) - An array of modifiers of the event, can be shift, control, ctrl, alt, meta, command, cmd, isKeypad, isAutoRepeat, leftButtonDown, middleButtonDown, rightButtonDown, capsLock, numLock, left, right.

Installation

To install prebuilt Electron binaries, use npm. The preferred method is to install Electron as a development dependency in your app:

npm install electron --save-dev

See the Electron versioning doc for info on how to manage Electron versions in your apps.

Global Installation

You can also install the electron command globally in your $PATH:

npm install electron -g

Customization

If you want to change the architecture that is downloaded (e.g., ia32 on an x64 machine), you can use the --arch flag with npm install or set the npm_config_arch environment variable:

npm install --arch=ia32 electron

In addition to changing the architecture, you can also specify the platform (e.g., win32, linux, etc.) using the --platform flag:

npm install --platform=win32 electron

Proxies

If you need to use an HTTP proxy, you need to set the ELECTRON_GET_USE_PROXY variable to any value, plus additional environment variables depending on your host system's Node version:

Custom Mirrors and Caches

During installation, the electron module will call out to @electron/get to download prebuilt binaries of Electron for your platform. It will do so by contacting GitHub's release download page (https://github.com/electron/electron/releases/tag/v$VERSION, where $VERSION is the exact version of Electron).

If you are unable to access GitHub or you need to provide a custom build, you can do so by either providing a mirror or an existing cache directory.

Mirror

You can use environment variables to override the base URL, the path at which to look for Electron binaries, and the binary filename. The URL used by @electron/get is composed as follows:

url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME

For instance, to use the China CDN mirror:

ELECTRON_MIRROR="https://cdn.npm.taobao.org/dist/electron/"

By default, ELECTRON_CUSTOM_DIR is set to v$VERSION. To change the format, use the {{ version }} placeholder. For example, version-{{ version }} resolves to version-5.0.0, {{ version }} resolves to 5.0.0, and v{{ version }} is equivalent to the default. As a more concrete example, to use the China non-CDN mirror:

ELECTRON_MIRROR="https://npm.taobao.org/mirrors/electron/"
ELECTRON_CUSTOM_DIR="{{ version }}"

The above configuration will download from URLs such as https://npm.taobao.org/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip.

Cache

Alternatively, you can override the local cache. @electron/get will cache downloaded binaries in a local directory to not stress your network. You can use that cache folder to provide custom builds of Electron or to avoid making contact with the network at all.

  • Linux: $XDG_CACHE_HOME or ~/.cache/electron/
  • macOS: ~/Library/Caches/electron/
  • Windows: $LOCALAPPDATA/electron/Cache or ~/AppData/Local/electron/Cache/

On environments that have been using older versions of Electron, you might find the cache also in ~/.electron.

You can also override the local cache location by providing a electron_config_cache environment variable.

The cache contains the version's official zip file as well as a checksum, stored as a text file. A typical cache might look like this:

├── httpsgithub.comelectronelectronreleasesdownloadv1.7.9electron-v1.7.9-darwin-x64.zip
│   └── electron-v1.7.9-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.7.9SHASUMS256.txt
│   └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.1electron-v1.8.1-darwin-x64.zip
│   └── electron-v1.8.1-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.1SHASUMS256.txt
│   └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.1electron-v1.8.2-beta.1-darwin-x64.zip
│   └── electron-v1.8.2-beta.1-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.1SHASUMS256.txt
│   └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.2electron-v1.8.2-beta.2-darwin-x64.zip
│   └── electron-v1.8.2-beta.2-darwin-x64.zip
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.2SHASUMS256.txt
│   └── SHASUMS256.txt
├── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.3electron-v1.8.2-beta.3-darwin-x64.zip
│   └── electron-v1.8.2-beta.3-darwin-x64.zip
└── httpsgithub.comelectronelectronreleasesdownloadv1.8.2-beta.3SHASUMS256.txt
    └── SHASUMS256.txt

Skip binary download

When installing the electron NPM package, it automatically downloads the electron binary.

This can sometimes be unnecessary, e.g. in a CI environment, when testing another component.

To prevent the binary from being downloaded when you install all npm dependencies you can set the environment variable ELECTRON_SKIP_BINARY_DOWNLOAD. E.g.:

ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install

Troubleshooting

When running npm install electron, some users occasionally encounter installation errors.

In almost all cases, these errors are the result of network problems and not actual issues with the electron npm package. Errors like ELIFECYCLE, EAI_AGAIN, ECONNRESET, and ETIMEDOUT are all indications of such network problems. The best resolution is to try switching networks, or wait a bit and try installing again.

You can also attempt to download Electron directly from electron/electron/releases if installing via npm is failing.

If installation fails with an EACCESS error you may need to fix your npm permissions.

If the above error persists, the unsafe-perm flag may need to be set to true:

sudo npm install electron --unsafe-perm=true

On slower networks, it may be advisable to use the --verbose flag in order to show download progress:

npm install --verbose electron

If you need to force a re-download of the asset and the SHASUM file set the force_no_cache environment variable to true.

IOCounters Object

  • readOperationCount Number - The number of I/O read operations.
  • writeOperationCount Number - The number of I/O write operations.
  • otherOperationCount Number - Then number of I/O other operations.
  • readTransferCount Number - The number of I/O read transfers.
  • writeTransferCount Number - The number of I/O write transfers.
  • otherTransferCount Number - Then number of I/O other transfers.

ipcMain

Communicate asynchronously from the main process to renderer processes.

Process: Main

The ipcMain module is an Event Emitter. When used in the main process, it handles asynchronous and synchronous messages sent from a renderer process (web page). Messages sent from a renderer will be emitted to this module.

Sending Messages

It is also possible to send messages from the main process to the renderer process, see webContents.send for more information.

  • When sending a message, the event name is the channel.
  • To reply to a synchronous message, you need to set event.returnValue.
  • To send an asynchronous message back to the sender, you can use event.reply(...). This helper method will automatically handle messages coming from frames that aren't the main frame (e.g. iframes) whereas event.sender.send(...) will always send to the main frame.

An example of sending and handling messages between the render and main processes:

// In main process.
const { ipcMain } = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
  console.log(arg) // prints "ping"
  event.reply('asynchronous-reply', 'pong')
})

ipcMain.on('synchronous-message', (event, arg) => {
  console.log(arg) // prints "ping"
  event.returnValue = 'pong'
})
// In renderer process (web page).
const { ipcRenderer } = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"

ipcRenderer.on('asynchronous-reply', (event, arg) => {
  console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')

Methods

The ipcMain module has the following method to listen for events:

ipcMain.on(channel, listener)

  • channel String
  • listener Function
    • event IpcMainEvent
    • ...args any[]

Listens to channel, when a new message arrives listener would be called with listener(event, args...).

ipcMain.once(channel, listener)

  • channel String
  • listener Function
    • event IpcMainEvent
    • ...args any[]

Adds a one time listener function for the event. This listener is invoked only the next time a message is sent to channel, after which it is removed.

ipcMain.removeListener(channel, listener)

  • channel String
  • listener Function
    • ...args any[]

Removes the specified listener from the listener array for the specified channel.

ipcMain.removeAllListeners([channel])

  • channel String (optional)

Removes listeners of the specified channel.

ipcMain.handle(channel, listener)

  • channel String
  • listener Function<Promise\ | any>
    • event IpcMainInvokeEvent
    • ...args any[]

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)

  • channel String
  • listener Function<Promise\ | any>
    • event IpcMainInvokeEvent
    • ...args any[]

Handles a single invokeable IPC message, then removes the listener. See ipcMain.handle(channel, listener).

ipcMain.removeHandler(channel)

  • channel String

Removes any handler for channel, if present.

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

  • frameId Integer - The ID of the renderer frame that sent this message
  • returnValue any - Set this to the value to be returned in a synchronous message
  • sender WebContents - Returns the webContents that sent the message
  • ports MessagePortMain[] - A list of MessagePorts that were transferred with this message
  • reply Function - A function that will send an IPC message to the renderer frame that sent the original message that you are currently handling. You should use this method to "reply" to the sent message in order to guarantee the reply will go to the correct process and frame.
    • channel String
    • ...args any[]

IpcMainInvokeEvent Object extends Event

  • frameId Integer - The ID of the renderer frame that sent this message
  • sender WebContents - Returns the webContents that sent the message

ipcRenderer

Communicate asynchronously from a renderer process to the main process.

Process: Renderer

The ipcRenderer module is an EventEmitter. It provides a few methods so you can send synchronous and asynchronous messages from the render process (web page) to the main process. You can also receive replies from the main process.

See ipcMain for code examples.

Methods

The ipcRenderer module has the following method to listen for events and send messages:

ipcRenderer.on(channel, listener)

  • channel String
  • listener Function
    • event IpcRendererEvent
    • ...args any[]

Listens to channel, when a new message arrives listener would be called with listener(event, args...).

ipcRenderer.once(channel, listener)

  • channel String
  • listener Function
    • event IpcRendererEvent
    • ...args any[]

Adds a one time listener function for the event. This listener is invoked only the next time a message is sent to channel, after which it is removed.

ipcRenderer.removeListener(channel, listener)

  • channel String
  • listener Function
    • ...args any[]

Removes the specified listener from the listener array for the specified channel.

ipcRenderer.removeAllListeners(channel)

  • channel String

Removes all listeners, or those of the specified channel.

ipcRenderer.send(channel, ...args)

  • channel String
  • ...args any[]

Send an asynchronous message to the main process via channel, along with arguments. Arguments will be serialized with the Structured Clone Algorithm, just like window.postMessage, so prototype chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.

NOTE: Sending non-standard JavaScript types such as DOM objects or special Electron objects is deprecated, and will begin throwing an exception starting with Electron 9.

The main process handles it by listening for channel with the ipcMain module.

If you need to transfer a MessagePort to the main process, use ipcRenderer.postMessage.

If you want to receive a single response from the main process, like the result of a method call, consider using ipcRenderer.invoke.

ipcRenderer.invoke(channel, ...args)

  • channel String
  • ...args any[]

Returns Promise<any> - Resolves with the response from the main process.

Send a message to the main process via channel and expect a result asynchronously. Arguments will be serialized with the Structured Clone Algorithm, just like window.postMessage, so prototype chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.

NOTE: Sending non-standard JavaScript types such as DOM objects or special Electron objects is deprecated, and will begin throwing an exception starting with Electron 9.

The main process should listen for channel with ipcMain.handle().

For example:

// Renderer process
ipcRenderer.invoke('some-name', someArgument).then((result) => {
  // ...
})

// Main process
ipcMain.handle('some-name', async (event, someArgument) => {
  const result = await doSomeWork(someArgument)
  return result
})

If you need to transfer a MessagePort to the main process, use ipcRenderer.postMessage.

If you do not need a response to the message, consider using ipcRenderer.send.

ipcRenderer.sendSync(channel, ...args)

  • channel String
  • ...args any[]

Returns any - The value sent back by the ipcMain handler.

Send a message to the main process via channel and expect a result synchronously. Arguments will be serialized with the Structured Clone Algorithm, just like window.postMessage, so prototype chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.

NOTE: Sending non-standard JavaScript types such as DOM objects or special Electron objects is deprecated, and will begin throwing an exception starting with Electron 9.

The main process handles it by listening for channel with ipcMain module, and replies by setting event.returnValue.

⚠️ WARNING: Sending a synchronous message will block the whole renderer process until the reply is received, so use this method only as a last resort. It's much better to use the asynchronous version, invoke().

ipcRenderer.postMessage(channel, message, [transfer])

  • channel String
  • message any
  • transfer MessagePort[] (optional)

Send a message to the main process, optionally transferring ownership of zero or more MessagePort objects.

The transferred MessagePort objects will be available in the main process as MessagePortMain objects by accessing the ports property of the emitted event.

For example:

// Renderer process
const { port1, port2 } = new MessageChannel()
ipcRenderer.postMessage('port', { message: 'hello' }, [port1])

// Main process
ipcMain.on('port', (e, msg) => {
  const [port] = e.ports
  // ...
})

For more information on using MessagePort and MessageChannel, see the MDN documentation.

ipcRenderer.sendTo(webContentsId, channel, ...args)

  • webContentsId Number
  • channel String
  • ...args any[]

Sends a message to a window with webContentsId via channel.

ipcRenderer.sendToHost(channel, ...args)

  • channel String
  • ...args any[]

Like ipcRenderer.send but the event will be sent to the <webview> element in the host page instead of the main process.

Event object

The documentation for the event object passed to the callback can be found in the ipc-renderer-event structure docs.

IpcRendererEvent Object extends Event

  • sender IpcRenderer - The IpcRenderer instance that emitted the event originally
  • senderId Integer - The webContents.id that sent the message, you can call event.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 set event.senderId to 0.
  • ports MessagePort[] - A list of MessagePorts that were transferred with this message

Issues In Electron

How to Contribute to Issues

For any issue, there are fundamentally three ways an individual can contribute:

  1. By opening the issue for discussion: If you believe that you have found a new bug in Electron, you should report it by creating a new issue in the electron/electron issue tracker.
  2. 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.
  3. By helping to resolve the issue: This can be done by demonstrating that the issue is not a bug or is fixed; but more often, by opening a pull request that changes the source in electron/electron in a concrete and reviewable manner.

Asking for General Help

"Finding Support" has a list of resources for getting programming help, reporting security issues, contributing, and more. Please use the issue tracker for bugs only!

Submitting a Bug Report

To submit a bug report:

When opening a new issue in the electron/electron issue tracker, users will be presented with a template that should be filled in.

If you believe that you have found a bug in Electron, please fill out the template to the best of your ability.

The two most important pieces of information needed to evaluate the report are a description of the bug and a simple test case to recreate it. It is easier to fix a bug if it can be reproduced.

See How to create a Minimal, Complete, and Verifiable example.

Triaging a Bug Report

It's common for open issues to involve discussion. Some contributors may have differing opinions, including whether the behavior is a bug or feature. This discussion is part of the process and should be kept focused, helpful, and professional.

Terse responses that provide neither additional context nor supporting detail are not helpful or professional. To many, such responses are annoying and unfriendly.

Contributors are encouraged to solve issues collaboratively and help one another make progress. If you encounter an issue that you feel is invalid, or which contains incorrect information, explain why you feel that way with additional supporting context, and be willing to be convinced that you may be wrong. By doing so, we can often reach the correct outcome faster.

Resolving a Bug Report

Most issues are resolved by opening a pull request. The process for opening and reviewing a pull request is similar to that of opening and triaging issues, but carries with it a necessary review and approval workflow that ensures that the proposed changes meet the minimal quality and functional guidelines of the Electron project.

JumpListCategory Object

  • type String (optional) - One of the following:
    • tasks - Items in this category will be placed into the standard Tasks category. There can be only one such category, and it will always be displayed at the bottom of the Jump List.
    • frequent - Displays a list of files frequently opened by the app, the name of the category and its items are set by Windows.
    • recent - Displays a list of files recently opened by the app, the name of the category and its items are set by Windows. Items may be added to this category indirectly using app.addRecentDocument(path).
    • custom - Displays tasks or file links, name must be set by the app.
  • name String (optional) - Must be set if type is custom, otherwise it should be omitted.
  • items JumpListItem[] (optional) - Array of JumpListItem objects if type is tasks or custom, otherwise it should be omitted.

Note: If a JumpListCategory object has neither the type nor the name property set then its type is assumed to be tasks. If the name property is set but the type property is omitted then the type is assumed to be custom.

JumpListItem Object

  • type String (optional) - One of the following:
    • task - A task will launch an app with specific arguments.
    • separator - Can be used to separate items in the standard Tasks category.
    • file - A file link will open a file using the app that created the Jump List, for this to work the app must be registered as a handler for the file type (though it doesn't have to be the default handler).
  • path String (optional) - Path of the file to open, should only be set if type is file.
  • program String (optional) - Path of the program to execute, usually you should specify process.execPath which opens the current program. Should only be set if type is task.
  • args String (optional) - The command line arguments when program is executed. Should only be set if type is task.
  • title String (optional) - The text to be displayed for the item in the Jump List. Should only be set if type is task.
  • description String (optional) - Description of the task (displayed in a tooltip). Should only be set if type is task.
  • iconPath String (optional) - The absolute path to an icon to be displayed in a Jump List, which can be an arbitrary resource file that contains an icon (e.g. .ico, .exe, .dll). You can usually specify process.execPath to show the program icon.
  • iconIndex Number (optional) - The index of the icon in the resource file. If a resource file contains multiple icons this value can be used to specify the zero-based index of the icon that should be displayed for this task. If a resource file contains only one icon, this property should be set to zero.
  • workingDirectory String (optional) - The working directory. Default is empty.

KeyboardEvent Object

  • ctrlKey Boolean (optional) - whether the Control key was used in an accelerator to trigger the Event
  • metaKey Boolean (optional) - whether a meta key was used in an accelerator to trigger the Event
  • shiftKey Boolean (optional) - whether a Shift key was used in an accelerator to trigger the Event
  • altKey Boolean (optional) - whether an Alt key was used in an accelerator to trigger the Event
  • triggeredByAccelerator Boolean (optional) - whether an accelerator was used to trigger the event as opposed to another user gesture like mouse click

KeyboardInputEvent Object extends InputEvent

  • type String - The type of the event, can be keyDown, keyUp or char.
  • keyCode String - The character that will be sent as the keyboard event. Should only use the valid key codes in Accelerator.

Keyboard Shortcuts

Overview

This feature allows you to configure local and global keyboard shortcuts for your Electron application.

Example

Local Shortcuts

Local keyboard shortcuts are triggered only when the application is focused. To configure a local keyboard shortcut, you need to specify an accelerator property when creating a MenuItem within the Menu module.

Starting with a working application from the Quick Start Guide, update the main.js file with the following lines:

const { Menu, MenuItem } = require('electron')

const menu = new Menu()
menu.append(new MenuItem({
  label: 'Electron',
  submenu: [{
    role: 'help',
    accelerator: process.platform === 'darwin' ? 'Alt+Cmd+I' : 'Alt+Shift+I',
    click: () => { console.log('Electron rocks!') }
  }]
}))

Menu.setApplicationMenu(menu)

NOTE: In the code above, you can see that the accelerator differs based on the user's operating system. For MacOS, it is Alt+Cmd+I, whereas for Linux and Windows, it is Alt+Shift+I.

After launching the Electron application, you should see the application menu along with the local shortcut you just defined:

Menu with a local shortcut

If you click Help or press the defined accelerator and then open the terminal that you ran your Electron application from, you will see the message that was generated after triggering the click event: "Electron rocks!".

Global Shortcuts

To configure a global keyboard shortcut, you need to use the globalShortcut module to detect keyboard events even when the application does not have keyboard focus.

Starting with a working application from the Quick Start Guide, update the main.js file with the following lines:

const { app, globalShortcut } = require('electron')

app.whenReady().then(() => {
  globalShortcut.register('Alt+CommandOrControl+I', () => {
    console.log('Electron loves global shortcuts!')
  })
}).then(createWindow)

NOTE: In the code above, the CommandOrControl combination uses Command on macOS and Control on Windows/Linux.

After launching the Electron application, if you press the defined key combination then open the terminal that you ran your Electron application from, you will see that Electron loves global shortcuts!

Shortcuts within a BrowserWindow

Using web APIs

If you want to handle keyboard shortcuts within a BrowserWindow, you can listen for the keyup and keydown DOM events inside the renderer process using the addEventListener() API.

window.addEventListener('keyup', doSomething, true)

Note the third parameter true indicates that the listener will always receive key presses before other listeners so they can't have stopPropagation() called on them.

Intercepting events in the main process

The before-input-event event is emitted before dispatching keydown and keyup events in the page. It can be used to catch and handle custom shortcuts that are not visible in the menu.

Example

Starting with a working application from the Quick Start Guide, update the main.js file with the following lines:

const { app, BrowserWindow } = require('electron')

app.whenReady().then(() => {
  const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } })

  win.loadFile('index.html')
  win.webContents.on('before-input-event', (event, input) => {
    if (input.control && input.key.toLowerCase() === 'i') {
      console.log('Pressed Control+I')
      event.preventDefault()
    }
  })
})

After launching the Electron application, if you open the terminal that you ran your Electron application from and press Ctrl+I key combination, you will see that this key combination was successfully intercepted.

Using third-party libraries

If you don't want to do manual shortcut parsing, there are libraries that do advanced key detection, such as mousetrap. Below are examples of usage of the mousetrap running in the Renderer process:

Mousetrap.bind('4', () => { console.log('4') })
Mousetrap.bind('?', () => { console.log('show shortcuts!') })
Mousetrap.bind('esc', () => { console.log('escape') }, 'keyup')

// combinations
Mousetrap.bind('command+shift+k', () => { console.log('command shift k') })

// map multiple combinations to the same callback
Mousetrap.bind(['command+k', 'ctrl+k'], () => {
  console.log('command k or control k')

  // return false to prevent default behavior and stop event from bubbling
  return false
})

// gmail style sequences
Mousetrap.bind('g i', () => { console.log('go to inbox') })
Mousetrap.bind('* a', () => { console.log('select all') })

// konami code!
Mousetrap.bind('up up down down left right left right b a enter', () => {
  console.log('konami code')
})

Custom Linux Desktop Launcher Actions

Overview

On many Linux environments, you can add custom entries to the system launcher by modifying the .desktop file. For Canonical's Unity documentation, see Adding Shortcuts to a Launcher. For details on a more generic implementation, see the freedesktop.org Specification.