2013-09-09 07:35:57 +00:00
|
|
|
# remote
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2016-04-22 17:30:49 +00:00
|
|
|
> Use main process modules from the renderer process.
|
2016-04-21 22:35:29 +00:00
|
|
|
|
2016-11-23 19:20:56 +00:00
|
|
|
Process: [Renderer](../glossary.md#renderer-process)
|
2016-11-03 17:26:00 +00:00
|
|
|
|
2013-12-30 14:06:33 +00:00
|
|
|
The `remote` module provides a simple way to do inter-process communication
|
2015-09-02 02:08:31 +00:00
|
|
|
(IPC) between the renderer process (web page) and the main process.
|
2014-05-10 03:51:25 +00:00
|
|
|
|
2015-11-12 13:20:09 +00:00
|
|
|
In Electron, GUI-related modules (such as `dialog`, `menu` etc.) are only
|
|
|
|
available in the main process, not in the renderer process. In order to use them
|
|
|
|
from the renderer process, the `ipc` module is necessary to send inter-process
|
|
|
|
messages to the main process. With the `remote` module, you can invoke methods
|
|
|
|
of the main process object without explicitly sending inter-process messages,
|
|
|
|
similar to Java's [RMI][rmi]. An example of creating a browser window from a
|
|
|
|
renderer process:
|
2013-08-14 22:43:35 +00:00
|
|
|
|
|
|
|
```javascript
|
2018-09-13 16:10:51 +00:00
|
|
|
const { BrowserWindow } = require('electron').remote
|
|
|
|
let win = new BrowserWindow({ width: 800, height: 600 })
|
2016-07-26 01:39:25 +00:00
|
|
|
win.loadURL('https://github.com')
|
2013-08-14 22:43:35 +00:00
|
|
|
```
|
|
|
|
|
2016-09-21 17:42:53 +00:00
|
|
|
**Note:** For the reverse (access the renderer process from the main process),
|
2018-05-29 08:14:06 +00:00
|
|
|
you can use [webContents.executeJavaScript](web-contents.md#contentsexecutejavascriptcode-usergesture-callback).
|
2015-06-06 11:38:00 +00:00
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
## Remote Objects
|
2013-12-30 14:06:33 +00:00
|
|
|
|
2014-05-10 03:51:25 +00:00
|
|
|
Each object (including functions) returned by the `remote` module represents an
|
2015-03-26 15:20:31 +00:00
|
|
|
object in the main process (we call it a remote object or remote function).
|
2014-05-10 03:51:25 +00:00
|
|
|
When you invoke methods of a remote object, call a remote function, or create
|
2013-12-30 14:06:33 +00:00
|
|
|
a new object with the remote constructor (function), you are actually sending
|
|
|
|
synchronous inter-process messages.
|
|
|
|
|
2017-11-29 11:13:45 +00:00
|
|
|
In the example above, both [`BrowserWindow`](browser-window.md) and `win` were remote objects and
|
2015-09-01 22:30:08 +00:00
|
|
|
`new BrowserWindow` didn't create a `BrowserWindow` object in the renderer
|
|
|
|
process. Instead, it created a `BrowserWindow` object in the main process and
|
|
|
|
returned the corresponding remote object in the renderer process, namely the
|
|
|
|
`win` object.
|
2013-12-30 14:06:33 +00:00
|
|
|
|
2016-09-21 17:42:53 +00:00
|
|
|
**Note:** Only [enumerable properties][enumerable-properties] which are present
|
|
|
|
when the remote object is first referenced are accessible via remote.
|
|
|
|
|
|
|
|
**Note:** Arrays and Buffers are copied over IPC when accessed via the `remote`
|
|
|
|
module. Modifying them in the renderer process does not modify them in the main
|
|
|
|
process and vice versa.
|
2016-01-11 05:02:07 +00:00
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
## Lifetime of Remote Objects
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2015-04-16 03:31:12 +00:00
|
|
|
Electron makes sure that as long as the remote object in the renderer process
|
2013-12-30 14:06:33 +00:00
|
|
|
lives (in other words, has not been garbage collected), the corresponding object
|
2015-09-01 22:30:08 +00:00
|
|
|
in the main process will not be released. When the remote object has been
|
2015-08-29 05:17:35 +00:00
|
|
|
garbage collected, the corresponding object in the main process will be
|
2013-12-30 14:06:33 +00:00
|
|
|
dereferenced.
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
If the remote object is leaked in the renderer process (e.g. stored in a map but
|
|
|
|
never freed), the corresponding object in the main process will also be leaked,
|
2014-05-10 03:51:25 +00:00
|
|
|
so you should be very careful not to leak remote objects.
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2013-12-30 14:06:33 +00:00
|
|
|
Primary value types like strings and numbers, however, are sent by copy.
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2015-03-26 15:20:31 +00:00
|
|
|
## Passing callbacks to the main process
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
Code in the main process can accept callbacks from the renderer - for instance
|
2015-09-01 22:30:08 +00:00
|
|
|
the `remote` module - but you should be extremely careful when using this
|
|
|
|
feature.
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2015-03-26 15:20:31 +00:00
|
|
|
First, in order to avoid deadlocks, the callbacks passed to the main process
|
2015-08-27 16:10:02 +00:00
|
|
|
are called asynchronously. You should not expect the main process to
|
2013-12-30 14:06:33 +00:00
|
|
|
get the return value of the passed callbacks.
|
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
For instance you can't use a function from the renderer process in an
|
|
|
|
`Array.map` called in the main process:
|
2015-08-27 16:10:02 +00:00
|
|
|
|
|
|
|
```javascript
|
|
|
|
// main process mapNumbers.js
|
2016-05-04 17:59:02 +00:00
|
|
|
exports.withRendererCallback = (mapper) => {
|
2016-07-26 01:39:25 +00:00
|
|
|
return [1, 2, 3].map(mapper)
|
|
|
|
}
|
2015-08-27 16:10:02 +00:00
|
|
|
|
2016-05-04 17:59:02 +00:00
|
|
|
exports.withLocalCallback = () => {
|
2016-07-26 01:39:25 +00:00
|
|
|
return [1, 2, 3].map(x => x + 1)
|
|
|
|
}
|
2015-08-29 05:17:35 +00:00
|
|
|
```
|
2015-08-27 16:10:02 +00:00
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
```javascript
|
2015-08-27 16:10:02 +00:00
|
|
|
// renderer process
|
2016-07-26 01:39:25 +00:00
|
|
|
const mapNumbers = require('electron').remote.require('./mapNumbers')
|
|
|
|
const withRendererCb = mapNumbers.withRendererCallback(x => x + 1)
|
|
|
|
const withLocalCb = mapNumbers.withLocalCallback()
|
2015-08-27 16:10:02 +00:00
|
|
|
|
2016-07-26 01:39:25 +00:00
|
|
|
console.log(withRendererCb, withLocalCb)
|
|
|
|
// [undefined, undefined, undefined], [2, 3, 4]
|
2015-08-27 16:10:02 +00:00
|
|
|
```
|
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
As you can see, the renderer callback's synchronous return value was not as
|
|
|
|
expected, and didn't match the return value of an identical callback that lives
|
|
|
|
in the main process.
|
2015-08-27 16:10:02 +00:00
|
|
|
|
|
|
|
Second, the callbacks passed to the main process will persist until the
|
2015-03-26 15:20:31 +00:00
|
|
|
main process garbage-collects them.
|
2013-12-30 14:06:33 +00:00
|
|
|
|
2014-05-10 03:51:25 +00:00
|
|
|
For example, the following code seems innocent at first glance. It installs a
|
2013-12-30 14:06:33 +00:00
|
|
|
callback for the `close` event on a remote object:
|
2013-08-14 22:43:35 +00:00
|
|
|
|
|
|
|
```javascript
|
2016-07-26 01:39:25 +00:00
|
|
|
require('electron').remote.getCurrentWindow().on('close', () => {
|
|
|
|
// window was closed...
|
|
|
|
})
|
2013-08-14 22:43:35 +00:00
|
|
|
```
|
|
|
|
|
2015-08-27 16:10:02 +00:00
|
|
|
But remember the callback is referenced by the main process until you
|
2015-08-29 05:17:35 +00:00
|
|
|
explicitly uninstall it. If you do not, each time you reload your window the
|
|
|
|
callback will be installed again, leaking one callback for each restart.
|
|
|
|
|
2015-09-01 22:30:08 +00:00
|
|
|
To make things worse, since the context of previously installed callbacks has
|
|
|
|
been released, exceptions will be raised in the main process when the `close`
|
2015-09-02 02:08:31 +00:00
|
|
|
event is emitted.
|
2015-08-29 05:17:35 +00:00
|
|
|
|
|
|
|
To avoid this problem, ensure you clean up any references to renderer callbacks
|
|
|
|
passed to the main process. This involves cleaning up event handlers, or
|
2018-01-27 20:34:34 +00:00
|
|
|
ensuring the main process is explicitly told to dereference callbacks that came
|
2015-08-29 05:17:35 +00:00
|
|
|
from a renderer process that is exiting.
|
2015-08-27 16:10:02 +00:00
|
|
|
|
2015-11-13 14:34:00 +00:00
|
|
|
## Accessing built-in modules in the main process
|
|
|
|
|
|
|
|
The built-in modules in the main process are added as getters in the `remote`
|
|
|
|
module, so you can use them directly like the `electron` module.
|
|
|
|
|
|
|
|
```javascript
|
2016-07-26 01:39:25 +00:00
|
|
|
const app = require('electron').remote.app
|
|
|
|
console.log(app)
|
2015-11-13 14:34:00 +00:00
|
|
|
```
|
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
## Methods
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
The `remote` module has the following methods:
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
### `remote.require(module)`
|
2013-08-14 22:43:35 +00:00
|
|
|
|
|
|
|
* `module` String
|
|
|
|
|
2017-03-13 22:48:42 +00:00
|
|
|
Returns `any` - The object returned by `require(module)` in the main process.
|
|
|
|
Modules specified by their relative path will resolve relative to the entrypoint
|
|
|
|
of the main process.
|
2017-03-13 22:42:26 +00:00
|
|
|
|
|
|
|
e.g.
|
|
|
|
|
2017-11-20 06:18:24 +00:00
|
|
|
```sh
|
2017-03-14 00:18:23 +00:00
|
|
|
project/
|
|
|
|
├── main
|
|
|
|
│ ├── foo.js
|
|
|
|
│ └── index.js
|
|
|
|
├── package.json
|
|
|
|
└── renderer
|
|
|
|
└── index.js
|
|
|
|
```
|
|
|
|
|
2017-03-13 22:42:26 +00:00
|
|
|
```js
|
|
|
|
// main process: main/index.js
|
2018-09-13 16:10:51 +00:00
|
|
|
const { app } = require('electron')
|
2017-03-14 17:48:44 +00:00
|
|
|
app.on('ready', () => { /* ... */ })
|
2017-03-13 22:42:26 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
```js
|
|
|
|
// some relative module: main/foo.js
|
|
|
|
module.exports = 'bar'
|
|
|
|
```
|
|
|
|
|
|
|
|
```js
|
|
|
|
// renderer process: renderer/index.js
|
|
|
|
const foo = require('electron').remote.require('./foo') // bar
|
|
|
|
```
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
### `remote.getCurrentWindow()`
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2016-12-19 17:40:07 +00:00
|
|
|
Returns [`BrowserWindow`](browser-window.md) - The window to which this web page
|
2015-08-29 05:17:35 +00:00
|
|
|
belongs.
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2018-06-16 06:21:07 +00:00
|
|
|
**Note:** Do not use `removeAllListeners` on [`BrowserWindow`](browser-window.md).
|
|
|
|
Use of this can remove all [`blur`](https://developer.mozilla.org/en-US/docs/Web/Events/blur)
|
|
|
|
listeners, disable click events on touch bar buttons, and other unintended
|
|
|
|
consequences.
|
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
### `remote.getCurrentWebContents()`
|
2015-05-11 06:05:20 +00:00
|
|
|
|
2016-12-19 17:40:07 +00:00
|
|
|
Returns [`WebContents`](web-contents.md) - The web contents of this web page.
|
2015-05-11 06:05:20 +00:00
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
### `remote.getGlobal(name)`
|
2013-08-14 22:43:35 +00:00
|
|
|
|
|
|
|
* `name` String
|
|
|
|
|
2016-09-24 23:59:30 +00:00
|
|
|
Returns `any` - The global variable of `name` (e.g. `global[name]`) in the main
|
2013-12-30 14:06:33 +00:00
|
|
|
process.
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2016-08-25 17:52:19 +00:00
|
|
|
## Properties
|
|
|
|
|
2015-08-29 05:17:35 +00:00
|
|
|
### `remote.process`
|
2013-08-14 22:43:35 +00:00
|
|
|
|
2016-08-25 17:52:19 +00:00
|
|
|
The `process` object in the main process. This is the same as
|
2015-08-29 05:17:35 +00:00
|
|
|
`remote.getGlobal('process')` but is cached.
|
2015-11-12 13:20:09 +00:00
|
|
|
|
2018-01-12 15:24:48 +00:00
|
|
|
[rmi]: https://en.wikipedia.org/wiki/Java_remote_method_invocation
|
2016-09-21 17:42:53 +00:00
|
|
|
[enumerable-properties]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties
|